Skip to content

Commit

Permalink
app: Add simple new version notification
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser committed Oct 30, 2020
1 parent f38c0be commit 434a387
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 118 deletions.
34 changes: 34 additions & 0 deletions src/renderer/components/ActionButton.tsx
@@ -0,0 +1,34 @@
import styled from '@emotion/styled';
import {css} from '@emotion/core';

const primary = css`
background: #28272b;
color: #fff;
&:hover {
background: #000;
}
`;

const muted = css`
background: #eee;
&:hover {
background: #e5e5e5;
}
`;

const ActionButton = styled('button')<{muted?: boolean}>`
display: grid;
grid-auto-flow: column;
grid-auto-columns: max-content;
grid-gap: 0.5rem;
align-items: center;
border: none;
padding: 0.5rem 1rem;
font-weight: bold;
border-radius: 3px;
${p => (p.muted ? muted : primary)}
`;

export default ActionButton;
70 changes: 70 additions & 0 deletions src/renderer/components/Footer.tsx
@@ -0,0 +1,70 @@
import * as React from 'react';
import styled from '@emotion/styled';
import {Save} from 'react-feather';
import {shell} from 'electron';

import Logo from 'src/shared/components/Logo';
import ActionButton from './ActionButton';
import useRelease from 'src/utils/useLatestRelease';

const Footer = () => {
const latestRelease = useRelease();

const hasNewVersion =
latestRelease &&
process.env.RELEASE_CHANNEL === 'stable' &&
process.env.RELEASE !== latestRelease.name;

const newVersion = latestRelease && hasNewVersion && (
<NewVersionButton onClick={() => shell.openExternal(latestRelease.html_url)}>
<Save size="1rem" /> {latestRelease.name} available
</NewVersionButton>
);

return (
<Wrapper>
<Logo size={28} />
<div>
<Title>prolink tools</Title>
<Release>{process.env.RELEASE}</Release>
</div>
<Info>{newVersion}</Info>
</Wrapper>
);
};

const Info = styled('div')`
display: flex;
gap: 0.5rem;
align-items: center;
justify-content: flex-end;
`;

const NewVersionButton = styled(ActionButton)`
background: #ef5f73;
color: #fff;
padding: 0.375rem 0.5rem;
font-size: 0.75rem;
`;

const Title = styled('h2')`
display: flex;
align-items: center;
font-size: 0.8rem;
margin: 0;
`;

const Release = styled('div')`
font-size: 0.7rem;
color: #777a7b;
`;

const Wrapper = styled('div')`
padding: 0.5rem;
display: grid;
align-items: center;
grid-template-columns: max-content max-content 1fr;
grid-gap: 0.5rem;
`;

export default Footer;
20 changes: 20 additions & 0 deletions src/renderer/components/PaneHeader.tsx
@@ -0,0 +1,20 @@
import styled from '@emotion/styled';

const Header = styled('header')`
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
border-bottom: 1px solid #eee;
`;

const HeaderInfo = styled('p')`
font-family: Ubuntu;
flex-grow: 1;
margin-right: 1.5rem;
font-size: 0.8rem;
max-width: 450px;
margin: 0;
`;

export {Header, HeaderInfo};
33 changes: 0 additions & 33 deletions src/renderer/components/Version.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions src/renderer/views/Application.tsx
Expand Up @@ -5,7 +5,7 @@ import {MemoryRouter, Switch, Route, Redirect} from 'react-router-dom';

import globalCss, {noSelect} from 'src/shared/globalCss';
import Titlebar from 'app/components/Titlebar';
import Version from 'app/components/Version';
import Footer from 'app/components/Footer';
import Devices from 'app/views/devices';
import OverlayConfig from 'app/views/overlayConfig';
import Settings from 'app/views/settings';
Expand All @@ -22,7 +22,7 @@ const Application = () => (
<Route path="/settings" component={Settings} />
</Switch>
</Frame>
<Version />
<Footer />
</MemoryRouter>
);

Expand Down
67 changes: 10 additions & 57 deletions src/renderer/views/overlayConfig/index.tsx
Expand Up @@ -2,9 +2,11 @@ import * as React from 'react';
import {observer} from 'mobx-react';
import styled from '@emotion/styled';
import {Plus, ArrowLeft} from 'react-feather';
import {css} from '@emotion/core';
import {AnimatePresence} from 'framer-motion';

import {Header, HeaderInfo} from 'src/renderer/components/PaneHeader';
import ActionButton from 'src/renderer/components/ActionButton';

import AvailableOverlays from './components/AvailableOverlays';
import OverlayList from './components/OverlayList';

Expand All @@ -14,23 +16,21 @@ const OverlayConfig = observer(() => {
return (
<React.Fragment>
<Header>
<Help>
<HeaderInfo>
Overlays are small websites that you can embed into a livestream using the{' '}
<a href="https://obsproject.com/wiki/Sources-Guide#browsersource">
OBS Browser Source
</a>{' '}
(or similar). Each instance of an overlay has it's own configuration.
</Help>
</HeaderInfo>
{addNewOpen ? (
<BackButton onClick={() => setOpen(!addNewOpen)}>
<ActionButton muted onClick={() => setOpen(!addNewOpen)}>
<ArrowLeft size="1rem" /> Back
</BackButton>
</ActionButton>
) : (
<AddButton onClick={() => setOpen(!addNewOpen)}>
<React.Fragment>
<Plus size="1rem" shapeRendering="crispEdges" /> Add Overlay
</React.Fragment>
</AddButton>
<ActionButton onClick={() => setOpen(!addNewOpen)}>
<Plus size="1rem" shapeRendering="crispEdges" /> Add Overlay
</ActionButton>
)}
</Header>
<Container>
Expand All @@ -48,53 +48,6 @@ const OverlayConfig = observer(() => {
);
});

const Header = styled('header')`
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
border-bottom: 1px solid #eee;
`;

const Help = styled('p')`
font-family: Ubuntu;
flex-grow: 1;
margin-right: 1.5rem;
font-size: 0.8rem;
max-width: 450px;
margin: 0;
`;

const actionButtonCss = css`
display: grid;
grid-template-columns: max-content max-content;
grid-gap: 0.5rem;
align-items: center;
border: none;
padding: 0.5rem 1rem;
font-weight: bold;
border-radius: 3px;
`;

const AddButton = styled('button')`
${actionButtonCss};
background: #28272b;
color: #fff;
&:hover {
background: #000;
}
`;

const BackButton = styled('button')`
${actionButtonCss};
background: #eee;
&:hover {
background: #e5e5e5;
}
`;

const Container = styled('div')`
position: relative;
flex-grow: 1;
Expand Down
7 changes: 7 additions & 0 deletions src/shared/constants.tsx
@@ -1 +1,8 @@
export const GITHUB_REPO = {
owner: 'evanpurkhiser',
repo: 'prolink-tools',
};

export const GITHUB_REPO_URL = `https://github.com/${GITHUB_REPO.owner}/${GITHUB_REPO.repo}`;

export const WEBSERVER_PORT = 5152;
21 changes: 21 additions & 0 deletions src/utils/useLatestRelease.tsx
@@ -0,0 +1,21 @@
import * as React from 'react';
import {request} from '@octokit/request';
import {Endpoints} from '@octokit/types';
import {GITHUB_REPO} from 'src/shared/constants';

type Release = Endpoints['GET /repos/:owner/:repo/releases/latest']['response'];

const useRelease = () => {
const [release, setRelease] = React.useState<Release['data'] | null>(null);

const getReleases = async () => {
const release = await request('GET /repos/:owner/:repo/releases/latest', GITHUB_REPO);
setRelease(release['data']);
};

React.useEffect(() => void getReleases(), []);

return release;
};

export default useRelease;
24 changes: 4 additions & 20 deletions src/website/components/DownloadCta.tsx
@@ -1,28 +1,12 @@
import * as React from 'react';
import styled from '@emotion/styled';
import {motion} from 'framer-motion';
import {request} from '@octokit/request';
import {Endpoints} from '@octokit/types';

import useRelease from 'src/utils/useLatestRelease';
import {AppleLogo, WindowsLogo, LinuxLogo} from 'src/shared/components/Icons';
import {format, parseISO} from 'date-fns';
import {GITHUB_REPO} from '../constants';

type Platform = NonNullable<ReturnType<typeof getPlatform>>;
type Release = Endpoints['GET /repos/:owner/:repo/releases/latest']['response'];

const useRelease = () => {
const [release, setRelease] = React.useState<Release | null>(null);

const getReleases = async () => {
const release = await request('GET /repos/:owner/:repo/releases/latest', GITHUB_REPO);
setRelease(release);
};

React.useEffect(() => void getReleases(), []);

return release;
};

const getPlatform = () => {
const platform = window.navigator.platform.toLowerCase();
Expand Down Expand Up @@ -58,7 +42,7 @@ const DownloadCta = (props: React.ComponentProps<typeof motion.div>) => {
}

// Find the asset for the paltform they're on
const asset = release.data.assets.find(asset => asset.name.includes(platform));
const asset = release.assets.find(asset => asset.name.includes(platform));
if (asset) {
window.location.replace(asset.browser_download_url);
}
Expand All @@ -74,10 +58,10 @@ const DownloadCta = (props: React.ComponentProps<typeof motion.div>) => {
</DownloadButton>

<VersionTag>
version {release?.data.name.slice(1) ?? 'x.x.x'}
version {release?.name.slice(1) ?? 'x.x.x'}
<small>
{release
? format(parseISO(release.data.published_at), 'MMMM do yyyy')
? format(parseISO(release.published_at), 'MMMM do yyyy')
: 'Fetching release...'}
</small>
</VersionTag>
Expand Down
6 changes: 0 additions & 6 deletions src/website/constants.tsx

This file was deleted.

0 comments on commit 434a387

Please sign in to comment.