Replace v6 RC testing promo with a v6 availability notice

v6 went GA on 2026-07-04 but v5 installs are pinned to the 5.1.x line
by the updater, so they have no in-app signal that v6 exists. Rework
the existing release announcement fabric (dismissible banner plus the
Updates settings card) from RC-testing copy to a factual notice: v6 is
a new major version, upgrading is a manual step, link to the upgrade
guide and changelog on main. New announcement id so users who
dismissed the RC banner see the GA notice once; dismissal still
persists per browser. Updater line-pinning is untouched.
This commit is contained in:
rcourtman 2026-07-08 16:12:47 +01:00
parent 3cf61d5a37
commit 6c83a7becb
4 changed files with 38 additions and 63 deletions

View file

@ -4,11 +4,11 @@ import { useLocation } from '@solidjs/router';
import type { VersionInfo } from '@/api/updates';
import type { SecurityStatus } from '@/types/config';
import {
V6_RC_ANNOUNCEMENT,
shouldShowV6RcAnnouncement,
V6_GA_ANNOUNCEMENT,
shouldShowV6Announcement,
} from '@/constants/releaseAnnouncements';
import { createLocalStorageStringSignal, STORAGE_KEYS } from '@/utils/localStorage';
import FlaskConicalIcon from 'lucide-solid/icons/flask-conical';
import InfoIcon from 'lucide-solid/icons/info';
import ExternalLinkIcon from 'lucide-solid/icons/external-link';
import XIcon from 'lucide-solid/icons/x';
@ -23,7 +23,7 @@ export function ReleaseAnnouncementBanner(props: ReleaseAnnouncementBannerProps)
createLocalStorageStringSignal(STORAGE_KEYS.RELEASE_ANNOUNCEMENT_DISMISSED, '');
const isDismissed = createMemo(
() => dismissedAnnouncementId() === V6_RC_ANNOUNCEMENT.id,
() => dismissedAnnouncementId() === V6_GA_ANNOUNCEMENT.id,
);
const shouldShow = createMemo(() => {
@ -31,7 +31,7 @@ export function ReleaseAnnouncementBanner(props: ReleaseAnnouncementBannerProps)
return false;
}
return shouldShowV6RcAnnouncement({
return shouldShowV6Announcement({
version: props.versionInfo()?.version,
pathname: location.pathname,
securityStatus: props.securityStatus(),
@ -39,7 +39,7 @@ export function ReleaseAnnouncementBanner(props: ReleaseAnnouncementBannerProps)
});
const dismiss = () => {
setDismissedAnnouncementId(V6_RC_ANNOUNCEMENT.id);
setDismissedAnnouncementId(V6_GA_ANNOUNCEMENT.id);
};
return (
@ -49,50 +49,38 @@ export function ReleaseAnnouncementBanner(props: ReleaseAnnouncementBannerProps)
<div class="flex items-start justify-between gap-3">
<div class="flex min-w-0 flex-1 items-start gap-3">
<div class="mt-0.5 rounded-full bg-emerald-100 p-2 text-emerald-700 dark:bg-emerald-900/70 dark:text-emerald-200">
<FlaskConicalIcon class="h-4 w-4" />
<InfoIcon class="h-4 w-4" />
</div>
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold">Pulse v6 RC testing</span>
<span class="rounded-full bg-emerald-100 px-2 py-0.5 text-[11px] font-medium text-emerald-800 dark:bg-emerald-900/70 dark:text-emerald-200">
{V6_RC_ANNOUNCEMENT.tag}
</span>
<span class="text-sm font-semibold">Pulse v6 is available</span>
</div>
<p class="mt-1 text-sm leading-relaxed text-emerald-900/85 dark:text-emerald-100/85">
Pulse v6 is a new major version with a rebuilt interface and support for
more platforms. Installs on the{' '}
<code class="rounded bg-emerald-100 px-1 py-0.5 text-[12px] dark:bg-emerald-900/70">
5.1.x
</code>{' '}
remains the current stable line. Pulse v6 changes the runtime,
upgrade path, navigation, and product model substantially. If you rely on
Pulse today, test v6 in a staging or non-production environment and report
any issues before the stable cut.
line do not update to v6 automatically; upgrading is a manual step. See
the upgrade guide for what changes and how to move.
</p>
<div class="mt-3 flex flex-wrap items-center gap-2">
<a
href={V6_RC_ANNOUNCEMENT.changelogUrl}
href={V6_GA_ANNOUNCEMENT.upgradeGuideUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 rounded-md bg-emerald-700 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-emerald-800 dark:bg-emerald-600 dark:hover:bg-emerald-500"
>
Read v6 changelog
Upgrade guide
<ExternalLinkIcon class="h-3.5 w-3.5" />
</a>
<a
href={V6_RC_ANNOUNCEMENT.releaseUrl}
href={V6_GA_ANNOUNCEMENT.changelogUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 rounded-md border border-emerald-300 bg-white px-3 py-1.5 text-sm font-medium text-emerald-900 transition-colors hover:bg-emerald-100 dark:border-emerald-800 dark:bg-emerald-950/20 dark:text-emerald-100 dark:hover:bg-emerald-900/40"
>
View v6 RC
<ExternalLinkIcon class="h-3.5 w-3.5" />
</a>
<a
href={V6_RC_ANNOUNCEMENT.demoUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 rounded-md border border-transparent px-2 py-1.5 text-sm font-medium text-emerald-800 transition-colors hover:bg-emerald-100 dark:text-emerald-200 dark:hover:bg-emerald-900/30"
>
Open demo
v6 changelog
<ExternalLinkIcon class="h-3.5 w-3.5" />
</a>
</div>
@ -103,7 +91,7 @@ export function ReleaseAnnouncementBanner(props: ReleaseAnnouncementBannerProps)
onClick={dismiss}
class="rounded-md p-1 text-emerald-700 transition-colors hover:bg-emerald-100 hover:text-emerald-900 dark:text-emerald-300 dark:hover:bg-emerald-900/50 dark:hover:text-emerald-100"
title="Dismiss"
aria-label="Dismiss v6 RC announcement"
aria-label="Dismiss v6 announcement"
>
<XIcon class="h-4 w-4" />
</button>

View file

@ -8,7 +8,7 @@ import Package from 'lucide-solid/icons/package';
import Download from 'lucide-solid/icons/download';
import type { UpdateInfo, VersionInfo, UpdatePlan } from '@/api/updates';
import {
V6_RC_ANNOUNCEMENT,
V6_GA_ANNOUNCEMENT,
V5_MAINTENANCE_BRANCH,
isV5ReleaseLine,
} from '@/constants/releaseAnnouncements';
@ -50,47 +50,36 @@ export const UpdatesSettingsPanel: Component<UpdatesSettingsPanelProps> = (props
<div class="space-y-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold text-emerald-900 dark:text-emerald-100">
Pulse v6 RC testing
</span>
<span class="inline-flex items-center rounded-full bg-emerald-100 px-2 py-0.5 text-[10px] font-medium text-emerald-800 dark:bg-emerald-900/70 dark:text-emerald-200">
{V6_RC_ANNOUNCEMENT.tag}
Pulse v6 is available
</span>
</div>
<p class="text-sm text-emerald-900/85 dark:text-emerald-100/85">
Pulse v6 is a new major version with a rebuilt interface and support
for more platforms. Installs on the{' '}
<code class="rounded bg-emerald-100 px-1 py-0.5 text-[12px] dark:bg-emerald-900/70">
5.1.x
</code>{' '}
remains the stable line. If you can, test v6 in a staging or
non-production environment and use the changelog before upgrading so the
move from v5 is deliberate rather than guesswork.
line do not update to v6 automatically; upgrading is a manual step
covered in the upgrade guide.
</p>
</div>
<div class="flex flex-wrap items-center gap-2">
<a
href={V6_RC_ANNOUNCEMENT.changelogUrl}
href={V6_GA_ANNOUNCEMENT.upgradeGuideUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 rounded-lg bg-emerald-700 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-emerald-800 dark:bg-emerald-600 dark:hover:bg-emerald-500"
>
Read v6 changelog
<Download class="w-4 h-4" />
Upgrade guide
<ArrowRight class="w-4 h-4" />
</a>
<a
href={V6_RC_ANNOUNCEMENT.releaseUrl}
href={V6_GA_ANNOUNCEMENT.changelogUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 rounded-lg border border-emerald-300 px-3 py-2 text-sm font-medium text-emerald-900 transition-colors hover:bg-emerald-100 dark:border-emerald-800 dark:text-emerald-100 dark:hover:bg-emerald-900/40"
>
View v6 RC
<ArrowRight class="w-4 h-4" />
</a>
<a
href={V6_RC_ANNOUNCEMENT.demoUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-1 rounded-lg px-3 py-2 text-sm font-medium text-emerald-800 transition-colors hover:bg-emerald-100 dark:text-emerald-200 dark:hover:bg-emerald-900/30"
>
Open demo
v6 changelog
<ArrowRight class="w-4 h-4" />
</a>
</div>

View file

@ -3,7 +3,7 @@ import type { SecurityStatus } from '@/types/config';
import {
canSeeAdminReleaseAnnouncement,
isV5ReleaseLine,
shouldShowV6RcAnnouncement,
shouldShowV6Announcement,
} from '@/constants/releaseAnnouncements';
describe('releaseAnnouncements', () => {
@ -34,28 +34,28 @@ describe('releaseAnnouncements', () => {
it('shows the announcement only on the supported v5 surfaces', () => {
expect(
shouldShowV6RcAnnouncement({
shouldShowV6Announcement({
version: 'v5.1.27',
pathname: '/proxmox/overview',
}),
).toBe(true);
expect(
shouldShowV6RcAnnouncement({
shouldShowV6Announcement({
version: 'v5.1.27',
pathname: '/settings/updates',
}),
).toBe(true);
expect(
shouldShowV6RcAnnouncement({
shouldShowV6Announcement({
version: 'v5.1.27',
pathname: '/alerts/overview',
}),
).toBe(false);
expect(
shouldShowV6RcAnnouncement({
shouldShowV6Announcement({
version: 'v6.0.0-rc.1',
pathname: '/settings/updates',
}),

View file

@ -2,12 +2,10 @@ import type { SecurityStatus } from '@/types/config';
export const V5_MAINTENANCE_BRANCH = 'release/5.1';
export const V6_RC_ANNOUNCEMENT = {
id: 'v6-rc-testing-v6.0.0-rc.1',
tag: 'v6.0.0-rc.1',
releaseUrl: 'https://github.com/rcourtman/Pulse/releases/tag/v6.0.0-rc.1',
changelogUrl: 'https://github.com/rcourtman/Pulse/blob/pulse/v6-release/docs/releases/V6_CHANGELOG.md',
demoUrl: 'https://v6-demo.pulserelay.pro',
export const V6_GA_ANNOUNCEMENT = {
id: 'v6-ga-available',
upgradeGuideUrl: 'https://github.com/rcourtman/Pulse/blob/main/docs/UPGRADE_v6.md',
changelogUrl: 'https://github.com/rcourtman/Pulse/blob/main/docs/releases/V6_CHANGELOG.md',
} as const;
function parseMajorVersion(version?: string | null): number | null {
@ -38,7 +36,7 @@ export function canSeeAdminReleaseAnnouncement(
return securityStatus.proxyAuthIsAdmin === true;
}
export function shouldShowV6RcAnnouncement(opts: {
export function shouldShowV6Announcement(opts: {
version?: string | null;
pathname?: string | null;
securityStatus?: SecurityStatus | null;