Changelog and What's new: CHANGELOG.md cut into each release, shown in the update band, a What's new card and once after updating

CHANGELOG.md keeps an Unreleased section (user-facing changes add a line in
the same commit); tool/release.sh cuts it into the version, the manifest
gets a structured "changes" field next to the one-line "notes" older
apps read, and the Gitea release text is that section. The app's update
band shows the top items, What's new opens a card (Added / Changed /
Fixed), and the first start after an update shows it once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-18 02:11:37 +03:00
1 parent ec0849eb01
commit 638a30e16c
22 files changed
+1637 -58

No files matched your search

+41
View File
@@ -190,6 +190,47 @@ void main() {
isTrue);
});
test('manifest changes: structured lists, notes kept, old manifests without', () {
final base = {
'version': '1.3.3',
'protocol': RelayConstants.protoVersion,
'url': 'https://x/y.tar.gz',
'notes': 'One line for older apps.',
};
final old = UpdateManifest.fromJson(base);
expect(old.changes, isNull);
expect(old.notes, 'One line for older apps.');
final m = UpdateManifest.fromJson({
...base,
'changes': {
'added': ['Danmaku style notifications', ' ', 7],
'fixed': ['Various bug fixes'],
'later': ['unknown kinds are ignored'],
},
});
expect(m.notes, 'One line for older apps.');
expect(m.changes!.added, ['Danmaku style notifications']);
expect(m.changes!.changed, isEmpty);
expect(m.changes!.fixed, ['Various bug fixes']);
expect(m.changes!.length, 2);
expect(ReleaseChanges.fromJson(m.changes!.toJson())!.toJson(), m.changes!.toJson());
// Junk or empty `changes` (and a non-string `notes`) do not break the manifest.
for (final junk in [null, 'text', [], {}, {'added': 'no list'}]) {
expect(UpdateManifest.fromJson({...base, 'changes': junk}).changes, isNull);
}
expect(UpdateManifest.fromJson({...base, 'notes': 3}).notes, '');
});
test('the repo manifest parses, and keeps a one-line string notes for 1.2.x/1.3.x', () {
final json = jsonDecode(File('../../updates/manifest.json').readAsStringSync()) as Map<String, Object?>;
// Older apps read `(json['notes'] as String?)`: it must stay a string.
expect(json['notes'], isA<String>());
expect((json['notes'] as String).contains('\n'), isFalse);
expect(UpdateManifest.fromJson(json, platform: 'linux-x64').version, json['version']);
});
test('manifest picks the asset for this platform', () {
final json = {
'version': '0.2.2',