Skip to content

Commit

Permalink
feat: toggle notifications with threshold settings
Browse files Browse the repository at this point in the history
  • Loading branch information
vkabc committed Aug 17, 2023
1 parent 1dd293e commit 8d61b8b
Show file tree
Hide file tree
Showing 12 changed files with 295 additions and 64 deletions.
2 changes: 1 addition & 1 deletion packages/site/src/components/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const ReconnectButton = (props: ComponentProps<typeof Button>) => {
};

export const SendHelloButton = (props: ComponentProps<typeof Button>) => {
return <Button {...props}>Send message</Button>;
return <Button {...props}>Set Stop Loss</Button>;
};

export const HeaderButtons = ({
Expand Down
5 changes: 4 additions & 1 deletion packages/site/src/components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type CardProps = {
description: ReactNode;
button?: ReactNode;
input?: ReactNode;
toggle?: ReactNode;
};
disabled?: boolean;
fullWidth?: boolean;
Expand Down Expand Up @@ -47,13 +48,15 @@ const Description = styled.div`
`;

export const Card = ({ content, disabled = false, fullWidth }: CardProps) => {
const { title, description, button, input } = content;
const { title, description, button, input , toggle} = content;
return (
<CardWrapper fullWidth={fullWidth} disabled={disabled}>
{title && (
<Title>{title}</Title>
)}
<Description>{description}</Description>

{toggle}
{input}
{button}
</CardWrapper>
Expand Down
2 changes: 1 addition & 1 deletion packages/site/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const Header = ({
<HeaderWrapper>
<LogoWrapper>
<SnapLogo color={theme.colors.icon.default} size={36} />
<Title>template-snap</Title>
<Title>Notify Me </Title>
</LogoWrapper>
<RightContainer>
<Toggle
Expand Down
6 changes: 3 additions & 3 deletions packages/site/src/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ type CardProps = {
};
const Input = styled.input<{ $inputColor?: string; }>`
padding: 0.5em;
margin: 0.5em;
color: ${props => props.$inputColor || 'gray'};
margin-bottom: 2em;
color: ${props => props.$inputColor || 'black'};
border-radius: 3px;
`;

export const InputPlaceholder = (props) => {
return (
<div>
<Input placeholder="1000" onChange={(e) => props.setThreshold({threshold: e.target.value})} type='text' />
<Input placeholder="alert when < " onChange={(e) => props.setThreshold({threshold: e.target.value})} type='text' />
</div>
);
};
28 changes: 16 additions & 12 deletions packages/site/src/components/SnapLogo.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
export const SnapLogo = ({ color, size }: { color: string; size: number }) => (
<svg
width={size}
height={size}
viewBox={`0 0 125 125`}
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M88.5473 0.415527H36.5005C13.893 0.415527 0.415527 13.9484 0.415527 36.5446V88.5034C0.415527 111.1 13.893 124.57 36.5005 124.57H88.4852C111.093 124.57 124.57 111.1 124.57 88.5034V36.5446C124.632 13.9484 111.155 0.415527 88.5473 0.415527ZM59.8533 92.2281C59.8533 94.0904 58.9216 95.7665 57.3068 96.7597C56.4373 97.3184 55.5057 97.5667 54.5119 97.5667C53.7045 97.5667 52.8971 97.3805 52.0897 97.008L30.3518 86.1445C27.2464 84.5305 25.2589 81.3645 25.2589 77.8261V57.2785C25.2589 55.4161 26.1905 53.7401 27.8053 52.7468C29.4201 51.7536 31.3455 51.6915 33.0224 52.4985L54.7604 63.3621C57.9279 64.9761 59.9154 68.142 59.9154 71.6804V92.2281H59.8533ZM58.549 59.0166L35.1962 46.4149C33.5193 45.4838 32.4635 43.6835 32.4635 41.635C32.4635 39.6485 33.5193 37.7862 35.1962 36.855L58.549 24.2533C61.0333 22.9496 63.9524 22.9496 66.4368 24.2533L89.7895 36.855C91.4664 37.7862 92.5223 39.5864 92.5223 41.635C92.5223 43.6835 91.4664 45.4838 89.7895 46.4149L66.4368 59.0166C65.1946 59.6995 63.8282 60.0099 62.4618 60.0099C61.0954 60.0099 59.7912 59.6995 58.549 59.0166ZM99.789 77.8261C99.789 81.3645 97.8015 84.5925 94.634 86.1445L72.896 97.008C72.1507 97.3805 71.3433 97.5667 70.4738 97.5667C69.4801 97.5667 68.5484 97.3184 67.6789 96.7597C66.0641 95.7665 65.1325 94.0904 65.1325 92.2281V71.6804C65.1325 68.142 67.1199 64.914 70.2875 63.3621L92.0254 52.4985C93.7023 51.6915 95.6277 51.7536 97.2425 52.7468C98.8573 53.7401 99.789 55.4161 99.789 57.2785V77.8261Z"
fill={color}
/>
</svg>
// <svg
// width={size}
// height={size}
// viewBox={`0 0 125 125`}
// fill="none"
// xmlns="http://www.w3.org/2000/svg"
// >
// <path
// d="M88.5473 0.415527H36.5005C13.893 0.415527 0.415527 13.9484 0.415527 36.5446V88.5034C0.415527 111.1 13.893 124.57 36.5005 124.57H88.4852C111.093 124.57 124.57 111.1 124.57 88.5034V36.5446C124.632 13.9484 111.155 0.415527 88.5473 0.415527ZM59.8533 92.2281C59.8533 94.0904 58.9216 95.7665 57.3068 96.7597C56.4373 97.3184 55.5057 97.5667 54.5119 97.5667C53.7045 97.5667 52.8971 97.3805 52.0897 97.008L30.3518 86.1445C27.2464 84.5305 25.2589 81.3645 25.2589 77.8261V57.2785C25.2589 55.4161 26.1905 53.7401 27.8053 52.7468C29.4201 51.7536 31.3455 51.6915 33.0224 52.4985L54.7604 63.3621C57.9279 64.9761 59.9154 68.142 59.9154 71.6804V92.2281H59.8533ZM58.549 59.0166L35.1962 46.4149C33.5193 45.4838 32.4635 43.6835 32.4635 41.635C32.4635 39.6485 33.5193 37.7862 35.1962 36.855L58.549 24.2533C61.0333 22.9496 63.9524 22.9496 66.4368 24.2533L89.7895 36.855C91.4664 37.7862 92.5223 39.5864 92.5223 41.635C92.5223 43.6835 91.4664 45.4838 89.7895 46.4149L66.4368 59.0166C65.1946 59.6995 63.8282 60.0099 62.4618 60.0099C61.0954 60.0099 59.7912 59.6995 58.549 59.0166ZM99.789 77.8261C99.789 81.3645 97.8015 84.5925 94.634 86.1445L72.896 97.008C72.1507 97.3805 71.3433 97.5667 70.4738 97.5667C69.4801 97.5667 68.5484 97.3184 67.6789 96.7597C66.0641 95.7665 65.1325 94.0904 65.1325 92.2281V71.6804C65.1325 68.142 67.1199 64.914 70.2875 63.3621L92.0254 52.4985C93.7023 51.6915 95.6277 51.7536 97.2425 52.7468C98.8573 53.7401 99.789 55.4161 99.789 57.2785V77.8261Z"
// fill={color}
// />
// </svg>

<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" className="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5" />
</svg>
);
132 changes: 132 additions & 0 deletions packages/site/src/components/ToggleGeneric.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { useEffect, useState } from 'react';
import styled from 'styled-components';
import { getStopLossToggle } from '../utils';

type CheckedProps = {
readonly checked: boolean;
};

const ToggleWrapper = styled.div`
touch-action: pan-x;
display: inline-block;
position: relative;
cursor: pointer;
background-color: transparent;
border: 0;
padding: 0;
-webkit-touch-callout: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
margin-right: 2.4rem;
margin-bottom: 2.4rem;
${({ theme }) => theme.mediaQueries.small} {
margin-right: 2.4rem;
}
`;

const ToggleInput = styled.input`
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
`;

const IconContainer = styled.div`
position: absolute;
width: 22px;
height: 22px;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
line-height: 0;
opacity: 0;
transition: opacity 0.25s ease;
& > * {
align-items: center;
display: flex;
height: 22px;
justify-content: center;
position: relative;
width: 22px;
}
`;

const CheckedContainer = styled(IconContainer)<CheckedProps>`
opacity: ${({ checked }) => (checked ? 1 : 0)};
left: 10px;
`;

const UncheckedContainer = styled(IconContainer)<CheckedProps>`
opacity: ${({ checked }) => (checked ? 0 : 1)};
right: 10px;
`;

const ToggleContainer = styled.div`
width: 68px;
height: 36px;
padding: 0;
border-radius: 36px;
background-color: ${({ theme }) => theme.colors.background.alternative};
transition: all 0.2s ease;
`;
const ToggleCircle = styled.div<CheckedProps>`
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
position: absolute;
top: 4px;
left: ${({ checked }) => (checked ? '36px' : '4px')};
width: 28px;
height: 28px;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.14);
border-radius: 50%;
background-color: #ffffff;
box-sizing: border-box;
transition: all 0.25s ease;
`;

export const ToggleGeneric = ({
onToggle,
defaultChecked = false,
}: {
onToggle(): void;
defaultChecked?: boolean;
}) => {
useEffect(() => {


const f = async () => {

const currentStop = await getStopLossToggle();
setChecked(currentStop);
}
f();

}, []);
const [checked, setChecked] = useState(defaultChecked);

const handleChange = () => {
onToggle();
setChecked(!checked);
};

return (
<ToggleWrapper onClick={handleChange}>
<ToggleContainer>
<CheckedContainer checked={checked}>
<span>🔔</span>
</CheckedContainer>
<UncheckedContainer checked={checked}>
</UncheckedContainer>
</ToggleContainer>
<ToggleCircle checked={checked} />
<ToggleInput type="checkbox" aria-label="Toggle Button" />
</ToggleWrapper>
);
};
1 change: 1 addition & 0 deletions packages/site/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './MetaMask';
export * from './PoweredBy';
export * from './SnapLogo';
export * from './Toggle';
export * from './ToggleGeneric';
49 changes: 34 additions & 15 deletions packages/site/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useContext, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import { MetamaskActions, MetaMaskContext } from '../hooks';
import {
connectSnap,
getSnap,
getSnap, getStopLossToggle,
getThemePreference,
sendHello,
sendToggleStop,
shouldDisplayReconnectButton,
} from '../utils';
import {
Expand All @@ -13,6 +15,8 @@ import {
ReconnectButton,
SendHelloButton,
Card,
Toggle,
ToggleGeneric,
} from '../components';
import { InputPlaceholder } from '../components/Input';

Expand All @@ -23,6 +27,7 @@ const Container = styled.div`
flex: 1;
margin-top: 7.6rem;
margin-bottom: 7.6rem;
${({ theme }) => theme.mediaQueries.small} {
padding-left: 2.4rem;
padding-right: 2.4rem;
Expand All @@ -47,6 +52,7 @@ const Subtitle = styled.p`
font-weight: 500;
margin-top: 0;
margin-bottom: 0;
${({ theme }) => theme.mediaQueries.small} {
font-size: ${({ theme }) => theme.fontSizes.text};
}
Expand Down Expand Up @@ -76,6 +82,7 @@ const Notice = styled.div`
& > * {
margin: 0;
}
${({ theme }) => theme.mediaQueries.small} {
margin-top: 1.2rem;
padding: 1.6rem;
Expand All @@ -92,6 +99,7 @@ const ErrorMessage = styled.div`
margin-top: 2.4rem;
max-width: 60rem;
width: 100%;
${({ theme }) => theme.mediaQueries.small} {
padding: 1.6rem;
margin-bottom: 1.2rem;
Expand All @@ -103,6 +111,7 @@ const ErrorMessage = styled.div`
const Index = () => {
const [state, dispatch] = useContext(MetaMaskContext);


const handleConnectClick = async () => {
try {
await connectSnap();
Expand All @@ -122,8 +131,8 @@ const Index = () => {
threshold: '',
});
const sendData = (data) => {
setData(data)
}
setData(data);
};

const handleSendHelloClick = async () => {
try {
Expand All @@ -134,15 +143,15 @@ const Index = () => {
}
};


return (
<Container>
<Heading>
Welcome to <Span>template-snap</Span>
<Span>Notify Me</Span>
</Heading>
<Subtitle>
Get started by editing <code>src/index.ts</code>
Get started by clicking <code>Install MetaMask Flask</code>
</Subtitle>
Notify Me is a snap extension that allows crypto holders to be alerted when a token reaches a certain price.
<CardContainer>
{state.error && (
<ErrorMessage>
Expand All @@ -154,7 +163,7 @@ const Index = () => {
content={{
title: 'Install',
description:
'Snaps is pre-release software only available in MetaMask Flask, a canary distribution for developers with access to upcoming features.',
'Notify Me allows crypto holders to be alerted when a token reaches a certain price.',
button: <InstallFlaskButton />,
}}
fullWidth
Expand Down Expand Up @@ -194,16 +203,28 @@ const Index = () => {
)}
<Card
content={{
title: 'Send Hello message',
title: 'Stop Loss',
description:
'Display a custom message within a confirmation screen in MetaMask.',
'When the price of a token drops below a certain threshold (1482), you will be notified.',
button: (
<SendHelloButton
onClick={handleSendHelloClick}
disabled={!state.installedSnap}
/>
),
input: <InputPlaceholder setThreshold={sendData}/>,
input: <InputPlaceholder setThreshold={sendData} />,
toggle: (
<ToggleGeneric
onToggle={async () => {
try {
console.log(await sendToggleStop(true));
} catch (e) {
console.error(e);
dispatch({ type: MetamaskActions.SetError, payload: e });
}
}}
/>
),
}}
disabled={!state.installedSnap}
fullWidth={
Expand All @@ -214,10 +235,8 @@ const Index = () => {
/>
<Notice>
<p>
Please note that the <b>snap.manifest.json</b> and{' '}
<b>package.json</b> must be located in the server root directory and
the bundle must be hosted at the location specified by the location
field.
Please note that this is a proof of concept and is not meant to be{' '}
<b>production ready </b>
</p>
</Notice>
</CardContainer>
Expand Down
Loading

0 comments on commit 8d61b8b

Please sign in to comment.