PluginProbe
Extendify / 0.6.0
Extendify v0.6.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.6.0, at src/components/notices/FooterNotice.js

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