tangled
alpha
login
or
join now
jeanmachine.dev
/
witchsky.app
forked from
jollywhoppers.com/witchsky.app
0
fork
atom
Bluesky app fork with some witchin' additions 💫
0
fork
atom
overview
issues
pulls
pipelines
Implement web toast
Paul Frazee
3 years ago
24559599
20eaac6a
+77
-21
3 changed files
expand all
collapse all
unified
split
public
index.html
src
App.web.tsx
view
com
util
Toast.web.tsx
-19
public/index.html
···
36
36
border-radius: 10px;
37
37
box-shadow: 0 5px 10px #0005;
38
38
}
39
39
-
40
40
-
/* These styles are for src/view/com/util/Toast */
41
41
-
div[data-toast-container] {
42
42
-
position: fixed;
43
43
-
bottom: 5vh;
44
44
-
right: 5vh;
45
45
-
width: 350px;
46
46
-
padding: 20px;
47
47
-
display: flex;
48
48
-
flex-direction: row;
49
49
-
align-items: center;
50
50
-
background: #fff;
51
51
-
border-radius: 10px;
52
52
-
box-shadow: 0 5px 10px #0005;
53
53
-
}
54
54
-
div[data-toast-container] > div {
55
55
-
font-size: 18px;
56
56
-
margin-left: 10px;
57
57
-
}
58
39
</style>
59
40
</head>
60
41
<body>
+2
-2
src/App.web.tsx
···
3
3
import * as view from './view/index'
4
4
import {RootStoreModel, setupState, RootStoreProvider} from './state'
5
5
import {WebShell} from './view/shell/web'
6
6
-
// import Toast from 'react-native-root-toast' TODO
6
6
+
import {ToastContainer} from './view/com/util/Toast.web'
7
7
8
8
function App() {
9
9
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(
···
26
26
<SafeAreaProvider>
27
27
<WebShell />
28
28
</SafeAreaProvider>
29
29
+
<ToastContainer />
29
30
</RootStoreProvider>
30
31
)
31
31
-
// <Toast.ToastContainer /> TODO
32
32
}
33
33
34
34
export default App
+75
src/view/com/util/Toast.web.tsx
···
1
1
+
/*
2
2
+
* Note: the dataSet properties are used to leverage custom CSS in public/index.html
3
3
+
*/
4
4
+
5
5
+
import React, {useState, useEffect} from 'react'
6
6
+
import {StyleSheet, Text, View} from 'react-native'
7
7
+
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
8
8
+
9
9
+
const DURATION = 3500
10
10
+
11
11
+
interface ActiveToast {
12
12
+
text: string
13
13
+
}
14
14
+
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
15
15
+
16
16
+
// globals
17
17
+
// =
18
18
+
let globalSetActiveToast: GlobalSetActiveToast | undefined
19
19
+
let toastTimeout: NodeJS.Timeout | undefined
20
20
+
21
21
+
// components
22
22
+
// =
23
23
+
type ToastContainerProps = {}
24
24
+
export const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
25
25
+
const [activeToast, setActiveToast] = useState<ActiveToast | undefined>()
26
26
+
useEffect(() => {
27
27
+
globalSetActiveToast = (t: ActiveToast | undefined) => {
28
28
+
setActiveToast(t)
29
29
+
}
30
30
+
})
31
31
+
return (
32
32
+
<>
33
33
+
{activeToast && (
34
34
+
<View style={styles.container}>
35
35
+
<FontAwesomeIcon icon="check" size={24} style={styles.icon} />
36
36
+
<Text style={styles.text}>{activeToast.text}</Text>
37
37
+
</View>
38
38
+
)}
39
39
+
</>
40
40
+
)
41
41
+
}
42
42
+
43
43
+
// methods
44
44
+
// =
45
45
+
export function show(text: string) {
46
46
+
if (toastTimeout) {
47
47
+
clearTimeout(toastTimeout)
48
48
+
}
49
49
+
globalSetActiveToast?.({text})
50
50
+
toastTimeout = setTimeout(() => {
51
51
+
globalSetActiveToast?.(undefined)
52
52
+
}, DURATION)
53
53
+
}
54
54
+
55
55
+
const styles = StyleSheet.create({
56
56
+
container: {
57
57
+
position: 'absolute',
58
58
+
right: 20,
59
59
+
bottom: 20,
60
60
+
width: 350,
61
61
+
padding: 20,
62
62
+
flexDirection: 'row',
63
63
+
alignItems: 'center',
64
64
+
backgroundColor: '#000c',
65
65
+
borderRadius: 10,
66
66
+
},
67
67
+
icon: {
68
68
+
color: '#fff',
69
69
+
},
70
70
+
text: {
71
71
+
color: '#fff',
72
72
+
fontSize: 18,
73
73
+
marginLeft: 10,
74
74
+
},
75
75
+
})