the update dialog no longer shows an unreleased version as the target
This commit is contained in:
5 files changed
+60
-4
No files matched your search
@@ -3,6 +3,7 @@
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Sparkles, Bug, Zap, CheckCircle, ScrollText } from 'lucide-svelte';
|
||||
import { compareVersions } from '$lib/utils/version';
|
||||
import { releasedEntries } from '$lib/utils/changelog-filter';
|
||||
import ChangelogText from '$lib/components/ChangelogText.svelte';
|
||||
|
||||
interface ChangelogEntry {
|
||||
@@ -10,6 +11,7 @@
|
||||
date: string;
|
||||
changes: Array<{ type: string; text: string }>;
|
||||
imageTag?: string;
|
||||
comingSoon?: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -22,9 +24,11 @@
|
||||
|
||||
let { open = $bindable(), version, changelog, lastSeenVersion, onDismiss }: Props = $props();
|
||||
|
||||
// Filter to show versions newer than lastSeenVersion, limited to 3 most recent
|
||||
// Versions newer than lastSeenVersion, 3 most recent. Coming-soon (unreleased)
|
||||
// entries are excluded: the user is on a released build, so an unreleased version
|
||||
// must never appear as something they "missed".
|
||||
const missedReleases = $derived(
|
||||
changelog
|
||||
releasedEntries(changelog)
|
||||
.filter((r) => {
|
||||
if (!lastSeenVersion) return true; // Show all if first time
|
||||
return compareVersions(r.version, lastSeenVersion.replace(/^v/, '')) > 0;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// A coming-soon changelog entry (comingSoon: true) is an unreleased placeholder
|
||||
// used for the webpage's "what's next" section. It must never appear in the app's
|
||||
// released-version surfaces (About list, What's New, self-update release notes),
|
||||
// which otherwise render it as the latest shipped version.
|
||||
|
||||
export interface ChangelogEntryLike {
|
||||
comingSoon?: boolean;
|
||||
}
|
||||
|
||||
/** Drop unreleased (comingSoon) entries, keeping only shipped releases. */
|
||||
export function releasedEntries<T extends ChangelogEntryLike>(entries: T[]): T[] {
|
||||
return entries.filter((e) => !e.comingSoon);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
// Trigger rebuild for debug logging changes
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import { releasedEntries } from '$lib/utils/changelog-filter';
|
||||
import { Badge } from '$lib/components/ui/badge';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
@@ -33,6 +34,7 @@
|
||||
date: string;
|
||||
changes: ChangelogChange[];
|
||||
imageTag: string;
|
||||
comingSoon?: boolean;
|
||||
}
|
||||
|
||||
let dependencies = $state<Dependency[]>([]);
|
||||
@@ -84,7 +86,9 @@
|
||||
try {
|
||||
const res = await fetch('/api/changelog');
|
||||
if (!res.ok) throw new Error('Failed to fetch changelog');
|
||||
changelog = await res.json();
|
||||
// Shipped releases only: an unreleased (coming-soon) entry must not show as
|
||||
// the "Latest" version.
|
||||
changelog = releasedEntries(await res.json());
|
||||
} catch (e) {
|
||||
changelogError = e instanceof Error ? e.message : 'Unknown error';
|
||||
} finally {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import * as Dialog from '$lib/components/ui/dialog';
|
||||
import { releasedEntries } from '$lib/utils/changelog-filter';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Badge } from '$lib/components/ui/badge';
|
||||
import { Progress } from '$lib/components/ui/progress';
|
||||
@@ -12,6 +13,7 @@
|
||||
date: string;
|
||||
changes: Array<{ type: string; text: string }>;
|
||||
imageTag?: string;
|
||||
comingSoon?: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -159,7 +161,9 @@
|
||||
);
|
||||
|
||||
if (response.ok) {
|
||||
const changelog: ChangelogEntry[] = await response.json();
|
||||
// Drop coming-soon (unreleased) entries: the update only ever goes to a
|
||||
// released version, so an unreleased changelog entry must not appear here.
|
||||
const changelog: ChangelogEntry[] = releasedEntries(await response.json());
|
||||
if (currentVersion && changelog.length > 0) {
|
||||
const newer = changelog.filter(entry => compareVersions(entry.version, currentVersion) > 0);
|
||||
releaseNotes = newer.length > 0 ? newer : changelog.slice(0, 1);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { describe, test, expect } from 'bun:test';
|
||||
import { releasedEntries } from '../src/lib/utils/changelog-filter';
|
||||
|
||||
describe('releasedEntries', () => {
|
||||
test('drops coming-soon (unreleased) entries', () => {
|
||||
const entries = [
|
||||
{ version: '1.0.48', comingSoon: true },
|
||||
{ version: '1.0.47' },
|
||||
{ version: '1.0.46', comingSoon: false }
|
||||
];
|
||||
expect(releasedEntries(entries).map((e) => e.version)).toEqual(['1.0.47', '1.0.46']);
|
||||
});
|
||||
|
||||
test('keeps everything when nothing is coming-soon', () => {
|
||||
const entries = [{ version: '1.0.47' }, { version: '1.0.46' }];
|
||||
expect(releasedEntries(entries)).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('empty in, empty out', () => {
|
||||
expect(releasedEntries([])).toEqual([]);
|
||||
});
|
||||
|
||||
test('the top entry being coming-soon does not become the latest released', () => {
|
||||
// The regression case: user on an older build, changelog[0] is an unreleased entry.
|
||||
const entries = [
|
||||
{ version: '1.0.48', comingSoon: true },
|
||||
{ version: '1.0.47' }
|
||||
];
|
||||
expect(releasedEntries(entries)[0].version).toBe('1.0.47');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user