improved Uri display formatting

This commit is contained in:
Fabian Freund
2026-04-28 17:55:48 +02:00
parent 4a54b8ee83
commit 845c9a1cfc
3 changed files with 46 additions and 18 deletions
+9 -12
View File
@@ -47,18 +47,11 @@ extension UriX on Uri {
return '';
}
final segments = pathSegments.join('/');
final buffer = StringBuffer();
if (path.startsWith('/')) {
buffer.write('/');
try {
return Uri.decodeComponent(path);
} on FormatException {
return path;
}
buffer.write(segments);
if (path.length > 1 && path.endsWith('/')) {
buffer.write('/');
}
return buffer.toString();
}
String get displayString {
@@ -94,6 +87,10 @@ extension UriStringX on String {
if (uri == null || uri.toString() != this) {
return this;
}
return uri.displayString;
try {
return uri.displayString;
} on FormatException {
return this;
}
}
}
@@ -21,6 +21,7 @@ import 'dart:convert';
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
import 'package:nullability/nullability.dart';
import 'package:weblibre/extensions/uri.dart';
import 'package:weblibre/features/geckoview/features/contextmenu/domain/converters/hit_result_converter.dart';
extension HitResultJson on HitResult {
@@ -82,14 +83,15 @@ extension HitResultX on HitResult {
const maxTitleLength = 2500;
return switch (this) {
UnknownHitResult(src: final src) => src,
ImageSrcHitResult(uri: final uri) => uri,
ImageHitResult(src: final src, title: final title) =>
title.isEmpty ? (src.length > maxTitleLength ? 'image' : src) : title!,
UnknownHitResult(src: final src) => src.uriDisplayString,
ImageSrcHitResult(uri: final uri) => uri.uriDisplayString,
ImageHitResult(src: final src, title: final title) => title.isEmpty
? (src.length > maxTitleLength ? 'image' : src.uriDisplayString)
: title!,
VideoHitResult(src: final src, title: final title) =>
(title.isEmpty) ? src : title!,
(title.isEmpty) ? src.uriDisplayString : title!,
AudioHitResult(src: final src, title: final title) =>
(title.isEmpty) ? src : title!,
(title.isEmpty) ? src.uriDisplayString : title!,
_ => 'about:blank',
};
}
@@ -65,5 +65,34 @@ void main() {
'https://example.com/%ZZ?query=%',
);
});
test('preserves trailing slash exactly once', () {
final uri = Uri.parse('http://x.com/a/b/');
expect(uri.displayString, 'http://x.com/a/b/');
});
test('decodes Cyrillic Reddit URL with trailing slash', () {
final uri = Uri.parse(
'https://www.reddit.com/r/KafkaFPS/comments/1sn0j5w/'
'%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D1%82%D0%B0%D0%BD%D1%8C%D1%82%D0%B5'
'_%D1%81%D0%BE%D0%BF%D1%80%D0%BE%D1%82%D0%B8%D0%B2%D0%BB%D1%8F'
'%D1%82%D1%8C%D1%81%D1%8F_%D0%BC%D0%B8%D1%81%D1%82%D0%B5%D1%80'
'_%D0%B0%D0%BD%D0%B4%D0%B5%D1%80%D1%81%D0%BE%D0%BD/',
);
expect(
uri.displayString,
'https://www.reddit.com/r/KafkaFPS/comments/1sn0j5w/'
'перестаньте_сопротивляться_мистер_андерсон/',
);
});
test('keeps IDN punycode host as-is', () {
expect(
'https://xn--j1ail.xn--p1ai/'.uriDisplayString,
'https://xn--j1ail.xn--p1ai/',
);
});
});
}