Feat: Update-All Extensions Button

This commit is contained in:
Youwes09
2026-04-25 17:22:13 -05:00
parent b5f96a3a5c
commit 63258b2aa1
2 changed files with 24 additions and 4 deletions
@@ -1,5 +1,5 @@
<script lang="ts">
import { MagnifyingGlass, ArrowsClockwise, Plus, GitBranch } from "phosphor-svelte";
import { MagnifyingGlass, ArrowsClockwise, Plus, GitBranch, ArrowCircleUp } from "phosphor-svelte";
import { FILTERS, type Filter, type Panel } from "../lib/extensionHelpers";
interface Props {
@@ -8,6 +8,7 @@
panel: Panel;
refreshing: boolean;
updateCount: number;
updatingAll: boolean;
availableLangs: string[];
langFilter: string | null;
anims: boolean;
@@ -18,14 +19,15 @@
onLang: (lang: string | null) => void;
onPanel: (p: Panel) => void;
onRefresh: () => void;
onUpdateAll: () => void;
}
let {
filter, search, panel, refreshing, updateCount,
filter, search, panel, refreshing, updateCount, updatingAll,
availableLangs, langFilter,
anims, tabIndicator,
tabsEl = $bindable(),
onFilter, onSearch, onLang, onPanel, onRefresh,
onFilter, onSearch, onLang, onPanel, onRefresh, onUpdateAll,
}: Props = $props();
</script>
@@ -57,6 +59,11 @@
<button class="icon-btn" onclick={onRefresh} disabled={refreshing} title="Refresh repo">
<ArrowsClockwise size={14} weight="light" class={refreshing ? "anim-spin" : ""} />
</button>
{#if updateCount > 0}
<button class="icon-btn update-badge" onclick={onUpdateAll} disabled={updatingAll} title="Update all ({updateCount})">
<ArrowCircleUp size={14} weight="fill" class={updatingAll ? "anim-spin" : ""} />
</button>
{/if}
</div>
</div>
@@ -90,6 +97,8 @@
.search { background: var(--bg-raised); border: 1px solid var(--border-dim); border-radius: var(--radius-md); padding: 5px 10px 5px 26px; color: var(--text-primary); font-size: var(--text-sm); width: 160px; outline: none; transition: border-color var(--t-base); }
.search::placeholder { color: var(--text-faint); }
.search:focus { border-color: var(--border-strong); }
.icon-btn.update-badge { color: var(--accent-fg); }
.icon-btn.update-badge:hover:not(:disabled) { background: var(--accent-muted); }
.lang-bar { display: flex; align-items: center; gap: 4px; padding: var(--sp-2) var(--sp-6); flex-shrink: 0; flex-wrap: wrap; border-bottom: 1px solid var(--border-dim); }
.lang-pill { font-family: var(--font-ui); font-size: var(--text-2xs); letter-spacing: var(--tracking-wider); text-transform: uppercase; padding: 3px 9px; border-radius: var(--radius-sm); border: 1px solid var(--border-dim); background: none; color: var(--text-faint); cursor: pointer; transition: color var(--t-fast), background var(--t-fast), border-color var(--t-fast); }
.lang-pill:hover { color: var(--text-muted); border-color: var(--border-strong); background: var(--bg-raised); }
@@ -29,6 +29,7 @@
let search = $state("");
let langFilter = $state<string | null>(null);
let working = $state(new Set<string>());
let updatingAll = $state(false);
let expanded = $state(new Set<string>());
let panel = $state<Panel>(null);
@@ -124,6 +125,15 @@
}
}
async function updateAll() {
const pending = extensions.filter((e) => e.hasUpdate);
if (!pending.length || updatingAll) return;
updatingAll = true;
for (const ext of pending) await mutate(ext.pkgName, "update");
updatingAll = false;
addToast({ kind: "success", title: "All extensions updated", body: `${pending.length} extension${pending.length === 1 ? "" : "s"} updated` });
}
async function installExternal() {
const url = externalUrl.trim();
const err = validateUrl(url, ".apk");
@@ -206,13 +216,14 @@
<div class="root anim-fade-in">
<ExtensionFilters
{filter} {search} {panel} {refreshing} {updateCount} {availableLangs} {langFilter}
{anims} {tabIndicator}
{anims} {tabIndicator} {updatingAll}
bind:tabsEl
onFilter={setFilter}
onSearch={(q) => search = q}
onLang={(l) => langFilter = l}
onPanel={openPanel}
onRefresh={fetchFromRepo}
onUpdateAll={updateAll}
/>
{#if panel === "apk"}