Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
website: Add simple Now Playing section
- Loading branch information
1 parent
5262c61
commit f5b9aed
Showing
5 changed files
with
214 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import * as React from 'react'; | ||
import {deepObserve} from 'mobx-utils'; | ||
|
||
import store from 'src/shared/store'; | ||
|
||
type Options = { | ||
/** | ||
* The paths in the device object ot watch for activity. | ||
*/ | ||
targetTest: (path: string) => boolean; | ||
/** | ||
* A function used to test weather the value constitutes an activity blip. | ||
*/ | ||
valueTest?: (value: any) => boolean; | ||
/** | ||
* Number of milliseconds to blip when there is target activity. Defaults to | ||
* 300ms. | ||
*/ | ||
blipTime?: number; | ||
}; | ||
|
||
function useStoreActivity({targetTest, valueTest, blipTime}: Options) { | ||
const [blip, setBlip] = React.useState<boolean>(false); | ||
let timeoutId = 0; | ||
|
||
React.useEffect(() => | ||
deepObserve(store, (change: any, changePath) => { | ||
const nameSuffix = change.name !== undefined ? `/${change.name}` : ''; | ||
|
||
const path = changePath.includes('/') | ||
? `${changePath.replace(/[0-9]+\//, '')}${nameSuffix}` | ||
: change.name; | ||
|
||
if (!targetTest(path)) { | ||
return; | ||
} | ||
|
||
if (valueTest !== undefined && !valueTest(change.newValue)) { | ||
return; | ||
} | ||
|
||
setBlip(true); | ||
clearInterval(timeoutId); | ||
setTimeout(() => setBlip(false), blipTime ?? 300); | ||
}) | ||
); | ||
|
||
return [blip]; | ||
} | ||
|
||
export default useStoreActivity; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import * as React from 'react'; | ||
import {motion} from 'framer-motion'; | ||
import styled from '@emotion/styled'; | ||
|
||
import useStoreActivity from 'src/utils/useStoreActivity'; | ||
|
||
type Props = React.ComponentProps<typeof motion.div>; | ||
|
||
const ActivityLink = (props: Props) => { | ||
const [blip] = useStoreActivity({ | ||
targetTest: path => path === 'mixstatus/trackHistory', | ||
blipTime: 1000, | ||
}); | ||
|
||
const makeAnimate = (baseColor: string) => | ||
blip | ||
? {color: '#F84B4B', transition: {duration: 0.1}} | ||
: {color: baseColor, transition: {duration: 3}}; | ||
|
||
return ( | ||
<Container {...props}> | ||
<motion.div | ||
style={{clipPath: 'inset(0 0 60px 0)'}} | ||
animate={makeAnimate('#71696C')} | ||
> | ||
<Graphic /> | ||
</motion.div> | ||
<motion.div | ||
style={{clipPath: 'inset(152px 0 0 0)'}} | ||
animate={makeAnimate('#E5E1E2')} | ||
> | ||
<Graphic /> | ||
</motion.div> | ||
</Container> | ||
); | ||
}; | ||
|
||
export default ActivityLink; | ||
|
||
const Graphic = (p: React.SVGProps<SVGSVGElement>) => ( | ||
<svg | ||
width="1268" | ||
height="212" | ||
viewBox="0 0 1268 212" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
{...p} | ||
> | ||
<circle cx="109" cy="205" r="6" stroke="currentColor" strokeWidth="2" /> | ||
<path | ||
d="M918 18V87.7579C918 98.8036 909.049 107.758 898.004 107.758C896.051 107.758 893.965 107.758 891.751 107.758C770.542 107.758 265.307 107.758 134.199 107.758C132.394 107.758 130.66 107.758 128.999 107.758C117.954 107.758 109 116.719 109 127.764C109 164.411 109 192 109 192" | ||
stroke="currentColor" | ||
strokeWidth="2" | ||
strokeLinejoin="round" | ||
strokeDasharray="5 3" | ||
/> | ||
<circle cx="918" cy="7" r="6" stroke="currentColor" strokeWidth="2" /> | ||
</svg> | ||
); | ||
|
||
const Container = styled(motion.div)` | ||
height: 212px; | ||
display: grid; | ||
justify-content: center; | ||
margin-top: -180px; | ||
margin-bottom: -60px; | ||
position: relative; | ||
@media only screen and (max-width: 1200px) { | ||
display: none; | ||
} | ||
> div { | ||
grid-column: 1; | ||
grid-row: 1; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import {observer} from 'mobx-react'; | ||
import * as React from 'react'; | ||
|
||
import {registeredOverlays} from 'src/overlay'; | ||
import store from 'src/shared/store'; | ||
|
||
export const ExampleOverlay = observer(() => { | ||
const instance = store.config.overlays.find(i => i.key === 'exampleNowPlaying'); | ||
const descriptor = registeredOverlays?.find(overlay => overlay.type === instance?.type); | ||
|
||
if (instance === undefined || descriptor === undefined) { | ||
// Show something silly if they removed the overlay | ||
return null; | ||
} | ||
|
||
return <descriptor.component config={instance.config} />; | ||
}); | ||
|
||
export const ExampleConfig = observer(() => { | ||
const instance = store.config.overlays.find(i => i.key === 'exampleNowPlaying'); | ||
const descriptor = registeredOverlays?.find(overlay => overlay.type === instance?.type); | ||
|
||
if (instance === undefined || descriptor === undefined) { | ||
// Show something silly if they removed the overlay | ||
return null; | ||
} | ||
|
||
return <descriptor.configInterface config={instance.config} />; | ||
}); |
f5b9aed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: