Skip to content

Commit

Permalink
website: Add simple Now Playing section
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser committed Nov 23, 2020
1 parent 5262c61 commit f5b9aed
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/overlay/overlays/nowPlaying/index.tsx
Expand Up @@ -111,7 +111,7 @@ const ConfigInterface: React.FC<{config: NowPlayingConfig}> = observer(({config}
noCenter
size="lg"
name="Overlay Theme"
description="Choose from a variety of different look and feels for the metadata."
description="Choose from various different looks and feels."
>
<Select
value={{value: config.theme, ...themes[config.theme]}}
Expand Down
51 changes: 51 additions & 0 deletions src/utils/useStoreActivity.tsx
@@ -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;
60 changes: 56 additions & 4 deletions src/website/Landing.tsx
Expand Up @@ -8,6 +8,8 @@ import Application from 'src/renderer/views/Application';
import Title from './components/Title';
import DownloadCta from './components/DownloadCta';
import playingTracks from './demo/playingTracks';
import ActivityLink from './components/ActivityLink';
import {ExampleOverlay, ExampleConfig} from './components/OverlayExamples';

const animateInfo: Variants = {
initial: {
Expand All @@ -24,7 +26,7 @@ const Landing = () => (
<React.Fragment>
<Global styles={globalCss} />

<HeroLanding
<Masthead
initial="initial"
animate="animate"
variants={{animate: {transition: {delayChildren: 0.2, staggerChildren: 0.15}}}}
Expand Down Expand Up @@ -52,19 +54,33 @@ const Landing = () => (
</DemoContainer>
</Demo>
</Spotlight>
</HeroLanding>
</Masthead>

<ActivityLink transition={{delay: 2}} initial={{opacity: 0}} animate={{opacity: 1}} />

<OverlaysSection>
<ExampleContent>
<NowPlayingContainer>
<ExampleOverlay />
</NowPlayingContainer>
<ConfigContainer>
<ExampleConfig />
</ConfigContainer>
</ExampleContent>
<OverlayInfo></OverlayInfo>
</OverlaysSection>
</React.Fragment>
);

const HeroLanding = styled(motion.section)`
const Masthead = styled(motion.section)`
display: grid;
grid-template-columns: 0.85fr 1fr;
grid-gap: 2rem;
padding: var(--padding) 0;
overflow: hidden;
height: 100vh;
max-height: 800px;
align-items: center;
padding: var(--padding) 0;
--padding: 4rem;
Expand Down Expand Up @@ -199,4 +215,40 @@ Demo.defaultProps = {
},
};

const OverlaysSection = styled('section')`
display: flex;
flex-direction: column;
align-items: center;
background: #38373d;
margin-bottom: 30rem;
max-height: 330px;
`;

const ExampleContent = styled('div')`
width: 100%;
height: 400px;
max-width: 1264px;
display: grid;
grid-template-columns: 1fr 0.85fr;
max-height: 330px;
grid-gap: 2rem;
padding: 5.5rem 2rem 0 2rem;
`;

const NowPlayingContainer = styled('div')``;

const ConfigContainer = styled('div')`
position: relative;
background: #fff;
box-shadow: 0 0 40px rgba(0, 0, 0, 0.15);
border-radius: 5px;
z-index: 2;
@media only screen and (max-width: 1200px) {
display: none;
}
`;

const OverlayInfo = styled('div')``;

export default Landing;
77 changes: 77 additions & 0 deletions src/website/components/ActivityLink.tsx
@@ -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;
}
`;
29 changes: 29 additions & 0 deletions src/website/components/OverlayExamples.tsx
@@ -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} />;
});

1 comment on commit f5b9aed

@vercel
Copy link

@vercel vercel bot commented on f5b9aed Nov 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.