PluginProbe ʕ •ᴥ•ʔ
Download Manager / trunk
Download Manager vtrunk
3.3.62 3.3.61 3.3.60 3.3.59 3.3.58 3.3.57 3.3.56 trunk 2.1.3 2.3.0 2.5.96 2.5.97 2.6.2 2.6.96 2.8.3 2.9.99 3.0.4 3.1.05 3.1.07 3.1.08 3.1.11 3.1.12 3.1.14 3.1.17 3.1.18 3.1.22 3.1.23 3.1.24 3.1.25 3.1.26 3.1.27 3.1.28 3.2.04 3.2.13 3.2.14 3.2.16 3.2.18 3.2.19 3.2.21 3.2.22 3.2.23 3.2.24 3.2.25 3.2.27 3.2.28 3.2.29 3.2.30 3.2.31 3.2.32 3.2.33 3.2.34 3.2.35 3.2.37 3.2.38 3.2.39 3.2.40 3.2.41 3.2.42 3.2.43 3.2.44 3.2.45 3.2.46 3.2.47 3.2.48 3.2.49 3.2.50 3.2.51 3.2.52 3.2.53 3.2.54 3.2.55 3.2.56 3.2.57 3.2.58 3.2.59 3.2.60 3.2.61 3.2.63 3.2.64 3.2.65 3.2.66 3.2.67 3.2.68 3.2.69 3.2.70 3.2.71 3.2.72 3.2.73 3.2.74 3.2.75 3.2.76 3.2.77 3.2.78 3.2.79 3.2.80 3.2.81 3.2.82 3.2.83 3.2.84 3.2.85 3.2.86 3.2.87 3.2.88 3.2.89 3.2.90 3.2.91 3.2.92 3.2.93 3.2.94 3.2.95 3.2.96 3.2.97 3.2.98 3.2.99 3.3.00 3.3.01 3.3.02 3.3.03 3.3.04 3.3.05 3.3.06 3.3.07 3.3.08 3.3.09 3.3.10 3.3.11 3.3.12 3.3.13 3.3.14 3.3.15 3.3.16 3.3.17 3.3.18 3.3.19 3.3.20 3.3.21 3.3.22 3.3.23 3.3.24 3.3.25 3.3.26 3.3.27 3.3.28 3.3.29 3.3.30 3.3.31 3.3.32 3.3.33 3.3.34 3.3.35 3.3.36 3.3.37 3.3.38 3.3.39 3.3.40 3.3.41 3.3.42 3.3.43 3.3.44 3.3.45 3.3.46 3.3.47 3.3.48 3.3.49 3.3.50 3.3.51 3.3.52 3.3.53 3.3.54 3.3.55
download-manager / src / Admin / views / addons-list.php
download-manager / src / Admin / views Last commit date
asset-manager 5 years ago dashboard-widgets 6 months ago metaboxes 1 week ago settings 4 months ago stats 1 week ago templates 1 week ago addons-list.php 1 week ago admin-footer.php 2 months ago admin-head.php 2 years ago edit-store-profile.php 5 years ago iconfinder.php 2 years ago page-header.php 6 months ago settings.php 6 months ago stats.php 6 months ago welcome.php 6 months ago
addons-list.php
680 lines
1 <?php
2 /**
3 * Admin → Add-Ons marketplace view.
4 *
5 * Renders a centered hero in .wpdm-admin-page-content. The framework's fixed
6 * #wpdm-admin-page-header is kept (empty/invisible) ONLY as a paint anchor:
7 * Pro's admin defers this view's first paint unless a fixed, painted element
8 * exists on the page. Data prep is separated from presentation below.
9 */
10 if (!defined('ABSPATH')) die();
11
12 if (!function_exists('is_plugin_active')) {
13 require_once ABSPATH . 'wp-admin/includes/plugin.php';
14 }
15
16 $items = [];
17 $installed_count = 0;
18
19 if (is_array($data)) {
20 foreach ($data as $package) {
21 $files = (array) $package->files;
22 $file = str_replace('.zip', '', array_shift($files));
23 $file = explode('/', $file);
24 $file = end($file);
25
26 $plugininfo = wpdm_plugin_data($file);
27
28 $installed = (bool) $plugininfo;
29 $installed_version = $installed && isset($plugininfo['Version']) ? $plugininfo['Version'] : '';
30 $active = $installed && isset($plugininfo['plugin_index_file']) && is_plugin_active($plugininfo['plugin_index_file']);
31 $update = $installed && $installed_version && version_compare($installed_version, $package->version, '<');
32
33 if ($installed) $installed_count++;
34
35 $items[] = (object) [
36 'ID' => $package->ID,
37 'title' => $package->post_title,
38 'excerpt' => $package->excerpt,
39 'link' => $package->link,
40 'version' => $package->version,
41 'price' => $package->price,
42 'currency' => $package->currency,
43 'file' => $file,
44 'categories' => implode(' ', array_map('sanitize_html_class', (array) $package->categories)),
45 'installed' => $installed,
46 'active' => $active,
47 'update' => $update,
48 ];
49 }
50 }
51
52 $total = count($items);
53 $cat_count = is_array($cats) ? count($cats) : 0;
54
55 $cat_counts = [];
56 foreach ($items as $countItem) {
57 foreach (array_filter(explode(' ', $countItem->categories)) as $catSlug) {
58 $cat_counts[$catSlug] = isset($cat_counts[$catSlug]) ? $cat_counts[$catSlug] + 1 : 1;
59 }
60 }
61 ?>
62 <style>
63 #screen-meta-links { display: none; }
64 .wrap.w3eden .updated,
65 .wrap.w3eden #screen-meta { display: none; }
66
67 /* The fixed header is kept only as a paint anchor (Pro defers this view's
68 first paint without a fixed, painted element). Rendered slim + invisible;
69 the real title is the centered hero in the content below. */
70 #wpdm-admin-page-header { pointer-events: none; }
71 #wpdm-admin-page-header #wpdm-admin-main-header { height: 40px; border: 0; box-shadow: none; }
72 #wpdm-admin-page-header h3 { visibility: hidden; }
73
74 .wpda {
75 --wpda-surface: #ffffff;
76 --wpda-bg: #f6f7fb;
77 --wpda-border: #e6e8ef;
78 --wpda-border-strong: #d3d7e3;
79 --wpda-text: #1e2433;
80 --wpda-text-muted: #6b7280;
81 --wpda-text-soft: #9aa1ad;
82 --wpda-primary: var(--color-primary, #4a8eff);
83 --wpda-primary-rgb: var(--color-primary-rgb, 74, 142, 255);
84 --wpda-success: var(--color-success, #10b981);
85 --wpda-success-rgb: var(--color-success-rgb, 16, 185, 129);
86 --wpda-warning: var(--color-warning, #f59e0b);
87 --wpda-warning-rgb: 245, 158, 11;
88 --wpda-danger: var(--color-danger, #ef4444);
89 --wpda-radius: 12px;
90 --wpda-radius-sm: 8px;
91 --wpda-radius-pill: 999px;
92 --wpda-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
93 --wpda-shadow-hover: 0 6px 16px rgba(16, 24, 40, .08), 0 14px 32px rgba(16, 24, 40, .10);
94 --wpda-transition: 180ms cubic-bezier(.4, 0, .2, 1);
95 font-family: var(--wpdm-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
96 color: var(--wpda-text);
97 }
98 .wpda * { box-sizing: border-box; }
99
100 /* slim invisible anchor (~40px) sits at the top; clear it, no big void */
101 .wpdm-admin-page-content.wpda { padding-top: 48px; }
102
103 /* ---- Hero ---- */
104 .wpda-hero { display: flex; flex-direction: column; align-items: center; text-align: center; margin-bottom: 0; }
105 .wpda-hero__icon {
106 display: inline-flex;
107 align-items: center;
108 justify-content: center;
109 width: 52px;
110 height: 52px;
111 margin-bottom: 18px;
112 color: var(--wpda-primary);
113 background: rgba(var(--wpda-primary-rgb), .1);
114 border-radius: 14px;
115 }
116 .wpda-hero__icon svg { width: 26px; height: 26px; }
117 .wpda .wpda-hero__title {
118 margin: 0;
119 padding: 0;
120 font-size: clamp(22px, 2.4vw, 28px);
121 font-weight: 800;
122 letter-spacing: -.02em;
123 line-height: 1.15;
124 color: var(--wpda-text);
125 }
126 .wpda .wpda-hero__subtitle {
127 max-width: 56ch;
128 margin: 8px auto 20px;
129 font-size: 13.5px;
130 line-height: 1.5;
131 color: var(--wpda-text-muted);
132 text-align: center;
133 }
134
135 .wpda-stats { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 22px 0 0; padding: 0; }
136 .wpda-stat {
137 min-width: 92px;
138 padding: 12px 16px;
139 background: var(--wpda-surface);
140 border: 1px solid var(--wpda-border);
141 border-radius: var(--wpda-radius-sm);
142 text-align: center;
143 }
144 .wpda-stat dt {
145 margin: 0 0 2px;
146 font-size: 11px;
147 font-weight: 600;
148 text-transform: uppercase;
149 letter-spacing: .04em;
150 color: var(--wpda-text-soft);
151 }
152 .wpda-stat dd {
153 margin: 0;
154 font-size: 22px;
155 font-weight: 800;
156 line-height: 1;
157 color: var(--wpda-text);
158 font-variant-numeric: tabular-nums;
159 }
160
161 .wpda-sep { height: 1px; background: var(--wpda-border); margin: 28px -32px; }
162
163 /* ---- Toolbar (search + scope) ---- */
164 .wpda-toolbar {
165 display: flex;
166 align-items: center;
167 justify-content: center;
168 gap: 14px;
169 flex-wrap: wrap;
170 margin-bottom: 16px;
171 }
172 .wpda-search { position: relative; flex: 0 1 460px; min-width: 220px; max-width: 460px; }
173 .wpda-search__icon {
174 position: absolute;
175 left: 12px;
176 top: 0;
177 bottom: 0;
178 margin: auto 0;
179 width: 16px;
180 height: 16px;
181 color: var(--wpda-text-soft);
182 pointer-events: none;
183 }
184 .wpda-search input {
185 width: 100%;
186 height: 38px;
187 margin: 0;
188 padding: 0 64px 0 36px;
189 font-size: 13px;
190 line-height: 38px;
191 color: var(--wpda-text);
192 background: var(--wpda-bg);
193 border: 1px solid var(--wpda-border);
194 border-radius: var(--wpda-radius-sm);
195 box-shadow: none;
196 transition: border-color var(--wpda-transition), box-shadow var(--wpda-transition), background var(--wpda-transition);
197 }
198 .wpda-search input:focus {
199 outline: none;
200 background: var(--wpda-surface);
201 border-color: var(--wpda-primary);
202 box-shadow: 0 0 0 3px rgba(var(--wpda-primary-rgb), .15);
203 }
204 .wpda-search input::placeholder { color: var(--wpda-text-soft); }
205 .wpda-search__kbd {
206 position: absolute;
207 right: 10px;
208 top: 0;
209 bottom: 0;
210 margin: auto 0;
211 height: 20px;
212 padding: 2px 7px;
213 font-size: 11px;
214 font-weight: 600;
215 line-height: 16px;
216 color: var(--wpda-text-soft);
217 background: var(--wpda-surface);
218 border: 1px solid var(--wpda-border);
219 border-radius: 5px;
220 pointer-events: none;
221 }
222 .wpda-search__clear {
223 position: absolute;
224 right: 8px;
225 top: 0;
226 bottom: 0;
227 margin: auto 0;
228 display: none;
229 align-items: center;
230 justify-content: center;
231 width: 22px;
232 height: 22px;
233 padding: 0;
234 color: var(--wpda-text-muted);
235 background: transparent;
236 border: 0;
237 border-radius: 50%;
238 cursor: pointer;
239 line-height: 1;
240 transition: background var(--wpda-transition), color var(--wpda-transition);
241 }
242 .wpda-search__clear:hover { background: var(--wpda-border); color: var(--wpda-text); }
243 .wpda-search.is-filled .wpda-search__kbd { display: none; }
244 .wpda-search.is-filled .wpda-search__clear { display: inline-flex; }
245
246 .wpda-scope {
247 display: inline-flex;
248 gap: 2px;
249 padding: 3px;
250 background: var(--wpda-bg);
251 border: 1px solid var(--wpda-border);
252 border-radius: var(--wpda-radius-sm);
253 }
254 .wpda-scope button {
255 display: inline-flex;
256 align-items: center;
257 gap: 6px;
258 padding: 6px 14px;
259 font-size: 12.5px;
260 font-weight: 600;
261 color: var(--wpda-text-muted);
262 background: transparent;
263 border: 0;
264 border-radius: 6px;
265 cursor: pointer;
266 transition: color var(--wpda-transition), background var(--wpda-transition), box-shadow var(--wpda-transition);
267 }
268 .wpda-scope button:hover { color: var(--wpda-text); }
269 .wpda-scope button.is-active { color: var(--wpda-text); background: var(--wpda-surface); box-shadow: var(--wpda-shadow); }
270 .wpda-scope__count {
271 padding: 1px 7px;
272 font-size: 11px;
273 font-weight: 700;
274 color: var(--wpda-text-muted);
275 background: var(--wpda-border);
276 border-radius: var(--wpda-radius-pill);
277 font-variant-numeric: tabular-nums;
278 }
279 .wpda-scope button.is-active .wpda-scope__count { color: #fff; background: var(--wpda-primary); }
280
281 /* ---- Filter bar (categories) ---- */
282 .wpda-filterbar { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-bottom: 22px; }
283 .wpda-cats { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 0; padding: 0; list-style: none; }
284 .wpda-cats li { margin: 0; }
285 .wpda-cats button {
286 display: inline-block;
287 padding: 6px 14px;
288 font-size: 12.5px;
289 font-weight: 600;
290 color: var(--wpda-text-muted);
291 background: var(--wpda-surface);
292 border: 1px solid var(--wpda-border);
293 border-radius: var(--wpda-radius-pill);
294 cursor: pointer;
295 transition: color var(--wpda-transition), background var(--wpda-transition), border-color var(--wpda-transition);
296 }
297 .wpda-cats button:hover { color: var(--wpda-text); border-color: var(--wpda-border-strong); }
298 .wpda-cats button.is-active {
299 color: #fff;
300 background: var(--wpda-primary);
301 border-color: var(--wpda-primary);
302 box-shadow: 0 1px 2px rgba(var(--wpda-primary-rgb), .35);
303 }
304 .wpda-cats button .wpda-cats__n { margin-left: 6px; font-weight: 600; opacity: .5; font-variant-numeric: tabular-nums; }
305 .wpda-cats button.is-active .wpda-cats__n { opacity: .72; }
306
307 /* ---- Grid ---- */
308 .wpda-grid {
309 display: grid;
310 grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
311 gap: 18px;
312 }
313
314 .wpda-card {
315 position: relative;
316 display: flex;
317 flex-direction: column;
318 background: var(--wpda-surface);
319 border: 1px solid var(--wpda-border);
320 border-radius: 14px;
321 box-shadow: var(--wpda-shadow);
322 overflow: hidden;
323 transition: transform var(--wpda-transition), box-shadow var(--wpda-transition), border-color var(--wpda-transition);
324 }
325 .wpda-card:hover { transform: translateY(-4px); border-color: rgba(var(--wpda-primary-rgb), .4); box-shadow: var(--wpda-shadow-hover); }
326 .wpda-card.wpda-hide { display: none; }
327
328 /* ---- Cover band ---- */
329 .wpda-card__cover {
330 position: relative;
331 height: 64px;
332 background:
333 radial-gradient(130% 140% at 85% -20%, rgba(255, 255, 255, .55), transparent 60%),
334 linear-gradient(135deg, hsl(var(--h, 220), 46%, 93%), hsl(calc(var(--h, 220) + 24), 42%, 89%));
335 }
336 .wpda-card__cover::after {
337 content: "";
338 position: absolute;
339 inset: 0;
340 background: linear-gradient(180deg, transparent 62%, rgba(15, 23, 42, .035));
341 }
342 .wpda-card__cover-status {
343 position: absolute;
344 top: 12px;
345 right: 12px;
346 z-index: 2;
347 display: inline-flex;
348 align-items: center;
349 gap: 5px;
350 padding: 4px 11px;
351 font-size: 10.5px;
352 font-weight: 700;
353 letter-spacing: .01em;
354 border-radius: var(--wpda-radius-pill);
355 background: #fff;
356 border: 1px solid var(--wpda-border);
357 box-shadow: 0 1px 2px rgba(16, 24, 40, .08);
358 white-space: nowrap;
359 }
360 .wpda-card__cover-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
361 .wpda-card__cover-status.wpda-status--active { color: var(--wpda-success); }
362 .wpda-card__cover-status.wpda-status--installed { color: var(--wpda-primary); }
363 .wpda-card__cover-status.wpda-status--update { color: var(--wpda-warning); }
364
365 /* ---- Body ---- */
366 .wpda-card__body { position: relative; padding: 0 18px 16px; flex: 1; }
367 .wpda-card__icon {
368 position: relative;
369 z-index: 1;
370 margin: -26px 0 12px;
371 width: 52px;
372 height: 52px;
373 display: flex;
374 align-items: center;
375 justify-content: center;
376 border-radius: 14px;
377 font-size: 21px;
378 font-weight: 800;
379 line-height: 1;
380 background: #fff;
381 color: hsl(var(--h, 220), 58%, 46%);
382 box-shadow: 0 4px 10px rgba(16, 24, 40, .14), 0 0 0 4px var(--wpda-surface);
383 }
384 .wpda-card__icon img { width: 100%; height: 100%; object-fit: cover; border-radius: 11px; }
385 .wpda-card__title { margin: 0 0 7px; font-size: 15px; font-weight: 700; line-height: 1.3; }
386 .wpda-card__title a { color: var(--wpda-text); text-decoration: none; transition: color var(--wpda-transition); }
387 .wpda-card:hover .wpda-card__title a { color: var(--wpda-primary); }
388 .wpda-card__title a:focus-visible { outline: 2px solid rgba(var(--wpda-primary-rgb), .5); outline-offset: 2px; border-radius: 3px; }
389 .wpda-card__excerpt {
390 margin: 0;
391 font-size: 12.5px;
392 line-height: 1.6;
393 color: var(--wpda-text-muted);
394 max-height: 60px;
395 overflow: hidden;
396 }
397
398 /* ---- Footer ---- */
399 .wpda-card__footer {
400 display: flex;
401 align-items: center;
402 justify-content: space-between;
403 gap: 12px;
404 padding: 13px 18px;
405 border-top: 1px solid var(--wpda-border);
406 }
407 .wpda-card__meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
408 .wpda-card__price { font-size: 16px; font-weight: 800; line-height: 1.2; color: var(--wpda-text); font-variant-numeric: tabular-nums; }
409 .wpda-card__price--free { color: var(--wpda-success); }
410 .wpda-card__version {
411 font-size: 11px;
412 font-weight: 600;
413 color: var(--wpda-text-soft);
414 font-variant-numeric: tabular-nums;
415 white-space: nowrap;
416 }
417 .wpda-card__cta { display: inline-flex; align-items: center; gap: 8px; flex: none; }
418
419 .wpda-btn {
420 display: inline-flex;
421 align-items: center;
422 gap: 6px;
423 padding: 7px 14px;
424 font-size: 12px;
425 font-weight: 600;
426 line-height: 1.2;
427 border: 1px solid transparent;
428 border-radius: var(--wpda-radius-sm);
429 cursor: pointer;
430 text-decoration: none;
431 white-space: nowrap;
432 transition: background var(--wpda-transition), border-color var(--wpda-transition), color var(--wpda-transition), box-shadow var(--wpda-transition), filter var(--wpda-transition);
433 }
434 .wpda-btn .fa, .wpda-btn svg { font-size: 11px; }
435 .wpda a.wpda-btn--primary { color: #fff; background: var(--wpda-primary); box-shadow: 0 1px 2px rgba(var(--wpda-primary-rgb), .3); }
436 .wpda a.wpda-btn--primary:hover { color: #fff; filter: brightness(.93); box-shadow: 0 4px 12px rgba(var(--wpda-primary-rgb), .42); }
437 .wpda a.wpda-btn--update { color: #fff; background: var(--wpda-warning); box-shadow: 0 1px 2px rgba(var(--wpda-warning-rgb), .3); }
438 .wpda a.wpda-btn--update:hover { color: #fff; filter: brightness(.95); box-shadow: 0 4px 12px rgba(var(--wpda-warning-rgb), .42); }
439 .wpda a.wpda-btn--ghost { color: var(--wpda-text); background: var(--wpda-surface); border-color: var(--wpda-border-strong); }
440 .wpda a.wpda-btn--ghost:hover { color: var(--wpda-primary); border-color: var(--wpda-primary); background: rgba(var(--wpda-primary-rgb), .06); }
441 .wpda-btn:focus-visible { outline: 2px solid rgba(var(--wpda-primary-rgb), .5); outline-offset: 2px; }
442
443 /* ---- States ---- */
444 .wpda-state { max-width: 460px; margin: 40px auto; padding: 32px 24px; text-align: center; }
445 .wpda-state__icon {
446 display: inline-flex;
447 align-items: center;
448 justify-content: center;
449 width: 56px;
450 height: 56px;
451 margin-bottom: 18px;
452 color: var(--wpda-text-soft);
453 background: var(--wpda-bg);
454 border: 1px solid var(--wpda-border);
455 border-radius: 50%;
456 }
457 .wpda-state__icon svg { width: 26px; height: 26px; }
458 .wpda-state--error .wpda-state__icon { color: var(--wpda-danger); background: rgba(239, 68, 68, .08); border-color: rgba(239, 68, 68, .2); }
459 .wpda-state__title { margin: 0 0 6px; font-size: 16px; font-weight: 700; color: var(--wpda-text); }
460 .wpda-state__text { margin: 0; font-size: 13px; line-height: 1.6; color: var(--wpda-text-muted); }
461 .wpda-empty-filter { grid-column: 1 / -1; }
462
463 @media (prefers-reduced-motion: reduce) {
464 .wpda-card, .wpda-card__title a, .wpda-btn,
465 .wpda-cats button, .wpda-scope button, .wpda-search input { transition: none; }
466 .wpda-card:hover { transform: none; }
467 }
468 </style>
469
470 <div class="wrap w3eden">
471 <div id="wpdm-admin-page-header" aria-hidden="true">
472 <div id="wpdm-admin-main-header">
473 <div class="media">
474 <div class="media-body">
475 <div class="media">
476 <div class="media-body">
477 <h3><i class="fa fa-plug"></i> <?php _e('Add-Ons', 'download-manager'); ?></h3>
478 </div>
479 </div>
480 </div>
481 </div>
482 </div>
483 </div>
484
485 <div class="wpdm-admin-page-content wpda">
486 <?php if ($total > 0) { ?>
487 <header class="wpda-hero">
488 <span class="wpda-hero__icon" aria-hidden="true">
489 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><path d="M17.5 14v3.5M21 17.5h-3.5M17.5 21v-3.5M14 17.5h3.5"/></svg>
490 </span>
491 <h1 class="wpda-hero__title"><?php _e('Add-Ons', 'download-manager'); ?></h1>
492 <p class="wpda-hero__subtitle"><?php _e('Extend WordPress Download Manager with official integrations — cloud storage, payment gateways, page builders, and more.', 'download-manager'); ?></p>
493 </header>
494
495 <dl class="wpda-stats">
496 <div class="wpda-stat"><dt><?php _e('Add-ons', 'download-manager'); ?></dt><dd><?php echo (int) $total; ?></dd></div>
497 <div class="wpda-stat"><dt><?php _e('Installed', 'download-manager'); ?></dt><dd><?php echo (int) $installed_count; ?></dd></div>
498 <div class="wpda-stat"><dt><?php _e('Categories', 'download-manager'); ?></dt><dd><?php echo (int) $cat_count; ?></dd></div>
499 </dl>
500
501 <div class="wpda-sep"></div>
502
503 <div class="wpda-toolbar">
504 <div class="wpda-search" id="wpda-search-wrap">
505 <span class="wpda-search__icon" aria-hidden="true">
506 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
507 </span>
508 <input type="search" id="wpda-search" autocomplete="off" aria-label="<?php esc_attr_e('Search add-ons', 'download-manager'); ?>" placeholder="<?php esc_attr_e('Search add-ons…', 'download-manager'); ?>">
509 <span class="wpda-search__kbd" aria-hidden="true">/</span>
510 <button type="button" class="wpda-search__clear" id="wpda-search-clear" aria-label="<?php esc_attr_e('Clear search', 'download-manager'); ?>">
511 <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
512 </button>
513 </div>
514 <div class="wpda-scope" role="tablist" aria-label="<?php esc_attr_e('Filter by install state', 'download-manager'); ?>">
515 <button type="button" class="is-active" data-scope="all" role="tab" aria-selected="true"><?php _e('All', 'download-manager'); ?></button>
516 <button type="button" data-scope="installed" role="tab" aria-selected="false">
517 <?php _e('Installed', 'download-manager'); ?>
518 <span class="wpda-scope__count"><?php echo (int) $installed_count; ?></span>
519 </button>
520 </div>
521 </div>
522
523 <div class="wpda-filterbar">
524 <ul class="wpda-cats" id="filter-mods" role="tablist" aria-label="<?php esc_attr_e('Filter by category', 'download-manager'); ?>">
525 <li><button type="button" class="is-active" data-cat="all"><?php _e('All Add-Ons', 'download-manager'); ?><span class="wpda-cats__n"><?php echo (int) $total; ?></span></button></li>
526 <?php if (is_array($cats)) { foreach ($cats as $cat) { $c_n = isset($cat_counts[$cat->slug]) ? (int) $cat_counts[$cat->slug] : 0; ?>
527 <li><button type="button" data-cat="<?php echo esc_attr($cat->slug); ?>"><?php echo esc_html($cat->name); ?><span class="wpda-cats__n"><?php echo $c_n; ?></span></button></li>
528 <?php } } ?>
529 </ul>
530 </div>
531
532 <div class="wpda-grid" id="addonlist">
533 <?php foreach ($items as $item) {
534 $search_index = strtolower(wp_strip_all_tags($item->title . ' ' . $item->excerpt));
535
536 $clean_title = trim(wp_strip_all_tags($item->title));
537 $mono = strtoupper(mb_substr($clean_title, 0, 1));
538 if ($mono === '') $mono = 'W';
539 $hue = abs(crc32($item->title)) % 360;
540
541 if ($item->update) { $status_class = 'update'; $status_label = __('Update available', 'download-manager'); }
542 elseif ($item->active) { $status_class = 'active'; $status_label = __('Active', 'download-manager'); }
543 elseif ($item->installed) { $status_class = 'installed'; $status_label = __('Installed', 'download-manager'); }
544 else { $status_class = ''; $status_label = ''; }
545
546 if ($item->update) $linklabel = '<i class="fa fa-sync"></i> ' . esc_html__('Update', 'download-manager');
547 elseif ($item->installed) $linklabel = '<i class="fa fa-sync"></i> ' . esc_html__('Re-Install', 'download-manager');
548 else $linklabel = '<i class="fa fa-plus-circle"></i> ' . esc_html__('Install', 'download-manager');
549 ?>
550 <article class="wpda-card all <?php echo esc_attr($item->categories); ?>"
551 style="--h: <?php echo (int) $hue; ?>"
552 data-search="<?php echo esc_attr($search_index); ?>"
553 data-installed="<?php echo $item->installed ? '1' : '0'; ?>">
554 <div class="wpda-card__cover">
555 <?php if ($status_label) { ?>
556 <span class="wpda-card__cover-status wpda-status--<?php echo esc_attr($status_class); ?>"><?php echo esc_html($status_label); ?></span>
557 <?php } ?>
558 </div>
559 <div class="wpda-card__body">
560 <span class="wpda-card__icon" aria-hidden="true"><?php echo esc_html($mono); ?></span>
561 <h3 class="wpda-card__title">
562 <a target="_blank" rel="noopener" title="<?php echo esc_attr($item->title); ?>"
563 href="<?php echo esc_url($item->link); ?>"><?php echo esc_html($item->title); ?></a>
564 </h3>
565 <p class="wpda-card__excerpt"><?php echo wp_kses_post($item->excerpt); ?></p>
566 </div>
567 <div class="wpda-card__footer">
568 <div class="wpda-card__meta">
569 <?php if ($item->price > 0) { ?>
570 <span class="wpda-card__price"><?php echo esc_html($item->currency . $item->price); ?></span>
571 <?php } else { ?>
572 <span class="wpda-card__price wpda-card__price--free"><?php _e('Free', 'download-manager'); ?></span>
573 <?php } ?>
574 <?php if ($item->version) { ?>
575 <span class="wpda-card__version"><?php echo esc_html('v' . $item->version); ?></span>
576 <?php } ?>
577 </div>
578 <div class="wpda-card__cta">
579 <?php if ($item->price > 0) { ?>
580 <a class="wpda-btn wpda-btn--primary" target="_blank" rel="noopener"
581 href="<?php echo esc_url('https://www.wpdownloadmanager.com/cart/?addtocart=' . $item->ID); ?>">
582 <i class="fa fa-shopping-cart"></i> <?php _e('Buy Now', 'download-manager'); ?>
583 </a>
584 <?php } else { ?>
585 <a class="wpda-btn <?php echo $item->update ? 'wpda-btn--update' : ($item->installed ? 'wpda-btn--ghost' : 'wpda-btn--primary'); ?>"
586 target="_blank" rel="noopener"
587 href="<?php echo esc_url($item->link); ?>"><?php echo $linklabel; ?></a>
588 <?php } ?>
589 </div>
590 </div>
591 </article>
592 <?php } ?>
593
594 <div class="wpda-state wpda-empty-filter" id="wpda-empty-filter" style="display:none">
595 <div class="wpda-state__icon">
596 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
597 </div>
598 <h3 class="wpda-state__title"><?php _e('No add-ons match your filters', 'download-manager'); ?></h3>
599 <p class="wpda-state__text"><?php _e('Try a different search term or category, or reset to view all add-ons.', 'download-manager'); ?></p>
600 </div>
601 </div>
602 <?php } else {
603 \WPDM\__\Session::clear('wpdm_addon_store_data');
604 \WPDM\__\Session::clear('wpdm_addon_store_cats');
605 ?>
606 <div class="wpda-state wpda-state--error">
607 <div class="wpda-state__icon">
608 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
609 </div>
610 <h3 class="wpda-state__title"><?php _e('Could not reach the add-on store', 'download-manager'); ?></h3>
611 <p class="wpda-state__text"><?php _e('We couldn\'t connect to the server. Please check your connection and reload the page to try again.', 'download-manager'); ?></p>
612 </div>
613 <?php } ?>
614 </div>
615 </div>
616
617 <script>
618 jQuery(function ($) {
619 var $grid = $('#addonlist');
620 var $cards = $grid.find('.wpda-card');
621 var $emptyState = $('#wpda-empty-filter');
622 var $searchWrap = $('#wpda-search-wrap');
623 var $search = $('#wpda-search');
624
625 var state = { q: '', cat: 'all', scope: 'all' };
626
627 function render() {
628 var q = state.q.toLowerCase().trim();
629 var visible = 0;
630
631 $cards.each(function () {
632 var $c = $(this);
633 var matchQ = !q || ($c.data('search') + '').indexOf(q) > -1;
634 var matchCat = state.cat === 'all' || $c.hasClass(state.cat);
635 var matchScope = state.scope === 'all' || String($c.data('installed')) === '1';
636 var show = matchQ && matchCat && matchScope;
637 $c.toggleClass('wpda-hide', !show);
638 if (show) visible++;
639 });
640
641 $emptyState.toggle(visible === 0);
642 }
643
644 $search.on('input', function () {
645 state.q = this.value;
646 $searchWrap.toggleClass('is-filled', this.value.length > 0);
647 render();
648 });
649
650 $('#wpda-search-clear').on('click', function () {
651 state.q = '';
652 $search.val('').focus();
653 $searchWrap.removeClass('is-filled');
654 render();
655 });
656
657 $('#filter-mods button').on('click', function () {
658 state.cat = $(this).data('cat');
659 $('#filter-mods button').removeClass('is-active').attr('aria-selected', 'false');
660 $(this).addClass('is-active').attr('aria-selected', 'true');
661 render();
662 });
663
664 $('.wpda-scope button').on('click', function () {
665 state.scope = $(this).data('scope');
666 $('.wpda-scope button').removeClass('is-active').attr('aria-selected', 'false');
667 $(this).addClass('is-active').attr('aria-selected', 'true');
668 render();
669 });
670
671 $(document).on('keydown', function (e) {
672 if (e.key !== '/' || e.ctrlKey || e.metaKey || e.altKey) return;
673 var tag = (e.target.tagName || '').toLowerCase();
674 if (tag === 'input' || tag === 'textarea' || e.target.isContentEditable) return;
675 e.preventDefault();
676 $search.focus();
677 });
678 });
679 </script>
680