diff --git a/containers/marketplace/marketplace.config b/containers/marketplace/marketplace.config index 9c6100a..8c87c0f 100644 --- a/containers/marketplace/marketplace.config +++ b/containers/marketplace/marketplace.config @@ -31,8 +31,8 @@ CFG_MARKETPLACE_DEV_ONLY=true # CFG_MARKETPLACE_CATEGORY="system" CFG_MARKETPLACE_TITLE="LibrePortal Marketplace" -CFG_MARKETPLACE_DESCRIPTION="Host your own app catalog and registry" -CFG_MARKETPLACE_LONG_DESCRIPTION="Serves a signed LibrePortal artifact channel (apps, hotfixes, releases) plus a browsable marketplace website over it. The official marketplace runs this exact app; point any box's CFG_RELEASE_BASE_URL at your instance to use it" +CFG_MARKETPLACE_DESCRIPTION="App Catalog & Registry" +CFG_MARKETPLACE_LONG_DESCRIPTION="Host your own signed LibrePortal app catalog — browse and add apps from your own instance." CFG_MARKETPLACE_URL="https://github.com/Webstar/LibrePortal" CFG_MARKETPLACE_ACTIONS="configure|install|restart|shutdown|uninstall" # diff --git a/containers/marketplace/resources/site/index.html b/containers/marketplace/resources/site/index.html index ec1b862..8a816ce 100644 --- a/containers/marketplace/resources/site/index.html +++ b/containers/marketplace/resources/site/index.html @@ -70,26 +70,33 @@ .topbar .spacer { flex: 1; } .topbar .chip { font-size: 0.8rem; color: var(--text-muted); border: 1px solid var(--border-color); padding: 5px 11px; border-radius: 999px; } - /* Layout: sidebar + main. */ + /* Layout: sidebar + main — matches the App Center (apps-layout.css / + sidebar.css): a 220px full-height column, full-width category rows with + bottom-border separators, and the same search box. */ .apps-layout { display: flex; width: 100%; min-height: calc(100vh - 60px); } - .sidebar-container { flex-shrink: 0; width: 240px; background: var(--sidebar-bg); border-right: 1px solid var(--border-color); } - .sidebar { position: sticky; top: 60px; padding: 18px 12px; } - .apps-search { position: relative; margin-bottom: 14px; } + .sidebar-container { + flex-shrink: 0; width: 220px; background: var(--sidebar-bg); + border-right: 1px solid var(--sidebar-border); + backdrop-filter: blur(12px) saturate(140%); -webkit-backdrop-filter: blur(12px) saturate(140%); + } + .sidebar { position: sticky; top: 60px; display: flex; flex-direction: column; } + .apps-search { position: relative; padding: 14px 20px; border-bottom: 1px solid var(--sidebar-border); } + .apps-search-icon { position: absolute; left: 32px; top: 50%; transform: translateY(-50%); color: rgba(var(--text-rgb),0.55); pointer-events: none; } .apps-search input { - width: 100%; padding: 9px 12px; border-radius: 10px; border: 1px solid var(--input-border); - background: var(--input-bg); color: var(--text-primary); font-size: 0.9rem; outline: none; + width: 100%; padding: 9px 12px 9px 36px; border-radius: 8px; border: 1px solid rgba(var(--text-rgb),0.12); + background: rgba(var(--text-rgb),0.06); color: var(--text-primary); font-size: 13px; outline: none; + transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease; } - .apps-search input:focus { border-color: var(--accent); } - .cat-list { display: flex; flex-direction: column; gap: 2px; } + .apps-search input::placeholder { color: rgba(var(--text-rgb),0.5); } + .apps-search input:focus { background: rgba(var(--text-rgb),0.10); border-color: rgba(var(--accent-rgb),0.55); box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.16); } + .cat-list { display: flex; flex-direction: column; } .category { - display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 10px; - cursor: pointer; color: var(--text-secondary); font-size: 0.92rem; text-transform: capitalize; - border: 1px solid transparent; + display: flex; align-items: center; gap: 10px; padding: 15px 20px; + cursor: pointer; color: var(--text-secondary); font-size: 14px; text-transform: capitalize; + border-bottom: 1px solid var(--sidebar-border); transition: background 0.2s, color 0.2s; } - .category:hover { background: rgba(var(--text-rgb),0.06); color: var(--text-primary); } - .category.active { background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.35); color: #fff; } - .category .cat-ic { width: 16px; height: 16px; opacity: 0.9; flex-shrink: 0; } - .category .cat-n { margin-left: auto; font-size: 0.75rem; opacity: 0.6; } + .category:hover, .category.active { background: var(--surface-hover); color: var(--text-primary); } + .category img { width: 20px; height: 20px; flex-shrink: 0; } .main-content { flex: 1; min-width: 0; } .status-strip { @@ -171,7 +178,10 @@
@@ -218,17 +228,17 @@ return by; } + function catRow(id, label) { + // Real App Center category glyphs (bundled into the site by the install + // hook); misc.svg is the fallback for an unknown category. + return '
' + + '' + + '' + esc(label) + '
'; + } function renderCats() { - var by = counts(); - var list = Object.keys(by).sort(); - var rows = ['
' + - '' + - 'All' + state.apps.length + '
']; - list.forEach(function (c) { - rows.push('
' + - '' + - '' + esc(c) + '' + by[c] + '
'); - }); + var list = Object.keys(counts()).sort(); + var rows = [catRow('all', 'All')]; + list.forEach(function (c) { rows.push(catRow(c, c)); }); cats.innerHTML = rows.join(''); } diff --git a/containers/marketplace/scripts/marketplace_install_hooks.sh b/containers/marketplace/scripts/marketplace_install_hooks.sh index ba8bdd1..c56cf87 100644 --- a/containers/marketplace/scripts/marketplace_install_hooks.sh +++ b/containers/marketplace/scripts/marketplace_install_hooks.sh @@ -21,5 +21,14 @@ marketplace_install_post_setup() runFileOp mkdir -p "$dest" || return 1 runFileOp cp -f "$def/resources/site/index.html" "$dest/index.html" || return 1 runFileOp cp -f "$def/$app_name.svg" "$dest/marketplace.svg" || return 1 + + # Bundle the App Center's category icons so the site's sidebar matches the + # WebUI (same per-category glyphs). Copied from the live frontend so they + # stay in step; best-effort (the site falls back to misc.svg if absent). + local cat_src="$containers_dir/libreportal/frontend/core/icons/categories" + if [[ -d "$cat_src" ]]; then + runFileOp mkdir -p "$dest/categories" || true + runFileOp cp -f "$cat_src"/*.svg "$dest/categories/" 2>/dev/null || true + fi isSuccessful "Marketplace site seeded. Publish a catalog into it: rsync dist// $dest//" }