Skip to content

Commit

Permalink
Merge pull request #73 from nini22P/dev
Browse files Browse the repository at this point in the history
v1.5.1
  • Loading branch information
nini22P authored Jan 1, 2024
2 parents c2b4460 + 11f62a8 commit c8cb1c7
Show file tree
Hide file tree
Showing 23 changed files with 232 additions and 177 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "omp",
"description": "OneDrive Media Player",
"private": true,
"version": "1.5.0",
"version": "1.5.1",
"scripts": {
"dev": "webpack serve",
"build": "webpack --mode=production --node-env=production",
Expand Down
127 changes: 64 additions & 63 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { AuthenticatedTemplate, UnauthenticatedTemplate } from '@azure/msal-react'
import { Outlet } from 'react-router-dom'
import { Outlet, useLocation } from 'react-router-dom'
import { Container, ThemeProvider, Paper } from '@mui/material'
import Grid from '@mui/material/Unstable_Grid2'
import NavBar from './pages/NavBar'
Expand All @@ -10,15 +9,15 @@ import useUser from './hooks/graph/useUser'
import useTheme from './hooks/ui/useTheme'
import useSync from './hooks/graph/useSync'
import useThemeColor from './hooks/ui/useThemeColor'
import SignIn from './pages/SignIn'
import LogIn from './pages/LogIn'
import useUiStore from './store/useUiStore'
import { useSpring, animated } from '@react-spring/web'
import { useMemo } from 'react'

const App = () => {
const theme = useTheme()
const { accounts } = useUser()
useSync(accounts)
const { account } = useUser()
useSync()
useThemeColor()

const [coverColor] = useUiStore((state) => [state.coverColor])
Expand All @@ -35,6 +34,12 @@ const App = () => {
[coverColor, theme.palette.background.default]
)

const location = useLocation()
const needLogin = useMemo(
() => (['/', '/history'].includes(location.pathname)) && !account,
[location, account]
)

return (
<ThemeProvider theme={theme}>
<animated.div
Expand All @@ -44,69 +49,65 @@ const App = () => {
background: background,
}}
>
<NavBar accounts={accounts} />
<AuthenticatedTemplate>
<Container maxWidth="xl" disableGutters={true} sx={{ height: '100%' }}>
<MobileSideBar />
<Grid container>
<Grid
xs={0}
sm={3}
lg={2}
<NavBar />

<Container maxWidth="xl" disableGutters={true} sx={{ height: '100%' }}>
<MobileSideBar />
<Grid container>
<Grid
xs={0}
sm={3}
lg={2}
sx={{
overflowY: 'auto',
display: { xs: 'none', sm: 'block' },
padding: '0 0 0.5rem 0.5rem',
paddingTop: 'calc(env(titlebar-area-height, 3rem) + 0.5rem)',
height: 'calc(100dvh - 4.5rem - env(titlebar-area-height, 2rem))',
}}
>
<SideBar />
</Grid>
<Grid
xs={12}
sm={9}
lg={10}
sx={{
padding: '0 0.5rem 0.5rem 0.5rem',
paddingTop: {
xs: 'calc(env(titlebar-area-height, 3rem) + 0.5rem)',
sm: 'calc(env(titlebar-area-height, 0rem) + 0.5rem)'
},
height: 'calc(100dvh - 4.5rem - env(titlebar-area-height, 2rem))',
}}
>
<Paper
sx={{
width: '100%',
height: '100%',
overflowY: 'auto',
display: { xs: 'none', sm: 'block' },
padding: '0 0 0.5rem 0.5rem',
paddingTop: 'calc(env(titlebar-area-height, 3rem) + 0.5rem)',
height: 'calc(100dvh - 4.5rem - env(titlebar-area-height, 2rem))',
}}
>
<SideBar />
</Grid>
<Grid
xs={12}
sm={9}
lg={10}
sx={{
padding: '0 0.5rem 0.5rem 0.5rem',
paddingTop: {
xs: 'calc(env(titlebar-area-height, 3rem) + 0.5rem)',
sm: 'calc(env(titlebar-area-height, 0rem) + 0.5rem)'
backgroundColor: `${theme.palette.background.paper}99`, backdropFilter: 'blur(2px)',
'& ::-webkit-scrollbar': {
width: '12px',
height: '12px',
},
'& ::-webkit-scrollbar-track': {
backgroundColor: 'transparent',
},
'& ::-webkit-scrollbar-thumb': {
background: theme.palette.primary.main,
borderRadius: '16px',
border: '3.5px solid transparent',
backgroundClip: 'content-box',
},
height: 'calc(100dvh - 4.5rem - env(titlebar-area-height, 2rem))',
}}
>
<Paper
sx={{
width: '100%',
height: '100%',
overflowY: 'auto',
backgroundColor: `${theme.palette.background.paper}99`, backdropFilter: 'blur(2px)',
'& ::-webkit-scrollbar': {
width: '12px',
height: '12px',
},
'& ::-webkit-scrollbar-track': {
backgroundColor: 'transparent',
},
'& ::-webkit-scrollbar-thumb': {
background: theme.palette.primary.main,
borderRadius: '16px',
border: '3.5px solid transparent',
backgroundClip: 'content-box',
},
}}>
<Outlet />
</Paper>
</Grid>
}}>
{needLogin ? <LogIn /> : <Outlet />}
</Paper>
</Grid>
</Container>
<Player />
</AuthenticatedTemplate>
</Grid>
</Container>

<UnauthenticatedTemplate>
<SignIn />
</UnauthenticatedTemplate>
<Player />

</animated.div>
</ThemeProvider>
Expand Down
19 changes: 13 additions & 6 deletions src/hooks/graph/useFilesData.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { getAppRootFiles, getFile, getFileThumbnails, getFiles, uploadAppRootJson } from '@/graph/graph'
import { loginRequest } from '@/graph/authConfig'
import useUser from './useUser'
import { useMsal } from '@azure/msal-react'

const useFilesData = () => {
const { instance, accounts } = useUser()
const { account } = useUser()
const { instance } = useMsal()

/**
* 获取文件夹数据
* @param path
* @returns
*/
const getFilesData = async (path: string) => {
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: accounts[0] })
await instance.initialize()
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: account })
const response = await getFiles(path, acquireToken.accessToken)
return response.value
}
Expand All @@ -22,7 +25,8 @@ const useFilesData = () => {
* @returns
*/
const getFileData = async (filePath: string) => {
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: accounts[0] })
await instance.initialize()
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: account })
const response = await getFile(filePath, acquireToken.accessToken)
return response
}
Expand All @@ -33,19 +37,22 @@ const useFilesData = () => {
* @returns
*/
const getFileThumbnailsData = async (itemId: string) => {
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: accounts[0] })
await instance.initialize()
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: account })
const response = await getFileThumbnails(itemId, acquireToken.accessToken)
return response
}

const getAppRootFilesData = async (filePath: string) => {
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: accounts[0] })
await instance.initialize()
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: account })
const response = await getAppRootFiles(filePath, acquireToken.accessToken)
return response
}

const uploadAppRootJsonData = async (fileName: string, fileContent: BodyInit) => {
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: accounts[0] })
await instance.initialize()
const acquireToken = await instance.acquireTokenSilent({ ...loginRequest, account: account })
const response = await uploadAppRootJson(fileName, fileContent, acquireToken.accessToken)
return response
}
Expand Down
9 changes: 4 additions & 5 deletions src/hooks/graph/useSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ import useSWR from 'swr'
import usePlaylistsStore from '@/store/usePlaylistsStore'
import useHistoryStore from '@/store/useHistoryStore'
import useFilesData from './useFilesData'
import { AccountInfo } from '@azure/msal-browser'
import { File } from '@/types/file'
import { Playlist } from '@/types/playlist'
import { fetchJson } from '@/utils'
import useUser from './useUser'

const useSync = (accounts: AccountInfo[]) => {
const useSync = () => {
const { account } = useUser()
const [historyList, updateHistoryList] = useHistoryStore((state) => [state.historyList, state.updateHistoryList])
const [playlists, updatePlaylists] = usePlaylistsStore((state) => [state.playlists, state.updatePlaylists])
const { getAppRootFilesData, uploadAppRootJsonData } = useFilesData()

const isLoggedIn = accounts.length > 0

// 自动从 OneDrive 获取应用数据
const appDatafetcher = async () => {
const appRootFiles = await getAppRootFilesData('/')
Expand All @@ -36,7 +35,7 @@ const useSync = (accounts: AccountInfo[]) => {
}
}

const { data, error, isLoading } = useSWR<{ history: File[], playlists: Playlist[] }>(isLoggedIn ? 'fetchAppData' : null, appDatafetcher)
const { data, error, isLoading } = useSWR<{ history: File[], playlists: Playlist[] }>(account ? 'fetchAppData' : null, appDatafetcher)

// 自动更新播放历史
useMemo(
Expand Down
8 changes: 6 additions & 2 deletions src/hooks/graph/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useMsal } from '@azure/msal-react'
import { loginRequest } from '@/graph/authConfig'
import usePlayQueueStore from '@/store/usePlayQueueStore'
import useUiStore from '@/store/useUiStore'
import { AccountInfo } from '@azure/msal-browser'

const useUser = () => {
const { instance, accounts } = useMsal()
Expand All @@ -19,11 +20,14 @@ const useUser = () => {
usePlayQueueStore.persist.clearStorage()
useUiStore.persist.clearStorage()
instance.logoutRedirect({
postLogoutRedirectUri: '/'
postLogoutRedirectUri: '/',
})
location.reload()
}

return { instance, accounts, login, logout }
const account: AccountInfo | null = accounts[0] || null

return { account, login, logout }
}

export default useUser
4 changes: 2 additions & 2 deletions src/hooks/player/usePlayerCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,14 @@ const usePlayerCore = (player: HTMLVideoElement | null) => {

if (!metaData) {
const currentMetaData = playQueue.filter(item => item.index === currentIndex)[0]
updateCover('./cover.svg')
updateCurrentMetaData(
{
title: currentMetaData?.fileName || 'Not playing',
artist: '',
path: currentMetaData?.filePath,
}
)
updateCover('./cover.webp')
}

if (
Expand All @@ -235,7 +235,7 @@ const usePlayerCore = (player: HTMLVideoElement | null) => {
updateCover(URL.createObjectURL(new Blob([new Uint8Array(cover as ArrayBufferLike)], { type: 'image/png' })))
}
} else {
updateCover('./cover.webp')
updateCover('./cover.svg')
}
}
}
Expand Down
58 changes: 47 additions & 11 deletions src/hooks/ui/useTheme.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,59 @@
import usePlayerStore from '@/store/usePlayerStore'
import useUiStore from '@/store/useUiStore'
import { createTheme, useMediaQuery } from '@mui/material'
import { useEffect, useMemo } from 'react'
import { extractColors } from 'extract-colors'
import { useMemo } from 'react'

const useTheme = () => {
const [coverColor, CoverThemeColor, colorMode] = useUiStore(state => [state.coverColor, state.CoverThemeColor, state.colorMode])
const [
coverColor,
CoverThemeColor,
colorMode,
updateCoverColor,
] = useUiStore(
state => [
state.coverColor,
state.CoverThemeColor,
state.colorMode,
state.updateCoverColor,
]
)

const [cover] = usePlayerStore((state) => [state.cover])

useEffect(() => {
if (colorMode === 'dark' || colorMode === 'light')
document.documentElement.setAttribute('data-theme', colorMode)
if (colorMode === 'auto')
document.documentElement.removeAttribute('data-theme')
return () => {
document.documentElement.removeAttribute('data-theme')
}
}, [colorMode])
useMemo(
() => {
if (colorMode === 'dark' || colorMode === 'light')
document.documentElement.setAttribute('data-theme', colorMode)
if (colorMode === 'auto')
document.documentElement.removeAttribute('data-theme')
return () => {
document.documentElement.removeAttribute('data-theme')
}
},
[colorMode]
)

const prefersColorSchemeDark = useMediaQuery('(prefers-color-scheme: dark)')
const prefersDarkMode = colorMode === 'light' ? false : prefersColorSchemeDark || colorMode === 'dark'

// 从专辑封面提取颜色
useMemo(
async () => {
if (cover !== './cover.svg') {
const colors = await extractColors(cover)
const lightColors = colors.filter(color => color.lightness < 0.7)
const darkColors = colors.filter(color => color.lightness > 0.5)
if (prefersDarkMode && darkColors.length > 0)
updateCoverColor(darkColors[0].hex)
else if (!prefersDarkMode && lightColors.length > 0)
updateCoverColor(lightColors[0].hex)
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[cover, prefersDarkMode]
)

const colors = {
primary: CoverThemeColor ? coverColor : prefersDarkMode ? '#df7ef9' : '#8e24aa',
}
Expand Down
Loading

0 comments on commit c8cb1c7

Please sign in to comment.