Skip to content

Commit 6c09882

Browse files
authored
feat: add quick install button for plugins in sidebar (#1115)
1 parent 3e4617e commit 6c09882

File tree

2 files changed

+89
-20
lines changed

2 files changed

+89
-20
lines changed

src/sidebarApps/extensions/index.js

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -358,41 +358,83 @@ function ListItem({ icon, name, id, version, downloads, installed }) {
358358
data-action="more-plugin-action"
359359
></span>
360360
) : (
361-
""
361+
<button className="install-btn" data-action="install-plugin">
362+
<span className="icon file_downloadget_app"></span>
363+
</button>
362364
)}
363365
</div>
364366
);
365367

366-
$el.onclick = (event) => {
368+
$el.onclick = async (event) => {
367369
const morePluginActionButton = event.target.closest(
368370
'[data-action="more-plugin-action"]',
369371
);
372+
const installPluginBtn = event.target.closest(
373+
'[data-action="install-plugin"]',
374+
);
370375
if (morePluginActionButton) {
371376
more_plugin_action(id, name);
372377
return;
378+
} else if (installPluginBtn) {
379+
try {
380+
let purchaseToken = null;
381+
const pluginUrl = Url.join(constants.API_BASE, `plugin/${id}`);
382+
const remotePlugin = await fsOperation(pluginUrl)
383+
.readFile("json")
384+
.catch(() => {
385+
throw new Error("Failed to fetch plugin details");
386+
});
387+
388+
if (remotePlugin && Number.parseFloat(remotePlugin.price) > 0) {
389+
try {
390+
const [product] = await helpers.promisify(iap.getProducts, [
391+
remotePlugin.sku,
392+
]);
393+
if (product) {
394+
async function getPurchase(sku) {
395+
const purchases = await helpers.promisify(iap.getPurchases);
396+
const purchase = purchases.find((p) =>
397+
p.productIds.includes(sku),
398+
);
399+
return purchase;
400+
}
401+
const purchase = await getPurchase(product.productId);
402+
purchaseToken = purchase?.purchaseToken;
403+
}
404+
} catch (error) {
405+
helpers.error(error);
406+
throw new Error("Failed to validate purchase");
407+
}
408+
}
409+
410+
const { default: installPlugin } = await import("lib/installPlugin");
411+
await installPlugin(id, remotePlugin.name, purchaseToken);
412+
window.toast(strings["success"], 3000);
413+
$explore.ontoggle();
414+
} catch (err) {
415+
console.error(err);
416+
window.toast(helpers.errorMessage(err), 3000);
417+
}
418+
return;
373419
}
374420

375421
plugin(
376422
{ id, installed },
377423
() => {
378-
const $item = () => (
379-
<ListItem
380-
icon={icon}
381-
name={name}
382-
id={id}
383-
version={version}
384-
installed={true}
385-
/>
386-
);
387-
if ($installed.contains($el))
388-
$installed.$ul?.replaceChild($item(), $el);
389-
else $installed.$ul?.append($item());
390-
if ($explore.contains($el)) $explore.$ul?.replaceChild($item(), $el);
391-
if ($searchResult.contains($el))
392-
$searchResult?.replaceChild($item(), $el);
424+
if (!$explore.collapsed) {
425+
$explore.ontoggle();
426+
}
427+
if (!$installed.collapsed) {
428+
$installed.ontoggle();
429+
}
393430
},
394431
() => {
395-
$el.remove();
432+
if (!$explore.collapsed) {
433+
$explore.ontoggle();
434+
}
435+
if (!$installed.collapsed) {
436+
$installed.ontoggle();
437+
}
396438
},
397439
);
398440
};
@@ -449,8 +491,12 @@ async function more_plugin_action(id, pluginName) {
449491
break;
450492
case strings.uninstall:
451493
await uninstall(id);
452-
const $plugin = $installed.querySelector(`[data-plugin-id="${id}"]`);
453-
$plugin.remove();
494+
if (!$explore.collapsed) {
495+
$explore.ontoggle();
496+
}
497+
if (!$installed.collapsed) {
498+
$installed.ontoggle();
499+
}
454500
break;
455501
}
456502
}

src/sidebarApps/extensions/style.scss

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,34 @@
7272
display: flex;
7373
align-items: center;
7474
cursor: pointer;
75+
justify-content: center;
7576
transition: background-color 0.3s ease;
77+
margin-left: 10px;
7678

7779
&:hover {
7880
background-color: var(--active-icon-color);
7981
}
8082
}
83+
84+
.install-btn {
85+
background: none;
86+
border: none;
87+
margin-left: 10px;
88+
border-radius: 50%;
89+
cursor: pointer;
90+
color: var(--primary-text-color);
91+
transition: all 0.3s ease;
92+
display: flex;
93+
align-items: center;
94+
justify-content: center;
95+
96+
&:hover {
97+
background-color: var(--active-icon-color);
98+
}
99+
100+
&:active {
101+
transform: scale(0.95);
102+
}
103+
}
81104
}
82105
}

0 commit comments

Comments
 (0)