diff --git a/lib/ui/screens/changelog_screen.dart b/lib/ui/screens/changelog_screen.dart index 2012242..aa13b25 100644 --- a/lib/ui/screens/changelog_screen.dart +++ b/lib/ui/screens/changelog_screen.dart @@ -31,6 +31,17 @@ class ChangeLogScreen extends ConsumerWidget { 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: // * 2026-06-05 [abc1234](https://...): subject // 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}'), ); } - 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 annotated = _injectInstallMarkers(content, versions); return Markdown( diff --git a/test/widget/changelog_screen_test.dart b/test/widget/changelog_screen_test.dart index 6d9aae3..13f22cc 100644 --- a/test/widget/changelog_screen_test.dart +++ b/test/widget/changelog_screen_test.dart @@ -102,4 +102,18 @@ void main() { expect(find.textContaining('Installed:'), findsNothing); 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); + }); }