PluginProbe ʕ •ᴥ•ʔ
Presto Player / trunk
Presto Player vtrunk
4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / dashboard / components / Onboarding / PremiumFeatures.js
presto-player / src / admin / dashboard / components / Onboarding Last commit date
Done.js 1 month ago Integrations.js 1 month ago PremiumFeatures.js 1 month ago UserInfo.js 1 month ago Welcome.js 1 month ago
PremiumFeatures.js
253 lines
1 import { Badge, Button, Text, Title, Container } from "@bsf/force-ui";
2 import {
3 ChevronRight,
4 ChevronLeft,
5 Check,
6 Lock,
7 ExternalLink,
8 } from "lucide-react";
9 import useUpgradeCTA from "../../hooks/useUpgradeCTA";
10 import useCompleteOnboarding from "../../hooks/useCompleteOnboarding";
11
12 const { __ } = wp.i18n;
13
14 const FEATURES = [
15 {
16 id: "video_sources",
17 title: __("YouTube, Vimeo & Self-hosted Videos", "presto-player"),
18 description: __(
19 "Embed videos from all major sources with a fully customizable player.",
20 "presto-player"
21 ),
22 type: "free",
23 },
24 {
25 id: "presets_branding",
26 title: __("Player Presets & Branding", "presto-player"),
27 description: __(
28 "Customize controls, colors, and poster images. Save reusable presets across your site.",
29 "presto-player"
30 ),
31 type: "free",
32 },
33 {
34 id: "builder_lms",
35 title: __("Page Builder & LMS Integrations", "presto-player"),
36 description: __(
37 "Works with Elementor, Divi, Beaver Builder, LearnDash, TutorLMS, and LifterLMS.",
38 "presto-player"
39 ),
40 type: "free",
41 },
42 {
43 id: "bunny_hosting",
44 title: __("Bunny.net Private Video Hosting", "presto-player"),
45 description: __(
46 "CDN-powered hosting with HLS adaptive streaming, private URLs, and transcoding.",
47 "presto-player"
48 ),
49 type: "premium",
50 },
51 {
52 id: "analytics",
53 title: __("Video Analytics & Engagement Insights", "presto-player"),
54 description: __(
55 "Track per-user views, watch time, and engagement. Includes Google Analytics.",
56 "presto-player"
57 ),
58 type: "premium",
59 },
60 {
61 id: "playlists_chapters",
62 title: __("Playlists & Video Chapters", "presto-player"),
63 description: __(
64 "Netflix-style bingeable playlists and clickable timestamp markers.",
65 "presto-player"
66 ),
67 type: "premium",
68 },
69 {
70 id: "more_pro_features",
71 title: __("And much more", "presto-player"),
72 description: __(
73 "Popups, email capture, watermarks, CTAs, captions, and advanced playback.",
74 "presto-player"
75 ),
76 type: "premium",
77 },
78 ];
79
80 const PremiumFeatures = ({ goToNextStep, goToPreviousStep }) => {
81 const {
82 isProUnlicensed,
83 isPremium,
84 licenseSettingsHref,
85 externalUpgradeLink,
86 } = useUpgradeCTA();
87 const { completeOnboarding, isSubmitting } = useCompleteOnboarding();
88
89 const handleUpgradeClick = isProUnlicensed
90 ? () => completeOnboarding(licenseSettingsHref)
91 : () => window.open(externalUpgradeLink, "_blank", "noopener noreferrer");
92
93 const upgradeLabel = isProUnlicensed
94 ? __("Activate License", "presto-player")
95 : __("Upgrade to Pro", "presto-player");
96
97 const heading = __("What's included with Presto Player", "presto-player");
98
99 const subtitle = isPremium
100 ? __(
101 "Your Pro license is active — every feature below is ready to use.",
102 "presto-player"
103 )
104 : isProUnlicensed
105 ? __(
106 "Your Pro features are ready — activate your license to start using them.",
107 "presto-player"
108 )
109 : __(
110 "A quick tour of everything you can do — included features are ready to use, and you can unlock the rest anytime.",
111 "presto-player"
112 );
113
114 return (
115 <Container direction="column" className="gap-5">
116 <Container direction="column" gap="xs">
117 <Title size="lg" tag="h3" title={heading} />
118 <Text size={14} weight={400} color="secondary">
119 {subtitle}
120 </Text>
121 </Container>
122
123 <Container direction="column" gap="none">
124 {FEATURES.map((feature, index) => {
125 const isFeatureUnlocked = feature.type === "free" || isPremium;
126
127 return (
128 <div key={feature.id}>
129 <Container
130 direction="row"
131 align="start"
132 gap="sm"
133 className="py-4 px-1"
134 >
135 {isFeatureUnlocked ? (
136 <div className="w-6 h-6 rounded-full bg-brand-background-50 flex items-center justify-center shrink-0 mt-0.5">
137 <Check
138 className="size-3.5 text-brand-primary-600"
139 strokeWidth={2.5}
140 />
141 </div>
142 ) : (
143 <div className="w-6 h-6 rounded-full border border-solid border-border-subtle bg-background-secondary flex items-center justify-center shrink-0 mt-0.5">
144 <Lock className="size-3.5 text-text-tertiary" />
145 </div>
146 )}
147
148 <Container.Item className="flex-grow min-w-0">
149 <Container
150 direction="row"
151 align="center"
152 gap="xs"
153 className="flex-wrap"
154 >
155 <Text size={14} weight={600} color="primary">
156 {feature.title}
157 </Text>
158 {feature.type === "free" ? (
159 <Badge
160 label={__("Included", "presto-player")}
161 size="sm"
162 variant="neutral"
163 disableHover
164 className="bg-brand-background-50 text-brand-primary-600 border-transparent"
165 />
166 ) : isPremium ? (
167 <Badge
168 label={__("Unlocked", "presto-player")}
169 size="sm"
170 variant="inverse"
171 disableHover
172 className="bg-brand-primary-600 text-white border-transparent"
173 />
174 ) : (
175 <Badge
176 label={__("Pro", "presto-player")}
177 size="sm"
178 variant="inverse"
179 disableHover
180 className="bg-brand-primary-600 text-white border-transparent"
181 />
182 )}
183 </Container>
184 <Text
185 size={14}
186 weight={400}
187 color="secondary"
188 className="mt-0.5"
189 >
190 {feature.description}
191 </Text>
192 </Container.Item>
193 </Container>
194 {index < FEATURES.length - 1 && (
195 <hr className="border-t border-solid border-border-subtle border-b-0 m-0 w-full" />
196 )}
197 </div>
198 );
199 })}
200 </Container>
201
202 <hr className="border-t border-solid border-border-subtle border-b-0 m-0 w-full" />
203
204 <Container direction="row" align="center" className="justify-between">
205 <Button
206 icon={<ChevronLeft />}
207 variant="outline"
208 onClick={goToPreviousStep}
209 >
210 {__("Back", "presto-player")}
211 </Button>
212 <Container direction="row" align="center" gap="sm">
213 <Button
214 className="text-text-tertiary"
215 variant="ghost"
216 onClick={goToNextStep}
217 >
218 {__("Skip", "presto-player")}
219 </Button>
220 {!isPremium && (
221 <Button
222 icon={<ExternalLink className="w-5 h-5" />}
223 iconPosition="right"
224 size="md"
225 tag="button"
226 type="button"
227 variant="ghost"
228 onClick={handleUpgradeClick}
229 disabled={isProUnlicensed && isSubmitting}
230 >
231 {upgradeLabel}
232 {!isProUnlicensed && (
233 <span className="sr-only">
234 {__("(opens in a new tab)", "presto-player")}
235 </span>
236 )}
237 </Button>
238 )}
239 <Button
240 iconPosition="right"
241 icon={<ChevronRight />}
242 onClick={goToNextStep}
243 >
244 {__("Next", "presto-player")}
245 </Button>
246 </Container>
247 </Container>
248 </Container>
249 );
250 };
251
252 export default PremiumFeatures;
253