rebuild translations

This commit is contained in:
zjs81
2026-08-11 00:15:45 -07:00
parent eee72b4c65
commit cf6c93c50a
63 changed files with 6584 additions and 4040 deletions
+23 -15
View File
@@ -83,8 +83,9 @@ List<String> _texts(WidgetTester tester) => tester
.toList();
void main() {
testWidgets('renders with a fake codec and shows the image preview',
(tester) async {
testWidgets('renders with a fake codec and shows the image preview', (
tester,
) async {
await _openSheet(tester, radio: _knownRadio);
expect(find.byType(ImageSendPreviewSheet), findsOneWidget);
@@ -94,8 +95,9 @@ void main() {
expect(send.onPressed, isNotNull);
});
testWidgets('shows the packet count for the encoded ft32 payload',
(tester) async {
testWidgets('shows the packet count for the encoded ft32 payload', (
tester,
) async {
await _openSheet(tester, radio: _knownRadio);
// FakeImageSendCodec emits the measured ft32 mean (156 B) -> one data chunk,
@@ -110,8 +112,9 @@ void main() {
expect(_texts(tester), contains('${expected.chunkCount}'));
});
testWidgets('shows a concrete airtime when the radio settings are known',
(tester) async {
testWidgets('shows a concrete airtime when the radio settings are known', (
tester,
) async {
await _openSheet(tester, radio: _knownRadio);
final texts = _texts(tester);
@@ -128,8 +131,9 @@ void main() {
);
});
testWidgets('headline time is the paced wall clock, not raw airtime',
(tester) async {
testWidgets('headline time is the paced wall clock, not raw airtime', (
tester,
) async {
await _openSheet(tester, radio: _knownRadio);
final expected = estimateSendFromRadioParams(
@@ -154,8 +158,9 @@ void main() {
expect(texts, isNot(contains('${seconds(expected.totalAirtime!)} s')));
});
testWidgets('renders "unknown" airtime when the radio params are absent',
(tester) async {
testWidgets('renders "unknown" airtime when the radio params are absent', (
tester,
) async {
await _openSheet(tester, radio: _unknownRadio);
final texts = _texts(tester);
@@ -223,8 +228,9 @@ void main() {
expect(find.byType(ImageSendPreviewSheet), findsNothing);
});
testWidgets('confirming returns the payload, packet count and both times',
(tester) async {
testWidgets('confirming returns the payload, packet count and both times', (
tester,
) async {
ImageSendPreviewResult? result;
await tester.pumpWidget(
@@ -270,8 +276,9 @@ void main() {
);
});
testWidgets('a codec that is still downloading cannot be sent from',
(tester) async {
testWidgets('a codec that is still downloading cannot be sent from', (
tester,
) async {
await _openSheet(
tester,
radio: _knownRadio,
@@ -289,7 +296,8 @@ void main() {
testWidgets('an unavailable codec explains itself with unavailableReason, '
'not the generic string', (tester) async {
const reason = 'This build ships the image decoder only. Encoding and '
const reason =
'This build ships the image decoder only. Encoding and '
'decoding a bitstream also needs the entropy-side graph and the rANS '
'coder, which are not included yet.';
await _openSheet(
+37 -26
View File
@@ -96,8 +96,9 @@ Future<void> _pumpBubble(
}
void main() {
testWidgets('decoded incoming bubble carries the R6 badge and caption',
(tester) async {
testWidgets('decoded incoming bubble carries the R6 badge and caption', (
tester,
) async {
final blobs = InMemoryReceivedImageBlobStore();
final store = ReceivedImageStore(blobs: blobs);
final png = base64Decode(_png1x1);
@@ -161,7 +162,6 @@ void main() {
expect(find.textContaining('Fine detail is generated'), findsOneWidget);
});
testWidgets('receiving state shows the packet count', (tester) async {
final store = ReceivedImageStore(decoder: null);
final reassembler = ImageReassembler(selfPrefix: 0xbeef);
@@ -193,21 +193,23 @@ void main() {
});
testWidgets(
'awaiting card shows the bitstream size, the packet count and the '
'tap-to-process affordance', (tester) async {
final store = await _awaitingStore(bytes: 156, packets: 2);
final entry = store.entryFor('await1')!;
expect(entry.state, ReceivedImageState.reassembled);
expect(entry.needsManualDecode, isTrue);
'awaiting card shows the bitstream size, the packet count and the '
'tap-to-process affordance',
(tester) async {
final store = await _awaitingStore(bytes: 156, packets: 2);
final entry = store.entryFor('await1')!;
expect(entry.state, ReceivedImageState.reassembled);
expect(entry.needsManualDecode, isTrue);
await _pumpBubble(tester, store);
await _pumpBubble(tester, store);
expect(find.text('156 bytes · 2 packets'), findsOneWidget);
expect(find.text('Tap to process'), findsOneWidget);
// A placeholder is never dressed up as a picture.
expect(find.text('AI-reconstructed'), findsNothing);
expect(find.byType(Image), findsNothing);
});
expect(find.text('156 bytes · 2 packets'), findsOneWidget);
expect(find.text('Tap to process'), findsOneWidget);
// A placeholder is never dressed up as a picture.
expect(find.text('AI-reconstructed'), findsNothing);
expect(find.byType(Image), findsNothing);
},
);
testWidgets('awaiting card honours injected strings', (tester) async {
final store = await _awaitingStore(bytes: 209, packets: 3);
@@ -338,8 +340,9 @@ void main() {
expect(decoder.decodeCalls, 1);
});
testWidgets('every non-decoded state renders a legible label',
(tester) async {
testWidgets('every non-decoded state renders a legible label', (
tester,
) async {
const cases = <String, String>{
'failedIncomplete': 'Image incomplete — 1 of 3 packets arrived',
'failedCorrupt': 'Image could not be reconstructed',
@@ -413,8 +416,9 @@ void main() {
expect(find.textContaining('Fine detail is generated'), findsOneWidget);
});
testWidgets('the caption quotes the real bitstream size, not a nominal one',
(tester) async {
testWidgets('the caption quotes the real bitstream size, not a nominal one', (
tester,
) async {
// It used to hardcode "~156 bytes" under every image, so a 209-byte image
// and a 110-byte one both claimed 156. The label's whole purpose is
// honesty about what was actually transmitted.
@@ -448,15 +452,22 @@ void main() {
await _pumpBubble(tester, store, streamId: id);
await tester.pump();
expect(find.textContaining('$bytes bytes'), findsOneWidget,
reason: 'caption must quote $bytes');
expect(find.textContaining('156 bytes'), findsNothing,
reason: 'no nominal size may leak into the caption');
expect(
find.textContaining('$bytes bytes'),
findsOneWidget,
reason: 'caption must quote $bytes',
);
expect(
find.textContaining('156 bytes'),
findsNothing,
reason: 'no nominal size may leak into the caption',
);
}
});
testWidgets('the R6 caption is never truncated in a narrow bubble',
(tester) async {
testWidgets('the R6 caption is never truncated in a narrow bubble', (
tester,
) async {
// It used to be maxLines: 2 and clipped mid-sentence — the rendered text
// read "Details are invented. Not a", cutting off exactly where the
// warning was. A half-shown warning is worse than none.