Skip to content

Commit 7f151d5

Browse files
committed
Implement intro modal
1 parent f6c60e8 commit 7f151d5

File tree

13 files changed

+453
-160
lines changed

13 files changed

+453
-160
lines changed

src/components/App.tsx

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useMemo, useState, useCallback, useEffect } from 'react'
1+
import React, { useMemo, useState, useEffect } from 'react'
22
import Router from './Router'
33
import GlobalStyle from './GlobalStyle'
44
import { ThemeProvider } from 'styled-components'
@@ -22,10 +22,7 @@ import AppNavigator from './organisms/AppNavigator'
2222
import { useRouter } from '../lib/router'
2323
import { values } from '../lib/db/utils'
2424
import { localLiteStorage } from 'ltstrg'
25-
import {
26-
defaultStorageCreatedKey,
27-
appModeChosenKey,
28-
} from '../lib/localStorageKeys'
25+
import { defaultStorageCreatedKey } from '../lib/localStorageKeys'
2926
import {
3027
getPathByName,
3128
addIpcListener,
@@ -45,6 +42,12 @@ import {
4542
unlistenBoostHubTeamCreateEvent,
4643
BoostHubTeamCreateEvent,
4744
} from '../lib/events'
45+
import {
46+
useCheckedFeatures,
47+
featureAppModeSelect,
48+
featureBoostHubIntro,
49+
} from '../lib/checkedFeatures'
50+
import BoostHubIntroModal from '../components/organisms/BoostHubIntroModal'
4851

4952
const LoadingText = styled.div`
5053
margin: 30px;
@@ -94,7 +97,6 @@ const App = () => {
9497
const { fetchDesktopGlobalData } = useBoostHub()
9598

9699
useEffectOnce(() => {
97-
const boostHubUserInfo = preferences['boosthub.user']
98100
initialize()
99101
.then(async (storageMap) => {
100102
const storages = values(storageMap)
@@ -142,68 +144,66 @@ const App = () => {
142144
.catch((error) => {
143145
console.error(error)
144146
})
145-
.then(() => {
146-
const appModeChosen = localLiteStorage.getItem(appModeChosenKey)
147-
if (appModeChosen !== 'true') {
148-
setShowAppModeModal(true)
149-
}
150-
localLiteStorage.setItem(appModeChosenKey, 'true')
151-
})
152-
.then(async () => {
153-
if (boostHubUserInfo == null) {
154-
return
155-
}
156-
const { user, teams } = await fetchDesktopGlobalData()
157-
if (user == null) {
158-
setPreferences({
159-
'boosthub.user': undefined,
160-
})
161-
setGeneralStatus({
162-
boostHubTeams: [],
163-
})
164-
return
165-
// User's auth is invalidated. Should go to auth page
166-
messageBox({
167-
title: 'Boost Hub login is required',
168-
message: 'Your BoostHub session has been expired.',
169-
buttons: ['Sign In Again', 'Cancel'],
170-
defaultButtonIndex: 0,
171-
iconType: DialogIconTypes.Warning,
172-
onClose: (value: number | null) => {
173-
if (value === 0) {
174-
return
175-
}
147+
})
176148

177-
setPreferences({
178-
'boosthub.user': undefined,
179-
})
180-
setGeneralStatus({
181-
boostHubTeams: [],
182-
})
183-
},
184-
})
185-
return
186-
}
187-
setPreferences((previousPreferences) => {
188-
return {
189-
...previousPreferences,
190-
'boosthub.user': {
191-
id: user.id,
192-
uniqueName: user.uniqueName,
193-
displayName: user.displayName,
194-
},
195-
}
149+
useEffectOnce(() => {
150+
const run = async () => {
151+
const boostHubUserInfo = preferences['boosthub.user']
152+
if (boostHubUserInfo == null) {
153+
return
154+
}
155+
const { user, teams } = await fetchDesktopGlobalData()
156+
if (user == null) {
157+
setPreferences({
158+
'boosthub.user': undefined,
196159
})
197160
setGeneralStatus({
198-
boostHubTeams: teams.map((team) => {
199-
return {
200-
id: team.id,
201-
name: team.name,
202-
domain: team.domain,
161+
boostHubTeams: [],
162+
})
163+
return
164+
// User's auth is invalidated. Should go to auth page
165+
messageBox({
166+
title: 'Boost Hub login is required',
167+
message: 'Your BoostHub session has been expired.',
168+
buttons: ['Sign In Again', 'Cancel'],
169+
defaultButtonIndex: 0,
170+
iconType: DialogIconTypes.Warning,
171+
onClose: (value: number | null) => {
172+
if (value === 0) {
173+
return
203174
}
204-
}),
175+
176+
setPreferences({
177+
'boosthub.user': undefined,
178+
})
179+
setGeneralStatus({
180+
boostHubTeams: [],
181+
})
182+
},
205183
})
184+
return
185+
}
186+
setPreferences((previousPreferences) => {
187+
return {
188+
...previousPreferences,
189+
'boosthub.user': {
190+
id: user.id,
191+
uniqueName: user.uniqueName,
192+
displayName: user.displayName,
193+
},
194+
}
206195
})
196+
setGeneralStatus({
197+
boostHubTeams: teams.map((team) => {
198+
return {
199+
id: team.id,
200+
name: team.name,
201+
domain: team.domain,
202+
}
203+
}),
204+
})
205+
}
206+
run()
207207
})
208208

209209
useEffect(() => {
@@ -254,11 +254,7 @@ const App = () => {
254254
}, [])
255255
useGlobalKeyDownHandler(keyboardHandler)
256256

257-
const [showAppModeModal, setShowAppModeModal] = useState(false)
258-
259-
const closeAppModeModal = useCallback(() => {
260-
setShowAppModeModal(false)
261-
}, [])
257+
const { isChecked } = useCheckedFeatures()
262258

263259
return (
264260
<ThemeProvider theme={selectTheme(preferences['general.theme'])}>
@@ -271,11 +267,15 @@ const App = () => {
271267
<>
272268
{preferences['general.showAppNavigator'] && <AppNavigator />}
273269
<Router />
270+
{!isChecked(featureAppModeSelect) ? (
271+
<AppModeModal />
272+
) : (
273+
!isChecked(featureBoostHubIntro) && <BoostHubIntroModal />
274+
)}
274275
</>
275276
) : (
276277
<LoadingText>Loading Data...</LoadingText>
277278
)}
278-
{showAppModeModal && <AppModeModal closeModal={closeAppModeModal} />}
279279
<GlobalStyle />
280280
<Dialog />
281281
<PreferencesModal />
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import React, { useCallback } from 'react'
2+
import Image from '../atoms/Image'
3+
import Icon from '../atoms/Icon'
4+
import { mdiAccountPlus, mdiHistory, mdiChartBar } from '@mdi/js'
5+
import styled from '../../lib/styled'
6+
import { flexCenter, border } from '../../lib/styled/styleFunctions'
7+
import { openNew } from '../../lib/platform'
8+
import { boostHubLearnMorePageUrl } from '../../lib/boosthub'
9+
10+
const BoostHubFeatureIntro = () => {
11+
const openLearnMorePage = useCallback(() => {
12+
openNew(boostHubLearnMorePageUrl)
13+
}, [])
14+
15+
return (
16+
<Container>
17+
<ul className='featureList'>
18+
<li className='featureListItem'>
19+
<div className='featureListItemIcon'>
20+
<Icon path={mdiAccountPlus} />
21+
</div>
22+
<div className='featureListItemBody'>
23+
<h2>Real-time Coauthoring</h2>
24+
<p>
25+
You can edit markdown documents with your colleagues synchronously
26+
</p>
27+
</div>
28+
</li>
29+
<li className='featureListItem'>
30+
<div className='featureListItemIcon'>
31+
<Icon path={mdiHistory} />
32+
</div>
33+
<div className='featureListItemBody'>
34+
<h2>Revision History</h2>
35+
<p>
36+
Every change of a document will be saved and accessible without
37+
time expiry
38+
</p>
39+
</div>
40+
</li>
41+
<li className='featureListItem'>
42+
<div className='featureListItemIcon'>
43+
<Icon path={mdiChartBar} />
44+
</div>
45+
<div className='featureListItemBody'>
46+
<h2>Diagram Supports</h2>
47+
<p>
48+
LaTeX math equation and most of popular diagrams(Chart.js, Mermaid
49+
and PlantUML) are available
50+
</p>
51+
</div>
52+
</li>
53+
<li className='featureLearnMoreItem'>
54+
<a onClick={openLearnMorePage}>Learn more</a>
55+
</li>
56+
</ul>
57+
<div className='screenShot'>
58+
<Image src='/static/boosthub.png' />
59+
</div>
60+
</Container>
61+
)
62+
}
63+
export default BoostHubFeatureIntro
64+
65+
const Container = styled.div`
66+
display: flex;
67+
.featureList {
68+
list-style: none;
69+
width: 300px;
70+
margin: 0;
71+
margin-right: 20px;
72+
padding: 0;
73+
& > .featureLearnMoreItem {
74+
text-align: right;
75+
color: ${({ theme }) => theme.primaryColor};
76+
cursor: pointer;
77+
&:hover {
78+
text-decoration: underline;
79+
}
80+
}
81+
}
82+
.featureList > .featureListItem {
83+
${border}
84+
display: flex;
85+
padding: 0 5px;
86+
margin-bottom: 10px;
87+
border-radius: 5px;
88+
padding: 10px 5px 10px 10px;
89+
background-color: ${({ theme }) => theme.navItemBackgroundColor};
90+
& > .featureListItemIcon {
91+
${flexCenter}
92+
font-size: 24px;
93+
width: 24px;
94+
height: 24px;
95+
}
96+
& > .featureListItemBody {
97+
margin-left: 7px;
98+
& > h2 {
99+
font-size: 18px;
100+
margin-top: 0;
101+
margin-bottom: 10px;
102+
}
103+
& > p {
104+
font-size: 14px;
105+
margin: 0;
106+
}
107+
}
108+
}
109+
.screenShot {
110+
flex: 1;
111+
img {
112+
width: 100%;
113+
${border}
114+
border-radius: 5px;
115+
}
116+
}
117+
`
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React, { FC, MouseEventHandler } from 'react'
2+
import { flexCenter } from '../../lib/styled/styleFunctions'
3+
import styled from '../../lib/styled'
4+
5+
interface ModalContainerProps {
6+
onShadowClick: MouseEventHandler<HTMLDivElement>
7+
}
8+
9+
const ModalContainer: FC<ModalContainerProps> = ({
10+
onShadowClick,
11+
children,
12+
}) => {
13+
return (
14+
<Container>
15+
{children}
16+
<div className='shadow' onClick={onShadowClick} />
17+
</Container>
18+
)
19+
}
20+
21+
export default ModalContainer
22+
23+
const Container = styled.div`
24+
z-index: 6000;
25+
position: fixed;
26+
top: 0;
27+
left: 0;
28+
bottom: 0;
29+
right: 0;
30+
-webkit-app-region: drag;
31+
${flexCenter}
32+
& > .shadow {
33+
position: absolute;
34+
z-index: 6001;
35+
top: 0;
36+
left: 0;
37+
right: 0;
38+
bottom: 0;
39+
background-color: rgba(0, 0, 0, 0.4);
40+
}
41+
`

0 commit comments

Comments
 (0)