Skip to content

Commit 9c2f4f5

Browse files
committed
promote
1 parent c313355 commit 9c2f4f5

File tree

8 files changed

+268
-0
lines changed

8 files changed

+268
-0
lines changed

index.html

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<link rel="stylesheet" href="/css/codicon.css" />
1616
<link rel="preload" href="star.png" as="image" crossorigin="anonymous" />
1717
<link rel="preload" href="floor.jpg" as="image" crossorigin="anonymous" />
18+
<link rel="preload" href="peter.png" as="image" crossorigin="anonymous" />
1819
<link rel="preload" href="image/1.jpg" as="image" crossorigin="anonymous" />
1920
<link rel="preload" href="image/2.jpg" as="image" crossorigin="anonymous" />
2021
<link rel="preload" href="image/3.jpg" as="image" crossorigin="anonymous" />

public/peter.png

195 KB
Loading

src/components/App.tsx

+8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import "./common/StockChart";
3131
import useStateContext from "../context/useStateContext";
3232
import SubscribeModal from "./SubscribeModal";
3333
import MantineModal from "./MantineModal";
34+
import CommercialModal from "./CommercialModal";
3435

3536
const isDevelopment = () => {
3637
return process.env.CC_NODE_ENV === "development";
@@ -149,6 +150,9 @@ export const App = () => {
149150
fullScreen,
150151
})
151152
}}
153+
onCommercialClick={() => {
154+
CommercialModal.open();
155+
}}
152156
/>,
153157
<EditorWrapper
154158
onRef={(ref) => {
@@ -185,6 +189,9 @@ export const App = () => {
185189
fullScreen,
186190
})
187191
}}
192+
onCommercialClick={() => {
193+
CommercialModal.open();
194+
}}
188195
/>,
189196
];
190197
}
@@ -234,6 +241,7 @@ export const App = () => {
234241
</Split>
235242
<MantineModal />
236243
<SubscribeModal />
244+
<CommercialModal />
237245
</Box>
238246
);
239247
};

src/components/CommercialFab.tsx

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { useMediaContext } from "react-declarative";
2+
import { makeStyles } from "../styles";
3+
import { AutoAwesome } from "@mui/icons-material";
4+
import Button from "@mui/material/Button";
5+
import Fab from "@mui/material/Fab";
6+
7+
const useStyles = makeStyles()({
8+
root: {
9+
position: 'fixed',
10+
bottom: '17px',
11+
right: '66px',
12+
opacity: 0.33,
13+
transition: 'opacity 500ms',
14+
'&:hover': {
15+
opacity: 1,
16+
}
17+
},
18+
button: {
19+
minHeight: "35px !important",
20+
maxHeight: "35px !important",
21+
paddingLeft: "15px !important",
22+
paddingRight: "15px !important",
23+
order: -1,
24+
zIndex: 99,
25+
},
26+
fab: {
27+
order: -1,
28+
zIndex: 99,
29+
},
30+
31+
});
32+
33+
interface ICommercialFabProps {
34+
onClick: () => void;
35+
}
36+
37+
export const CommercialFab = ({
38+
onClick,
39+
}: ICommercialFabProps) => {
40+
const { classes, cx } = useStyles();
41+
42+
const { isWide } = useMediaContext();
43+
44+
if (isWide) {
45+
return (
46+
<Button
47+
className={cx(classes.button, classes.root)}
48+
variant="contained"
49+
size="small"
50+
startIcon={<AutoAwesome color="inherit" />}
51+
onClick={onClick}
52+
>
53+
Move faster
54+
</Button>
55+
);
56+
}
57+
58+
return (
59+
<Fab
60+
className={cx(classes.fab, classes.root)}
61+
size="small"
62+
color="primary"
63+
onClick={onClick}
64+
>
65+
<AutoAwesome color="inherit" />
66+
</Fab>
67+
);
68+
};
69+
70+
export default CommercialFab;

src/components/CommercialModal.tsx

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { useMemo, useState } from 'react';
2+
3+
import { makeStyles } from '../styles';
4+
import { alpha, darken, Theme } from '@mui/material';
5+
6+
import { Center, PortalView, RevealView, Countdown, openBlank, createLsManager, Subject, useOnce, copyToClipboard, useSnack } from 'react-declarative';
7+
8+
import Typography from '@mui/material/Typography';
9+
import Button from '@mui/material/Button';
10+
import Paper from '@mui/material/Paper';
11+
import Stack from '@mui/material/Stack';
12+
import Box from '@mui/material/Box';
13+
14+
const LOGO_HEIGHT = 225;
15+
16+
const useStyles = makeStyles()((theme) => ({
17+
root: {
18+
position: 'fixed',
19+
top: 0,
20+
left: 0,
21+
right: 0,
22+
bottom: 0,
23+
zIndex: 9999,
24+
background: alpha('#999999', 0.2),
25+
backdropFilter: 'saturate(180%) blur(20px)',
26+
height: '100%',
27+
width: '100%',
28+
display: 'flex',
29+
alignItems: 'center',
30+
justifyContent: 'center',
31+
flexDirection: 'column',
32+
gap: 20,
33+
padding: 15,
34+
},
35+
container: {
36+
position: "relative",
37+
marginBottom: '3.5vw',
38+
overflow: "hidden",
39+
maxWidth: 375,
40+
padding: 15,
41+
},
42+
reveal: {
43+
width: 'unset !important',
44+
},
45+
avatarRoot: {
46+
position: "absolute",
47+
overflow: "hidden",
48+
display: "flex",
49+
alignItems: "center",
50+
justifyContent: "center",
51+
top: 0,
52+
left: 0,
53+
right: 0,
54+
width: "100%",
55+
height: LOGO_HEIGHT,
56+
background: darken(theme.palette.background.paper, 0.12),
57+
},
58+
avatarAdjust: {
59+
paddingBottom: LOGO_HEIGHT,
60+
},
61+
}));
62+
63+
const openSubject = new Subject<void>();
64+
65+
export const CommercialModal = () => {
66+
const { classes } = useStyles();
67+
68+
const [opened, setOpened] = useState(false);
69+
const notify = useSnack();
70+
71+
useOnce(() => openSubject.subscribe(() => setOpened(true)));
72+
73+
const handleSubmit = () => {
74+
copyToClipboard("[email protected]");
75+
notify("Email copied to clipboard");
76+
openBlank("mailto:[email protected]");
77+
setOpened(false);
78+
};
79+
80+
const renderLogo = () => (
81+
<>
82+
<Box className={classes.avatarRoot}>
83+
<Stack alignItems="center" gap={1}>
84+
<Center>
85+
<Box
86+
component="img"
87+
src="/peter.png"
88+
loading='lazy'
89+
sx={{ width: 128, height: 128, borderRadius: '50%' }}
90+
/>
91+
</Center>
92+
<Typography variant="h6">Peter Tripolsky</Typography>
93+
<Typography
94+
variant="body2"
95+
textAlign="center"
96+
sx={{ color: (theme: Theme) => theme.palette.text.secondary }}
97+
>
98+
The Creator of <b>react-declarative</b>
99+
</Typography>
100+
</Stack>
101+
</Box>
102+
<div className={classes.avatarAdjust} />
103+
</>
104+
);
105+
106+
if (!opened) {
107+
return null;
108+
}
109+
110+
return (
111+
<PortalView>
112+
<Box className={classes.root} onClick={() => setOpened(false)}>
113+
<RevealView className={classes.reveal}>
114+
<Paper className={classes.container}>
115+
<Stack direction='column' gap="15px">
116+
{renderLogo()}
117+
<span style={{ marginTop: -10 }}>
118+
Move faster by hiring Outsource Company 👷. We have developed 💻 a lot IT of projects<br /><br />
119+
This includes AI and enterprise software development 😃<br /><br />
120+
</span>
121+
<Button
122+
variant="contained"
123+
onClick={handleSubmit}
124+
>
125+
Schedule the meeting
126+
</Button>
127+
</Stack>
128+
</Paper>
129+
</RevealView>
130+
</Box>
131+
</PortalView>
132+
);
133+
};
134+
135+
CommercialModal.open = () => openSubject.next();
136+
137+
export default CommercialModal;

src/components/PreviewWrapper.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Box from "@mui/material/Box";
77
import { Fab } from "@mui/material";
88
import { Fullscreen, FullscreenExit } from "@mui/icons-material";
99
import useStateContext from "../context/useStateContext";
10+
import CommercialFab from "./CommercialFab";
1011

1112
const useStyles = makeStyles()((theme) => ({
1213
root: {
@@ -52,11 +53,13 @@ const useStyles = makeStyles()((theme) => ({
5253
interface IPreviewWrapperProps {
5354
onRef: (ref: HTMLIFrameElement) => void;
5455
onFullscreenToggle: (fullScreen: boolean) => void;
56+
onCommercialClick: () => void;
5557
}
5658

5759
export const PreviewWrapper = ({
5860
onRef,
5961
onFullscreenToggle,
62+
onCommercialClick,
6063
}: IPreviewWrapperProps) => {
6164

6265
const { classes, cx } = useStyles();
@@ -111,6 +114,7 @@ export const PreviewWrapper = ({
111114
}}>
112115
{fullScreen ? <FullscreenExit /> : <Fullscreen />}
113116
</Fab>
117+
<CommercialFab onClick={onCommercialClick} />
114118
</div>
115119
</div>
116120
</div>

src/config/setup.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { copyToClipboard } from "react-declarative";
2+
3+
function fallbackCopyTextToClipboard(text: string) {
4+
const textArea = document.createElement("textarea");
5+
textArea.value = text;
6+
7+
textArea.style.top = "0";
8+
textArea.style.left = "0";
9+
textArea.style.position = "fixed";
10+
11+
document.body.appendChild(textArea);
12+
textArea.focus();
13+
textArea.select();
14+
15+
try {
16+
const successful = document.execCommand("copy");
17+
const msg = successful ? "successful" : "unsuccessful";
18+
console.log(`Fallback: Copying text command was ${msg}`);
19+
} catch (err) {
20+
console.error("Fallback: Oops, unable to copy", err);
21+
}
22+
23+
document.body.removeChild(textArea);
24+
}
25+
26+
copyToClipboard.override(async (text: string) => {
27+
if (window.self !== window.top) {
28+
window.top?.postMessage(
29+
{
30+
type: "copy-action",
31+
text,
32+
},
33+
"*"
34+
);
35+
return;
36+
}
37+
try {
38+
if ("copyToClipboard" in navigator) {
39+
// @ts-ignore
40+
await navigator.copyToClipboard(text);
41+
return;
42+
}
43+
await navigator.clipboard.writeText(text);
44+
} catch {
45+
fallbackCopyTextToClipboard(text);
46+
}
47+
});

src/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import "./config/polyfills";
2+
import "./config/setup";
23

34
import {
45
ModalProvider,

0 commit comments

Comments
 (0)