feat: linkify #NNN references in ChangeLog to Codeberg issues

Closes #472

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas SharedInbox
2026-06-06 21:51:13 +02:00
co-authored by Claude Sonnet 4.6
parent 913f9e8855
commit e22322166c
2 changed files with 27 additions and 1 deletions
+13 -1
View File
@@ -31,6 +31,17 @@ class ChangeLogScreen extends ConsumerWidget {
return '$h:$m, ${dt.day} $month ${dt.year}'; return '$h:$m, ${dt.day} $month ${dt.year}';
} }
static const _repoUrl = 'https://codeberg.org/guettli/sharedinbox';
static final _issueRefPattern = RegExp(r'#(\d+)');
static String _linkifyIssueRefs(String text) {
return text.replaceAllMapped(
_issueRefPattern,
(m) => '[#${m[1]}]($_repoUrl/issues/${m[1]})',
);
}
// Changelog lines have the form: // Changelog lines have the form:
// * 2026-06-05 [abc1234](https://...): subject // * 2026-06-05 [abc1234](https://...): subject
// This pattern captures the short hash inside the markdown link. // This pattern captures the short hash inside the markdown link.
@@ -82,7 +93,8 @@ class ChangeLogScreen extends ConsumerWidget {
child: Text('Error loading changelog: ${snapshot.error}'), child: Text('Error loading changelog: ${snapshot.error}'),
); );
} }
final content = snapshot.data ?? 'No changelog entries found.'; final raw = snapshot.data ?? 'No changelog entries found.';
final content = _linkifyIssueRefs(raw);
final versions = installedVersions.value ?? {}; final versions = installedVersions.value ?? {};
final annotated = _injectInstallMarkers(content, versions); final annotated = _injectInstallMarkers(content, versions);
return Markdown( return Markdown(
+14
View File
@@ -102,4 +102,18 @@ void main() {
expect(find.textContaining('Installed:'), findsNothing); expect(find.textContaining('Installed:'), findsNothing);
expect(find.textContaining('initial release'), findsOneWidget); expect(find.textContaining('initial release'), findsOneWidget);
}); });
testWidgets('ChangeLogScreen renders #NNN as a tappable link', (
tester,
) async {
const changelog = '* 2024-03-01 fix: resolve crash, see #42\n';
await tester.pumpWidget(
_buildScreen(assets: {'assets/changelog.txt': changelog}),
);
await tester.pumpAndSettle();
// The link text "#42" must be visible in the rendered output.
expect(find.textContaining('#42'), findsOneWidget);
});
} }