fix: route installs to apps or services
Demo images / Build & push demo images (push) Successful in 3m39s

This commit is contained in:
archipelago
2026-09-12 15:07:33 -04:00
parent d35474f774
commit c4aa72dccc
6 changed files with 32 additions and 7 deletions
+13 -4
View File
@@ -365,6 +365,7 @@ import AppGrid from './discover/AppGrid.vue'
import InstallVersionModal from '@/components/InstallVersionModal.vue'
import type { MarketplaceApp, FeaturedApp } from './discover/types'
import { getCuratedAppList, INSTALLED_ALIASES, FEATURED_DEFINITIONS, categorizeCommunityApp, fetchAppCatalog, type CatalogFeatured, type CatalogStorefront } from './discover/curatedApps'
import { isServiceContainer } from './apps/serviceNames'
const router = useRouter()
const store = useAppStore()
@@ -733,6 +734,16 @@ onBeforeUnmount(() => {
const toast = useToast()
function installToast(app: MarketplaceApp) {
const service = isServiceContainer(app.id)
const destination = service ? 'Services' : 'My Apps'
toast.action(
`Installing ${app.title ?? app.id} — it will appear in ${destination}`,
{ label: `View ${destination}`, onClick: () => router.push({ path: '/dashboard/apps', query: service ? { tab: 'services' } : {} }) },
{ variant: 'info', duration: 15000 },
)
}
function installBlockedReason(appId: string): string | undefined {
if (!bitcoinPruned.value) return undefined
if (appId !== 'electrumx' && appId !== 'electrs' && appId !== 'mempool-electrs') return undefined
@@ -766,8 +777,7 @@ function failInstall(app: MarketplaceApp, err: unknown) {
async function installApp(app: MarketplaceApp, versionOverride?: string) {
if (installingApps.has(app.id) || isInstalled(app.id)) return
queueInstall(app)
toast.info("Installing " + (app.title ?? app.id) + " - check My Apps")
router.push('/dashboard/apps').catch(() => {})
installToast(app)
try {
const installUrl = app.url || app.manifestUrl || app.s9pkUrl
await rpcClient.call({ method: 'package.install', params: { id: app.id, url: installUrl, version: versionOverride || app.version }, timeout: 600000 })
@@ -780,8 +790,7 @@ async function installApp(app: MarketplaceApp, versionOverride?: string) {
async function installCommunityApp(app: MarketplaceApp, versionOverride?: string) {
if (installingApps.has(app.id) || isInstalled(app.id) || !app.dockerImage) return
queueInstall(app)
toast.info("Installing " + (app.title ?? app.id) + " - check My Apps")
router.push('/dashboard/apps').catch(() => {})
installToast(app)
try {
const installParams: Record<string, unknown> = { id: app.id, dockerImage: app.dockerImage, version: versionOverride || app.version }
if ((app as Record<string, unknown>).containerConfig) {
+14 -2
View File
@@ -185,6 +185,7 @@ import {
getCuratedAppList,
} from './marketplace/marketplaceData'
import { fetchAppCatalog } from './discover/curatedApps'
import { isServiceContainer } from './apps/serviceNames'
const router = useRouter()
const route = useRoute()
@@ -207,6 +208,17 @@ const appStoreSections = computed(() => APP_STORE_SECTIONS)
const installingApps = server.installingApps
const electrumxArchiveWarning = 'You need a full archival bitcoin node before downloading ElectrumX'
function installToast(app: MarketplaceApp) {
const service = isServiceContainer(app.id)
const tab = service ? 'services' : 'apps'
const destination = service ? 'Services' : 'My Apps'
toast.action(
`Installing ${app.title ?? app.id} — it will appear in ${destination}`,
{ label: `View ${destination}`, onClick: () => router.push({ path: '/dashboard/apps', query: service ? { tab } : {} }) },
{ variant: 'info', duration: 15000 },
)
}
// Install progress tracking is now in serverStore (global watcher on WebSocket data)
// so it works regardless of which page is active
@@ -518,7 +530,7 @@ async function installApp(app: MarketplaceApp) {
// Stay on the store page: the tile itself shows install progress via the
// global watcher, and a forced jump to My Apps yanked the user out of the
// page they were deliberately browsing.
toast.info("Installing " + (app.title ?? app.id) + " — it will appear in My Apps")
installToast(app)
try {
const installUrl = app.url || app.manifestUrl || app.s9pkUrl
@@ -543,7 +555,7 @@ async function installCommunityApp(app: MarketplaceApp) {
queueInstall(app)
// Stay on the store page (see installApp).
toast.info("Installing " + (app.title ?? app.id) + " — it will appear in My Apps")
installToast(app)
try {
const installParams: Record<string, unknown> = { id: app.id, dockerImage: app.dockerImage, version: app.version }
+1 -1
View File
@@ -37,7 +37,7 @@ export function isServicePackage(id: string, pkg?: PackageDataEntry): boolean {
// Known app -> category mappings (matches App Store categorisation)
export const APP_CATEGORY_MAP: Record<string, string> = {
'bitcoin-core': 'money', 'bitcoin-knots': 'money', 'bitcoin-ui': 'money', 'electrumx': 'money', 'electrs': 'money',
'bitcoin-core': 'money', 'bitcoin-knots': 'money', 'bitcoin-ui': 'money', 'cuprate-ui': 'money', 'electrumx': 'money', 'electrs': 'money',
'lnd': 'money', 'mempool': 'money', 'mempool-web': 'money', 'btcpay-server': 'commerce',
'fedimint': 'money', 'fedimint-gateway': 'money',
'indeedhub': 'media', 'jellyfin': 'media', 'photoprism': 'media', 'immich': 'media',
+2
View File
@@ -14,6 +14,8 @@
// SERVICE_NAMES set that used to live in appsConfig.ts verbatim.
export const SERVICE_NAMES = new Set([
'dwn', 'archy-mempool-db', 'archy-btcpay-db', 'archy-nbxplorer', 'archy-tor',
// Cuprate's daemon is the backend dependency of the Cuprate UI app.
'cuprate',
// Headless backends with no user-facing UI: the Fedimint ecash client daemon,
// the Nostr relay, and the Meshtastic LoRa daemon (its chat UI lives in the
// built-in Mesh tab) belong in Services, not My Apps.
@@ -308,6 +308,7 @@ export function getCuratedAppList(): MarketplaceApp[] {
// Supporting containers (DBs, caches, workers) do NOT — having only a DB
// without the main app should not mark the app as installed in the UI.
export const INSTALLED_ALIASES: Record<string, string[]> = {
'cuprate-ui': ['cuprate-ui', 'cuprate'],
mempool: ['mempool', 'mempool-web', 'archy-mempool-web'],
bitcoin: ['bitcoin-knots'],
btcpay: ['btcpay-server'],
@@ -68,6 +68,7 @@ const REGISTRY = 'source.archipelago-foundation.org/lfg2025'
/** Marketplace app ID -> backend package keys (for "Already Installed" when first-boot/deploy created them) */
export const INSTALLED_ALIASES: Record<string, string[]> = {
'cuprate-ui': ['cuprate-ui', 'cuprate'],
mempool: ['mempool-web', 'mempool-api', 'archy-mempool-web', 'archy-mempool-db'],
bitcoin: ['bitcoin-knots'],
btcpay: ['btcpay-server', 'archy-btcpay-db', 'archy-nbxplorer'],