Skip to content

Commit

Permalink
Implement component to display notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Pseudorizer committed Jul 28, 2021
1 parent 1329427 commit f870892
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 8 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "code-with-mosh-downloader",
"version": "0.0.7",
"version": "0.1.2",
"description": "Download courses from codewithmosh.com",
"main": ".webpack/main",
"scripts": {
Expand Down Expand Up @@ -67,6 +67,7 @@
"@electron-forge/plugin-webpack": "6.0.0-beta.59",
"@electron-forge/publisher-github": "^6.0.0-beta.59",
"@electron-forge/test-utils": "^6.0.0-beta.59",
"@styled-icons/evaicons-solid": "^10.34.0",
"@types/async-lock": "^1.1.3",
"@types/mocha": "^9.0.0",
"@types/node": "^16.4.3",
Expand All @@ -88,6 +89,7 @@
"node-html-parser": "^4.1.2",
"node-loader": "^2.0.0",
"react-is": "^17.0.2",
"react-spring": "^9.2.4",
"sanitize-filename": "^1.6.3",
"spectron": "^15.0.0",
"style-loader": "^3.2.1",
Expand Down
15 changes: 9 additions & 6 deletions src/app/appRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {useRef} from 'react';
import styled from 'styled-components';
import GlobalDefault from 'App/styles/globalDefault';
import {ipcRenderer} from 'electron';
import {Notifications} from 'App/components/notifications';

const RootContainer = styled.div`
width: 100vw;
Expand All @@ -16,14 +17,16 @@ export default function App() {
const inputRef = useRef<HTMLInputElement>();

const onAdd = async () => {
const a = await ipcRenderer.invoke('to-enqueue', {url: 'https://codewithmosh.com/courses', type: 'everything'});
const a = await ipcRenderer.invoke('to-enqueue',
{url: 'https://codewithmosh.com/courses/1422300/lectures/32679735', type: 'video'});
};

return (
<RootContainer>
<GlobalDefault/>
<input ref={inputRef} style={{width: '200px', backgroundColor: 'grey', flex: '1'}}/>
<button onClick={() => onAdd()} style={{width: '200px', flex: '1'}}>add</button>
</RootContainer>
<RootContainer>
<GlobalDefault/>
<Notifications/>
<input ref={inputRef} style={{width: '200px', backgroundColor: 'grey', flex: '1'}}/>
<button onClick={() => onAdd()} style={{width: '200px', flex: '1'}}>add</button>
</RootContainer>
);
}
135 changes: 135 additions & 0 deletions src/app/components/notifications.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React, {useEffect, useRef, useState} from 'react';
import {ipcRenderer} from 'electron';
import styled from 'styled-components';
import {AppNotification} from 'Types/types';
import {Close} from '@styled-icons/evaicons-solid';
import {animated, useTransition} from 'react-spring';

export type NotificationsProps = {}

const Container = styled.div`
position: fixed;
bottom: 0;
right: 0;
z-index: 1;
display: flex;
flex-direction: column;
align-items: flex-end;
`;

const NotificationContainer = styled.div<{ backgroundColour: string, foregroundColour: string }>`
background-color: ${props => props.backgroundColour};
color: ${props => props.foregroundColour};
border-radius: 10px;
display: flex;
`;

const NotificationTextContainer = styled.div`
flex: 5 1;
padding: 0.6rem;
display: flex;
`;

const NotificationText = styled.p`
flex: 1 0;
font-size: 12pt;
font-weight: 500;
`;

const NotificationDismiss = styled.div<{ hoverColour: string }>`
display: flex;
flex: 1 0;
min-height: 100%;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
align-items: center;
justify-content: center;
max-width: 30px;
transition: .2s ease-in-out background-color;
border-left: 1px solid #242424;
&:hover { // #418B5A
background-color: ${props => props.hoverColour};
cursor: pointer;
}
`;

const CloseIcon = styled(Close)`
flex: 1;
width: 20px;
height: 20px;
`;

const colours = {
'success': {
foreground: '#000',
background: '#7FC395',
hover: '#51AC6E',
},
'info': {
foreground: '#000',
background: '#8FBDBD',
hover: '#589595',
},
'error': {
foreground: '#000',
background: '#FD9B9B',
hover: '#f56d6d',
}
};

export function Notifications(props: NotificationsProps) {
const [refMap] = useState(() => new WeakMap<AppNotification, HTMLElement>());
const [notifications, setNotifications] = useState<AppNotification[]>([]);
const closeRef = useRef<HTMLDivElement>();

const transitions = useTransition(notifications, {
from: {opacity: 0, height: 0, margin: '0 1rem 0.7rem 0.7rem', width: '450px', transform: 'translate(0px, 0px)'},
enter: item => async next => await next({opacity: 1, height: refMap.get(item).offsetHeight}),
leave: item => async next => {
await next({transform: 'translate(475px, 0px)'});
await next({height: 0, margin: 'unset'});
},
config: {
tension: 450,
friction: 65
}
});

useEffect(() => {
ipcRenderer.on('to-alerts', (event, args: AppNotification) => {
setNotifications(prev => [...prev, args]);

setTimeout(() => {
setNotifications(prev => {
return prev.filter(x => x !== args);
});
}, 3000);
});
}, []);

const onCloseClick = (item: AppNotification) => {
setNotifications(prev => {
return prev.filter(x => x !== item);
});
};

return (
<Container>
{transitions((style, item) => (
<animated.div style={style}>
<NotificationContainer foregroundColour={colours[item.type].foreground}
backgroundColour={colours[item.type].background}
ref={ref => ref && refMap.set(item, ref)}>
<NotificationTextContainer>
<NotificationText>{item.message}</NotificationText>
</NotificationTextContainer>
<NotificationDismiss hoverColour={colours[item.type].hover} ref={closeRef} onClick={() => onCloseClick(item)}>
<CloseIcon/>
</NotificationDismiss>
</NotificationContainer>
</animated.div>
))}
</Container>
);
}
7 changes: 7 additions & 0 deletions src/app/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ export type DownloadQueueItem = {
}

export type DownloadQueueItemType = 'everything' | 'course' | 'video' | 'end';

export type AppNotification = {
type: AppNotificationType,
message: string
}

export type AppNotificationType = 'success' | 'error' | 'info';
127 changes: 126 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4"
integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==

"@babel/runtime@^7.10.5", "@babel/runtime@^7.14.0":
version "7.14.8"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446"
integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==
dependencies:
regenerator-runtime "^0.13.4"

"@babel/template@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
Expand Down Expand Up @@ -443,7 +450,7 @@
resolved "https://registry.yarnpkg.com/@electron/remote/-/remote-1.2.0.tgz#772eb4c3ac17aaba5a9cf05a09092f6277f5671f"
integrity sha512-C774t2DFVJsa+dxU9Gc2nYzylRZoJ79I0Sxrh8T9cN69fBkntfGbyBEQiD9UfZopqL0CYLzk1anY2Ywhql6h1w==

"@emotion/is-prop-valid@^0.8.8":
"@emotion/is-prop-valid@^0.8.7", "@emotion/is-prop-valid@^0.8.8":
version "0.8.8"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
Expand Down Expand Up @@ -652,6 +659,91 @@
dependencies:
"@octokit/openapi-types" "^9.1.1"

"@react-spring/animated@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.2.4.tgz#062ecc0fdfef89f2541a42d8500428b70035f879"
integrity sha512-AfV6ZM8pCCAT29GY5C8/1bOPjZrv/7kD0vedjiE/tEYvNDwg9GlscrvsTViWR2XykJoYrDfdkYArrldWpsCJ5g==
dependencies:
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/core@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.2.4.tgz#275a4a065e3a315a4f5fb28c9a6f62ce718c25d6"
integrity sha512-R+PwyfsjiuYCWqaTTfCpYpRmsP0h87RNm7uxC1Uxy7QAHUfHEm2sAHn+AdHPwq/MbVwDssVT8C5yf2WGcqiXGg==
dependencies:
"@react-spring/animated" "~9.2.0"
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/konva@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.2.4.tgz#e467b24b3b110ba496526c9001439ce561641e0d"
integrity sha512-19anDOIkfjcydDTfGgVIuZ3lruZxKubYGs9oHCswaP8SRLj7c1kkopJHUr/S4LXGxiIdqdF0XucWm0iTEPEq4w==
dependencies:
"@react-spring/animated" "~9.2.0"
"@react-spring/core" "~9.2.0"
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/native@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.2.4.tgz#0fd335a44c05023f5428df444d8f1aa3da7abfc9"
integrity sha512-xKJWKh5qOhSclpL3iuGwJRLoZzTNvlBEnIrMs8yh8xvX6z9Lmnu4uGu5DpfrnM1GzBvRoktoCoLEx/VcEYFSng==
dependencies:
"@react-spring/animated" "~9.2.0"
"@react-spring/core" "~9.2.0"
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/rafz@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.2.4.tgz#44793e9adc14dd0dcd1573d094368af11a89d73a"
integrity sha512-SOKf9eue+vAX+DGo7kWYNl9i9J3gPUlQjifIcV9Bzw9h3i30wPOOP0TjS7iMG/kLp2cdHQYDNFte6nt23VAZkQ==

"@react-spring/shared@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.2.4.tgz#f9cc66ac5308a77293330a18518e34121f4008c1"
integrity sha512-ZEr4l2BxmyFRUvRA2VCkPfCJii4E7cGkwbjmTBx1EmcGrOnde/V2eF5dxqCTY3k35QuCegkrWe0coRJVkh8q2Q==
dependencies:
"@react-spring/rafz" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/three@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.2.4.tgz#849c97658a6e1410b6f823ad21e2ee33feada820"
integrity sha512-ljFig7XW099VWwRPKPUf+4yYLivp/sSWXN3oO5SJOF/9BSoV1quS/9chZ5Myl5J14od3CsHf89Tv4FdlX5kHlA==
dependencies:
"@react-spring/animated" "~9.2.0"
"@react-spring/core" "~9.2.0"
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/types@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.2.4.tgz#2365ce9d761f548a9adcb2cd68714bf26765a5de"
integrity sha512-zHUXrWO8nweUN/ISjrjqU7GgXXvoEbFca1CgiE0TY0H/dqJb3l+Rhx8ecPVNYimzFg3ZZ1/T0egpLop8SOv4aA==

"@react-spring/web@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.2.4.tgz#c6d5464a954bfd0d7bc90117050f796a95ebfa08"
integrity sha512-vtPvOalLFvuju/MDBtoSnCyt0xXSL6Amyv82fljOuWPl1yGd4M1WteijnYL9Zlriljl0a3oXcPunAVYTD9dbDQ==
dependencies:
"@react-spring/animated" "~9.2.0"
"@react-spring/core" "~9.2.0"
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@react-spring/zdog@~9.2.0":
version "9.2.4"
resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.2.4.tgz#db1d1924fe9920e917d889c4d3bb138bd0885cf1"
integrity sha512-rv7ptedS37SHr6yuCbRkUErAzAhebdgt8f4KUtZWzseC+7qLNkaZWf+uujgsb881qAuX9b9yz8rre9UKeYepgw==
dependencies:
"@react-spring/animated" "~9.2.0"
"@react-spring/core" "~9.2.0"
"@react-spring/shared" "~9.2.0"
"@react-spring/types" "~9.2.0"

"@sindresorhus/is@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
Expand All @@ -662,6 +754,22 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.1.tgz#d26729db850fa327b7cacc5522252194404226f5"
integrity sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==

"@styled-icons/evaicons-solid@^10.34.0":
version "10.34.0"
resolved "https://registry.yarnpkg.com/@styled-icons/evaicons-solid/-/evaicons-solid-10.34.0.tgz#54cff976f32aad41949da7419f6d9947d7bde431"
integrity sha512-74S0zzxovKTXNpID8bXB4Qy34EBq3vuVAlTd9xsT2gY16BtPH7JcGHLmtQpbpJcHuWkcQH4bSv+GLq+0/i/ljQ==
dependencies:
"@babel/runtime" "^7.14.0"
"@styled-icons/styled-icon" "^10.6.3"

"@styled-icons/styled-icon@^10.6.3":
version "10.6.3"
resolved "https://registry.yarnpkg.com/@styled-icons/styled-icon/-/styled-icon-10.6.3.tgz#eae0e5e18fd601ac47e821bb9c2e099810e86403"
integrity sha512-/A95L3peioLoWFiy+/eKRhoQ9r/oRrN/qzbSX4hXU1nGP2rUXcX3LWUhoBNAOp9Rw38ucc/4ralY427UUNtcGQ==
dependencies:
"@babel/runtime" "^7.10.5"
"@emotion/is-prop-valid" "^0.8.7"

"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
Expand Down Expand Up @@ -5802,6 +5910,18 @@ react-is@^17.0.2:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==

react-spring@^9.2.4:
version "9.2.4"
resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.2.4.tgz#9d89b0321664d594f957dca9459b13d94b3dfa39"
integrity sha512-bMjbyTW0ZGd+/h9cjtohLqCwOGqX2OuaTvalOVfLCGmhzEg/u3GgopI3LAm4UD2Br3MNdVdGgNVoESg4MGqKFQ==
dependencies:
"@react-spring/core" "~9.2.0"
"@react-spring/konva" "~9.2.0"
"@react-spring/native" "~9.2.0"
"@react-spring/three" "~9.2.0"
"@react-spring/web" "~9.2.0"
"@react-spring/zdog" "~9.2.0"

react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
Expand Down Expand Up @@ -5915,6 +6035,11 @@ redent@^1.0.0:
indent-string "^2.1.0"
strip-indent "^1.0.1"

regenerator-runtime@^0.13.4:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==

regexp.prototype.flags@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26"
Expand Down

0 comments on commit f870892

Please sign in to comment.