PluginProbe
Extendify / 0.4.0
Extendify v0.4.0
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / components / notices / FooterNotice.js

FooterNotice.js in Extendify 0.4.0, at src/components/notices/FooterNotice.js

108 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { __ } from '@wordpress/i18n'
2 import { Icon, closeSmall } from '@wordpress/icons'
3 import { Button } from '@wordpress/components'
4 import WelcomeNotice from './WelcomeNotice'
5 import PromotionNotice from './PromotionNotice'
6 import FeedbackNotice from './FeedbackNotice'
7 import { useUserStore } from '../../state/User'
8 import { useGlobalStore } from '../../state/GlobalState'
9 import { useState, useEffect, useRef } from '@wordpress/element'
10 import { InstallStandaloneNotice } from './InstallStandaloneNotice'
11 import { General } from '../../api/General'
12
13 const NoticesByPriority = {
14 welcome: WelcomeNotice,
15 promotion: PromotionNotice,
16 feedback: FeedbackNotice,
17 standalone: InstallStandaloneNotice,
18 }
19
20 export default function FooterNotice() {
21 const [hasNotice, setHasNotice] = useState(null)
22 const once = useRef(false)
23 const promotionData = useGlobalStore(
24 (state) => state.metaData?.banners?.footer,
25 )
26
27 const showFeedback = () => {
28 const imports = useUserStore.getState().imports ?? 0
29 const firstLoadedOn =
30 useUserStore.getState()?.firstLoadedOn ?? new Date()
31 const timeDifference =
32 new Date().getTime() - new Date(firstLoadedOn).getTime()
33 const daysSinceActivated = timeDifference / 86_400_000 // 24 hours
34
35 return imports >= 3 && daysSinceActivated > 3
36 }
37
38 // Find the first notice key to use
39 // TODO: extract this logic into the individual component instead of controlling it here
40 const componentKey =
41 Object.keys(NoticesByPriority).find((key) => {
42 if (key === 'promotion') {
43 return (
44 // When checking promotions, use the key sent from the server
45 // to check whether it's been dismissed
46 promotionData?.key &&
47 !useUserStore.getState().noticesDismissedAt[
48 promotionData.key
49 ]
50 )
51 }
52
53 if (key === 'feedback') {
54 return (
55 showFeedback() &&
56 !useUserStore.getState().noticesDismissedAt[key]
57 )
58 }
59
60 if (key === 'standalone') {
61 return (
62 !window.extendifyData.standalone &&
63 !useUserStore.getState().noticesDismissedAt[key]
64 )
65 }
66
67 return !useUserStore.getState().noticesDismissedAt[key]
68 }) ?? null
69 const Notice = NoticesByPriority[componentKey]
70
71 const dismiss = async () => {
72 setHasNotice(false)
73 // The noticesDismissedAt key will either be the key from NoticesByPriority,
74 // or a key passed in from the server, such as 'holiday-sale2077'
75 const key =
76 componentKey === 'promotion' ? promotionData.key : componentKey
77 useUserStore.getState().markNoticeSeen(key, 'notices')
78 await General.ping(`footer-notice-x-${key}`)
79 }
80
81 useEffect(() => {
82 // Only show the notice once on main render and only if a notice exists.
83 if (NoticesByPriority[componentKey] && !once.current) {
84 setHasNotice(true)
85 once.current = true
86 }
87 }, [componentKey])
88
89 if (!hasNotice) {
90 return null
91 }
92 return (
93 <div className="bg-extendify-secondary hidden lg:flex space-x-4 py-3 px-5 justify-center items-center relative max-w-screen-4xl mx-auto">
94 {/* Pass all data to all components and let them decide what they use */}
95 <Notice promotionData={promotionData} />
96 <div className="absolute right-1">
97 <Button
98 className="opacity-50 hover:opacity-100 focus:opacity-100 text-extendify-black"
99 icon={<Icon icon={closeSmall} />}
100 label={__('Dismiss this notice', 'extendify')}
101 onClick={dismiss}
102 showTooltip={false}
103 />
104 </div>
105 </div>
106 )
107 }
108