fix: BUG-33 CPU threshold, TASK-27 tab icons, TASK-36 iframe errors
- BUG-33: CPU load alert threshold increased from 2x to 4x core count (8→16 on 4-core machine) to reduce false alerts during container ops - TASK-27: Launch buttons for new-tab apps now show external link icon (BTCPay, Grafana, PhotoPrism, Portainer, OnlyOffice, etc.) - TASK-36: Iframe error screen now distinguishes between X-Frame-Options blocked vs container not reachable, with appropriate messaging Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,7 @@ const PORT_TO_APP_ID: Record<string, string> = {
|
||||
'18081': 'nostr-rs-relay',
|
||||
'7777': 'indeedhub',
|
||||
'50002': 'electrumx',
|
||||
'3010': 'thunderhub',
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -139,8 +139,11 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold text-white mb-2">This site blocks embedded viewing</h3>
|
||||
<p class="text-white/50 text-sm mb-6">{{ appTitle }} sets security headers that prevent iframe embedding.<br>Open it in a new browser tab instead.</p>
|
||||
<h3 class="text-lg font-semibold text-white mb-2">{{ mustOpenNewTab ? 'This app opens in a new tab' : 'App not reachable' }}</h3>
|
||||
<p class="text-white/50 text-sm mb-6">
|
||||
<template v-if="mustOpenNewTab">{{ appTitle }} sets security headers that prevent iframe embedding.<br>Open it in a new browser tab instead.</template>
|
||||
<template v-else>{{ appTitle }} may still be starting up or the container is stopped.<br>Try opening in a new tab or check the app status.</template>
|
||||
</p>
|
||||
<button
|
||||
@click="openNewTabAndBack"
|
||||
class="glass-button px-6 py-3 rounded-lg text-sm font-semibold inline-flex items-center gap-2"
|
||||
|
||||
@@ -146,9 +146,10 @@
|
||||
v-if="canLaunch(pkg)"
|
||||
data-controller-launch-btn
|
||||
@click.stop="launchApp(id as string)"
|
||||
class="flex-1 px-4 py-2 glass-button glass-button-sm rounded-lg text-sm font-medium"
|
||||
class="flex-1 px-4 py-2 glass-button glass-button-sm rounded-lg text-sm font-medium flex items-center justify-center gap-1.5"
|
||||
>
|
||||
{{ t('common.launch') }}
|
||||
<svg v-if="opensInTab(id as string)" class="w-3.5 h-3.5 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /></svg>
|
||||
</button>
|
||||
<button
|
||||
v-if="!isWebOnlyApp(id as string) && (pkg.state === 'stopped' || pkg.state === 'exited')"
|
||||
@@ -490,6 +491,17 @@ function canLaunch(pkg: PackageDataEntry): boolean {
|
||||
return !!hasUI && canLaunchState
|
||||
}
|
||||
|
||||
/** Apps that open in a new browser tab (X-Frame-Options blocks iframe) */
|
||||
const TAB_LAUNCH_APPS = new Set([
|
||||
'btcpay-server', 'grafana', 'photoprism', 'homeassistant',
|
||||
'vaultwarden', 'nextcloud', 'uptime-kuma', 'portainer',
|
||||
'onlyoffice', 'nginx-proxy-manager',
|
||||
])
|
||||
|
||||
function opensInTab(id: string): boolean {
|
||||
return TAB_LAUNCH_APPS.has(id)
|
||||
}
|
||||
|
||||
function launchApp(id: string) {
|
||||
useAppLauncherStore().openSession(id)
|
||||
}
|
||||
|
||||
@@ -735,7 +735,7 @@ async function loadCommunityMarketplace() {
|
||||
// Get app tier classification (matches backend get_app_tier)
|
||||
function getAppTier(appId: string): string {
|
||||
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
||||
const recommended = ['fedimint', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'portainer']
|
||||
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'portainer']
|
||||
if (core.includes(appId)) return 'core'
|
||||
if (recommended.includes(appId)) return 'recommended'
|
||||
return 'optional'
|
||||
@@ -777,6 +777,17 @@ function getCuratedAppList() {
|
||||
manifestUrl: undefined,
|
||||
repoUrl: 'https://github.com/lightningnetwork/lnd'
|
||||
},
|
||||
{
|
||||
id: 'thunderhub',
|
||||
title: 'ThunderHub',
|
||||
version: '0.13.31',
|
||||
description: 'Lightning node management UI. Manage channels, send and receive payments, view routing fees, and monitor your Lightning node.',
|
||||
icon: '/assets/img/app-icons/thunderhub.svg',
|
||||
author: 'Anthony Potdevin',
|
||||
dockerImage: 'docker.io/apotdevin/thunderhub:v0.13.31',
|
||||
manifestUrl: undefined,
|
||||
repoUrl: 'https://github.com/apotdevin/thunderhub'
|
||||
},
|
||||
{
|
||||
id: 'mempool',
|
||||
title: 'Mempool Explorer',
|
||||
|
||||
Reference in New Issue
Block a user