feat: updates

This commit is contained in:
qier222 2022-04-02 02:12:15 +08:00
parent 719a3a60d4
commit 86f088e5c9
No known key found for this signature in database
GPG Key ID: 9C85007ED905F14D
9 changed files with 87 additions and 69 deletions

View File

@ -14,7 +14,8 @@
"dev:renderer": "vite dev",
"build:main": "node scripts/build.main.mjs",
"build:renderer": "vite build",
"build": "npm run typecheck && npm run build:renderer && npm run build:main && electron-builder --config .electron-builder.config.js --dir",
"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-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",
"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\"",
"eslint": "eslint --ext .ts,.js ./",

View File

@ -57,7 +57,7 @@ const PlayingTrack = () => {
</div>
</div>
<IconButton onClick={() => toast('Work in progress')}>
<IconButton onClick={() => toast('施工中...')}>
<SvgIcon
className='h-6 w-6 text-black dark:text-white'
name='heart-outline'
@ -115,23 +115,30 @@ const Others = () => {
const playerSnapshot = useSnapshot(player)
const mode = useMemo(() => playerSnapshot.mode, [playerSnapshot.mode])
const isFM = () => mode === PlayerMode.FM
return (
<div className='flex items-center justify-end gap-2 pr-2 text-black dark:text-white'>
<IconButton onClick={() => toast('Work in progress')} disabled={isFM()}>
<IconButton
onClick={() => toast('Work in progress')}
disabled={mode === PlayerMode.FM}
>
<SvgIcon className='h-6 w-6' name='playlist' />
</IconButton>
<IconButton onClick={() => toast('Work in progress')} disabled={isFM()}>
<IconButton
onClick={() => toast('施工中...')}
disabled={mode === PlayerMode.FM}
>
<SvgIcon className='h-6 w-6' name='repeat' />
</IconButton>
<IconButton onClick={() => toast('Work in progress')} disabled={isFM()}>
<IconButton
onClick={() => toast('施工中...')}
disabled={mode === PlayerMode.FM}
>
<SvgIcon className='h-6 w-6' name='shuffle' />
</IconButton>
<IconButton onClick={() => toast('Work in progress')}>
<IconButton onClick={() => toast('施工中...')}>
<SvgIcon className='h-6 w-6' name='volume' />
</IconButton>
<IconButton onClick={() => toast('Work in progress')}>
<IconButton onClick={() => toast('施工中...')}>
<SvgIcon className='h-6 w-6' name='lyrics' />
</IconButton>
</div>

View File

@ -68,7 +68,10 @@ const SearchBox = () => {
const Settings = () => {
return (
<div className='app-region-no-drag btn-hover-animation rounded-lg p-2.5 text-gray-500 transition duration-300 after:rounded-full after:bg-black/[.06] hover:text-gray-900 dark:text-gray-300 dark:after:bg-white/10 dark:hover:text-gray-200'>
<div
onClick={() => toast('施工中...')}
className='app-region-no-drag btn-hover-animation rounded-lg p-2.5 text-gray-500 transition duration-300 after:rounded-full after:bg-black/[.06] hover:text-gray-900 dark:text-gray-300 dark:after:bg-white/10 dark:hover:text-gray-200'
>
<SvgIcon className='h-[1.125rem] w-[1.125rem]' name='settings' />
</div>
)
@ -78,20 +81,27 @@ const Avatar = () => {
const navigate = useNavigate()
const { data: user } = useUser()
const avatarUrl = resizeImage(user?.profile?.avatarUrl ?? '', 'sm')
const avatarUrl = user?.profile?.avatarUrl
? resizeImage(user?.profile?.avatarUrl ?? '', 'sm')
: ''
return (
<img
src={avatarUrl}
onClick={() => navigate('/login')}
className='app-region-no-drag h-9 w-9 rounded-full bg-gray-100 dark:bg-gray-700'
/>
// <div onClick={() => navigate('/login')}>
// <SvgIcon
// name='user'
// className='h-9 w-9 rounded-full bg-gray-400/10 p-1 text-gray-400'
// />
// </div>
<>
{avatarUrl ? (
<img
src={avatarUrl}
onClick={() => navigate('/login')}
className='app-region-no-drag h-9 w-9 rounded-full bg-gray-100 dark:bg-gray-700'
/>
) : (
<div onClick={() => navigate('/login')}>
<SvgIcon
name='user'
className='h-9 w-9 rounded-full bg-black/[.06] p-1 text-gray-500'
/>
</div>
)}
</>
)
}

View File

@ -191,7 +191,7 @@ const Header = ({
color={ButtonColor.Gray}
iconColor={ButtonColor.Gray}
isSkelton={isLoading}
onClick={() => toast('Work in progress')}
onClick={() => toast('施工中...')}
>
<SvgIcon name='heart-outline' className='h-6 w-6' />
</Button>
@ -200,7 +200,7 @@ const Header = ({
color={ButtonColor.Gray}
iconColor={ButtonColor.Gray}
isSkelton={isLoading}
onClick={() => toast('Work in progress')}
onClick={() => toast('施工中...')}
>
<SvgIcon name='more' className='h-6 w-6' />
</Button>

View File

@ -8,6 +8,21 @@ import DailyTracksCard from '@/components/DailyTracksCard'
import FMCard from '@/components/FMCard'
export default function Home() {
const {
data: dailyRecommendPlaylists,
isLoading: isLoadingDailyRecommendPlaylists,
} = useQuery(
PlaylistApiNames.FETCH_DAILY_RECOMMEND_PLAYLISTS,
fetchDailyRecommendPlaylists,
{
retry: false,
placeholderData: () =>
window.ipcRenderer?.sendSync('getApiCacheSync', {
api: 'recommend/resource',
}),
}
)
const {
data: recommendedPlaylists,
isLoading: isLoadingRecommendedPlaylists,
@ -24,20 +39,6 @@ export default function Home() {
}
)
const {
data: dailyRecommendPlaylists,
isLoading: isLoadingDailyRecommendPlaylists,
} = useQuery(
PlaylistApiNames.FETCH_DAILY_RECOMMEND_PLAYLISTS,
fetchDailyRecommendPlaylists,
{
placeholderData: () =>
window.ipcRenderer?.sendSync('getApiCacheSync', {
api: 'recommend/resource',
}),
}
)
const playlists = [
...(dailyRecommendPlaylists?.recommend ?? []),
...(recommendedPlaylists?.result ?? []),

View File

@ -28,7 +28,7 @@ const EmailInput = ({
return (
<div className='w-full'>
<div className='mb-1 text-sm font-medium text-gray-700 dark:text-gray-300'>
Email
</div>
<input
value={email}
@ -54,7 +54,7 @@ const PhoneInput = ({
return (
<div className='w-full'>
<div className='mb-1 text-sm font-medium text-gray-700 dark:text-gray-300'>
Phone
</div>
<div className='flex w-full'>
<input
@ -91,7 +91,7 @@ const PasswordInput = ({
return (
<div className='mt-3 flex w-full flex-col'>
<div className='mb-1 text-sm font-medium text-gray-700 dark:text-gray-300'>
Password
</div>
<div className='flex w-full'>
<input
@ -135,7 +135,7 @@ const LoginButton = ({
'bg-brand-100 text-brand-300 dark:bg-brand-700 dark:text-white/50'
)}
>
Login
</button>
)
}
@ -153,15 +153,15 @@ const OtherLoginMethods = ({
}[] = [
{
id: Method.QRCODE,
name: 'QR Code',
name: '二维码',
},
{
id: Method.EMAIL,
name: 'Email',
name: '邮箱',
},
{
id: Method.PHONE,
name: 'Phone',
name: '手机',
},
]
return (
@ -178,7 +178,7 @@ const OtherLoginMethods = ({
<button
key={id}
onClick={() => setMethod(id)}
className='flex w-full cursor-default items-center justify-center rounded-lg bg-gray-100 py-2 font-medium text-gray-600 transition duration-300 hover:bg-gray-200 hover:text-gray-800 dark:bg-gray-600 dark:text-gray-200 dark:hover:bg-gray-500 dark:hover:text-gray-100'
className='flex w-full cursor-default items-center justify-center rounded-lg bg-gray-100 py-2 text-gray-600 transition duration-300 hover:bg-gray-200 hover:text-gray-800 dark:bg-gray-600 dark:text-gray-200 dark:hover:bg-gray-500 dark:hover:text-gray-100'
>
<SvgIcon className='mr-2 h-5 w-5' name={id} />
<span>{name}</span>
@ -312,7 +312,7 @@ const LoginWithPhone = () => {
// Login with QRCode
const LoginWithQRCode = () => {
const [qrCodeMessage, setQrCodeMessage] = useState('扫码登录')
const [qrCodeMessage, setQrCodeMessage] = useState('打开网易云音乐,扫码登录')
const [qrCodeImage, setQrCodeImage] = useState('')
const navigate = useNavigate()
@ -344,7 +344,7 @@ const LoginWithQRCode = () => {
refetchKey()
break
case 801:
setQrCodeMessage('等待扫码')
setQrCodeMessage('打开网易云音乐,扫码登录')
break
case 802:
setQrCodeMessage('等待确认')

View File

@ -118,7 +118,7 @@ const Header = memo(
color={ButtonColor.Gray}
iconColor={ButtonColor.Gray}
isSkelton={isLoading}
onClick={() => toast('Work in progress')}
onClick={() => toast('施工中...')}
>
<SvgIcon name='heart-outline' className='h-6 w-6' />
</Button>
@ -127,7 +127,7 @@ const Header = memo(
color={ButtonColor.Gray}
iconColor={ButtonColor.Gray}
isSkelton={isLoading}
onClick={() => toast('Work in progress')}
onClick={() => toast('施工中...')}
>
<SvgIcon name='more' className='h-6 w-6' />
</Button>

View File

@ -157,7 +157,10 @@ export class Player {
*/
private async _fetchAudioSource(trackID: TrackID) {
const response = await fetchAudioSourceWithReactQuery({ id: trackID })
if (response.data?.[0]?.url) return response.data[0].url
return {
audio: response.data?.[0]?.url,
id: trackID,
}
}
/**
@ -174,14 +177,14 @@ export class Player {
* Play audio via howler
*/
private async _playAudio() {
const audio = await this._fetchAudioSource(this.trackID)
const { audio, id } = await this._fetchAudioSource(this.trackID)
if (!audio) {
toast('Failed to load audio source')
return
}
Howler.unload()
const howler = new Howl({
src: [audio],
src: [`${audio}?id=${id}`],
format: ['mp3', 'flac'],
html5: true,
autoplay: true,
@ -191,8 +194,9 @@ export class Player {
_howler = howler
this.play()
this.state = State.PLAYING
this._cacheAudio(this.trackID, audio)
_howler.once('load', () => {
this._cacheAudio(_howler._src)
})
if (!this._progressInterval) {
this._setupProgressInterval()
@ -209,8 +213,10 @@ export class Player {
}
}
private _cacheAudio(id: number, audio: string) {
private _cacheAudio(audio: string) {
if (audio.includes('yesplaymusic')) return
const id = Number(audio.split('?id=')[1])
if (isNaN(id) || !id) return
cacheAudio(id, audio)
}
@ -242,18 +248,13 @@ export class Player {
play(fade: boolean = false) {
if (_howler.playing()) return
const setPlayState = () => {
this.state = State.PLAYING
}
_howler.play()
if (fade) {
_howler.once('play', () => {
_howler.fade(0, this._volume, PLAY_PAUSE_FADE_DURATION)
setPlayState()
})
} else {
setPlayState()
this.state = State.PLAYING
}
}
@ -262,18 +263,15 @@ export class Player {
* @param {boolean} fade fade out
*/
pause(fade: boolean = false) {
const setPauseState = () => {
_howler.pause()
this.state = State.PAUSED
}
if (fade) {
_howler.fade(this._volume, 0, PLAY_PAUSE_FADE_DURATION)
this.state = State.PAUSED
_howler.once('fade', () => {
setPauseState()
_howler.pause()
})
} else {
setPauseState()
this.state = State.PAUSED
_howler.pause()
}
}

View File

@ -42,6 +42,7 @@ export default defineConfig({
],
base: './',
build: {
target: process.env.IS_ELECTRON ? 'esnext' : 'modules',
sourcemap: process.env.NODE_ENV === 'debug',
outDir: '../../dist/renderer',
emptyOutDir: true,