Skip to content

Commit

Permalink
feat: recent listened songs
Browse files Browse the repository at this point in the history
  • Loading branch information
Sherlockouo committed Jan 17, 2024
1 parent 7f1cb4f commit 2989590
Show file tree
Hide file tree
Showing 12 changed files with 10,605 additions and 12,413 deletions.
2 changes: 1 addition & 1 deletion packages/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@sentry/electron": "^3.0.7",
"@tanstack/react-query": "^4.26.1",
"NeteaseCloudMusicApi": "^4.13.2",
"better-sqlite3": "8.5.0",
"better-sqlite3": "9.2.2",
"change-case": "^4.1.2",
"compare-versions": "^4.1.3",
"electron-log": "^4.4.8",
Expand Down
50 changes: 25 additions & 25 deletions packages/desktop/scripts/build.sqlite3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,31 @@ if (!fs.existsSync(binDir)) {
}

// Get Electron Module Version
let electronModuleVersion = '118'
// async function getElectronModuleVersion() {
// const releases = await axios({
// method: 'get',
// url: 'https://releases.electronjs.org/releases.json',
// headers: {
// Connection: 'keep-alive',
// Cookie:
// '_ga=GA1.2.1440531065.1691594509; _ga_7GG8HKLCLE=GS1.2.1695203360.15.0.1695203360.0.0.0',
// 'User-Agent':
// 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
// },
// setTimeout: 120000,
// })
// if (!releases.data) {
// console.error(pc.red('Can not get electron releases'))
// process.exit(1)
// }
// electronModuleVersion = releases.data.find(r => r.version.includes(electronVersion))?.modules
// if (!electronModuleVersion) {
// console.error(pc.red('Can not find electron module version in electron-releases'))
// process.exit(1)
// }
// console.log(pc.cyan(`electronModuleVersion=${electronModuleVersion}`))
// }
let electronModuleVersion = ''
async function getElectronModuleVersion() {
const releases = await axios({
method: 'get',
url: 'https://releases.electronjs.org/releases.json',
headers: {
Connection: 'keep-alive',
Cookie:
'_ga=GA1.2.1440531065.1691594509; _ga_7GG8HKLCLE=GS1.2.1695203360.15.0.1695203360.0.0.0',
'User-Agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
},
setTimeout: 120000,
})
if (!releases.data) {
console.error(pc.red('Can not get electron releases'))
process.exit(1)
}
electronModuleVersion = releases.data.find(r => r.version.includes(electronVersion))?.modules
if (!electronModuleVersion) {
console.error(pc.red('Can not find electron module version in electron-releases'))
process.exit(1)
}
console.log(pc.cyan(`electronModuleVersion=${electronModuleVersion}`))
}

// Download better-sqlite library from GitHub Release
async function download(arch: Arch) {
Expand Down
2 changes: 1 addition & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@unblockneteasemusic/server": "^0.27.3",
"NeteaseCloudMusicApi": "^4.13.2",
"axios": "^0.27.2",
"better-sqlite3": "8.5.0",
"better-sqlite3": "9.2.2",
"change-case": "^4.1.2",
"compare-versions": "^4.1.3",
"fastify": "^4.5.3",
Expand Down
13 changes: 13 additions & 0 deletions packages/shared/api/Playlists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum PlaylistApiNames {
LikeAPlaylist = 'likeAPlaylist',
FetchTopPlaylistParams = 'fetchTopPlaylist',
FetchHQPlaylistParams = 'fetchHQPlaylist',
FetchFetchRecentSongs = 'fetchFetchRecentSongs'
}

// top playlist
Expand Down Expand Up @@ -66,6 +67,18 @@ export interface FetchRecommendedPlaylistsResponse {
result: Playlist[]
}

export interface FetchRecentSongsParams {
limit?: number
}

export interface FetchRecentSongsResponse {
code: number
data: {
total:number
list:RecentSongs[]
}
}

// 每日推荐歌曲(需要登录)
export interface FetchDailyRecommendSongsResponse {
code: number
Expand Down
9 changes: 9 additions & 0 deletions packages/shared/interface.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ declare interface Playlist {
videos?: null
}

declare interface RecentSongs {
resourceId: string
playTime:number
resouceType:string
data:Track
banned: boolean
multiTerminalInfo:null
}

declare interface Track {
id: number
a: null
Expand Down
13 changes: 13 additions & 0 deletions packages/web/api/playlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
FetchDailyRecommendSongsResponse,
AddSongToPlayListParams,
AddSongToPlayListResponse,
FetchRecentSongsResponse,
FetchRecentSongsParams,
} from '@/shared/api/Playlists'

// hq 歌单
Expand Down Expand Up @@ -66,6 +68,17 @@ export function fetchRecommendedPlaylists(
})
}

// 听歌历史
export function fetchFetchRecentSongs(
params: FetchRecentSongsParams
): Promise<FetchRecentSongsResponse> {
return request({
url: '/record/recent/song',
method: 'get',
params,
})
}

// 每日推荐歌单(需要登录)
export function fetchDailyRecommendPlaylists(): Promise<FetchDailyRecommendPlaylistsResponse> {
return request({
Expand Down
1 change: 1 addition & 0 deletions packages/web/i18n/locales/en-us.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"common": {
"recent":"Recent",
"artist_one": "Artist",
"daily": "Daily",
"artist_other": "Artists",
Expand Down
1 change: 1 addition & 0 deletions packages/web/i18n/locales/zh-cn.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"common": {
"recent":"最近播放",
"album_one": "专辑",
"album_other": "专辑",
"daily": "日推",
Expand Down
10 changes: 9 additions & 1 deletion packages/web/pages/My/Collections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import Icon from '@/web/components/Icon'
import FileUploader from '@/web/components/Tools/Upload'
import CoverWall from '@/web/components/CoverWall'
import { IconNames } from '@/web/components/Icon/iconNamesType'
import Recent from './Recent'

const collections = ['daily', 'playlists', 'albums', 'artists', 'videos', 'cloud'] as const
const collections = ['daily', 'playlists', 'albums', 'artists', 'videos', 'cloud','recent'] as const
type Collection = typeof collections[number]

const Albums = () => {
Expand Down Expand Up @@ -112,6 +113,12 @@ const CollectionTabs = ({ className }: { className:string }) => {
name: t`common.cloud`,
// iconName: 'cloud',
},
{
id: 'recent',
name: t`common.recent`,
// iconName: 'cloud',
},

]

const { librarySelectedTab: selectedTab } = useSnapshot(persistedUiStates)
Expand Down Expand Up @@ -160,6 +167,7 @@ const Collections = () => {
{selectedTab === 'artists' && <Artists />}
{selectedTab === 'videos' && <Videos />}
{selectedTab === 'cloud' && <Cloud key={"cloud"}/>}
{selectedTab === 'recent' && <Recent key={"recent"}/>}
</div>
</motion.div>
)
Expand Down
105 changes: 105 additions & 0 deletions packages/web/pages/My/Recent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { useEffect, useRef, useState } from 'react'
import useArtistSongs from '@/web/api/hooks/useArtistSongs'
import useTracks from '@/web/api/hooks/useTracks'
import { FetchArtistSongsParams } from '@/shared/api/Artist'
import TrackList from '../../components/TrackList/TrackListVirtual'
import player from '@/web/states/player'
import { useParams } from 'react-router-dom'
import ScrollPagination from '@/web/components/ScrollPage'
import { fetchArtistSongs } from '@/web/api/artist'
import { fetchTracks } from '@/web/api/track'
import toast from 'react-hot-toast'
import { CloudDiskInfoParam } from '@/shared/api/User'
import { cloudDisk } from '@/web/api/user'
import { motion } from 'framer-motion'
import Track from '@/web/components/TrackList/Track'
import { openContextMenu } from '@/web/states/contextMenus'
import { useSnapshot } from 'valtio'
import useIntersectionObserver from '@/web/hooks/useIntersectionObserver'
import { useThrottle } from 'react-use'
import { has, throttle } from 'lodash-es'
import Loading from '@/web/components/Animation/Loading'
import { cx } from '@emotion/css'
import { fetchFetchRecentSongs } from '@/web/api/playlist'
import { FetchRecentSongsParams } from '@/shared/api/Playlists'

const reactQueryOptions = {
refetchOnWindowFocus: false,
refetchInterval: 1000 * 60 * 60, // 1 hour
refetchOnMount: false,
}

const Recent = () => {
const {trackID, state} = useSnapshot(player)
const [dataSource, setDatasource] = useState<Track[]>([])
const [songIDs, setSongIDs] = useState<number[]>([])
const [hasMore, setHasMore] = useState(true)
const [currentPage, setCurrentPage] = useState(1)
const observePoint = useRef<HTMLDivElement | null>(null)
const { onScreen: isScrollReachBottom } = useIntersectionObserver(observePoint)
const getData = async (pageNo: number, pageSize: number) => {
if (hasMore === false) return
const cloudParams: FetchRecentSongsParams = {
limit: pageNo * pageSize || 50,
}
const resp = await fetchFetchRecentSongs(cloudParams)

setHasMore(dataSource.length < resp.data.total)

const recentSongs = resp.data ? resp.data.list.map((song: RecentSongs) => song.data) : []

setDatasource(recentSongs)

return { hasMore: dataSource.length < resp.data.total }
}
const getDataThrottle = throttle((pageNo: number, pageSize: number)=>{
console.log('page ',pageNo);

getData(pageNo,pageSize)
},1000)

useEffect(()=>{
if(isScrollReachBottom && hasMore){
setCurrentPage(currentPage + 1)
getDataThrottle(currentPage,50)
}
},[isScrollReachBottom])

const onPlay = (trackID: number | null = null) => {
player.playAList(songIDs, trackID)
}

const handleClick = (e: React.MouseEvent<HTMLElement>, trackID: number) => {
if (e.type === 'contextmenu') {
e.preventDefault()
openContextMenu({
event: e,
type: 'track',
dataSourceID: trackID,
options: {
useCursorPosition: true,
},
})
return
}

if (e.detail === 2) onPlay?.(trackID)
}
return (
<motion.div className={cx('min-h-screen')}>
{(dataSource)?.map((track,index)=>{
return <Track
key={index}
track={track}
index={index}
playingTrackID={trackID || 0}
state={state}
handleClick={handleClick} />
})
}
<div ref={observePoint} className='flex justify-center'>{hasMore && <Loading />}</div>
</motion.div>
)
}

export default Recent
2 changes: 1 addition & 1 deletion packages/web/states/persistedUiStates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface PersistedUiStates {
loginPhoneCountryCode: string
loginType: 'phone' | 'email' | 'qrCode'
minimizePlayer: boolean
librarySelectedTab: 'daily' | 'playlists' | 'albums' | 'artists' | 'videos' | 'cloud'
librarySelectedTab: 'daily' | 'playlists' | 'albums' | 'artists' | 'videos' | 'cloud' | 'recent'
}

const initPersistedUiStates: PersistedUiStates = {
Expand Down
Loading

0 comments on commit 2989590

Please sign in to comment.