fix(ui): enable task detail text selection and compact extension stats (#1511)

This commit is contained in:
Levi authored and GitHub committed 2026-09-13 23:30:45 +08:00
1 parent a29f4bb42a
commit a760290213
6 files changed
+236 -71

No files matched your search

@@ -0,0 +1,26 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:gopeed/core/utils/compact_count_formatter.dart';
void main() {
test('keeps small counts exact and compacts larger counts to a bounded label', () {
expect(CompactCountFormatter.format(-1), '0');
expect(CompactCountFormatter.format(0), '0');
expect(CompactCountFormatter.format(9999), '9999');
expect(CompactCountFormatter.format(10000), '1w');
expect(CompactCountFormatter.format(12345), '1.2w');
expect(CompactCountFormatter.format(99999), '9.9w');
expect(CompactCountFormatter.format(123456), '12w');
expect(CompactCountFormatter.format(1000000), '1m');
expect(CompactCountFormatter.format(1234567), '1.2m');
expect(CompactCountFormatter.format(10000000), '10m');
expect(CompactCountFormatter.format(12345678), '12m');
expect(CompactCountFormatter.format(100000000), '100m');
expect(CompactCountFormatter.format(123456789), '123m');
expect(CompactCountFormatter.format(1000000000), '1b');
expect(CompactCountFormatter.format(1234567890), '1.2b');
expect(CompactCountFormatter.format(12345678901), '12b');
expect(CompactCountFormatter.format(1234567890123), '1.2t');
expect(CompactCountFormatter.format(1234567890123456), '1.2q');
expect(CompactCountFormatter.format(9223372036854775807), '9.2qi');
});
}
+85 -1
View File
@@ -2,7 +2,7 @@ import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart' show TargetPlatform, debugDefaultTargetPlatformOverride;
import 'package:flutter/material.dart' show Icons, Scrollbar;
import 'package:flutter/material.dart' show Icons, Scrollbar, SelectionArea;
import 'package:flutter/gestures.dart' show PointerDeviceKind, kDoubleTapMinTime, kSecondaryMouseButton;
import 'package:flutter/rendering.dart' show RenderParagraph;
import 'package:flutter/services.dart' show MethodChannel, SystemChannels;
@@ -504,6 +504,11 @@ void main() {
closeTo(tester.getRect(find.byKey(const ValueKey('extension-card-extension-2'))).right, 0.01),
);
tester.view.physicalSize = const Size(1024, 768);
await tester.pumpAndSettle();
expect(gridColumns(), 3);
expect(tester.getSize(find.byKey(const ValueKey('extension-card-extension-0'))).width, greaterThanOrEqualTo(290));
tester.view.physicalSize = const Size(1028, 608);
await tester.pumpAndSettle();
expect(gridColumns(), 3);
@@ -536,6 +541,31 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('extension cards compact large counts without crowding their actions', (WidgetTester tester) async {
await _setTestSize(tester, const Size(722, 608));
await tester.pumpWidget(
ProviderScope(
overrides: [extensionsControllerProvider.overrideWith(CrowdedExtensionCardController.new)],
child: shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: const AppComponentThemes(child: ExtensionsPage()),
),
),
);
await tester.pumpAndSettle();
expect(find.text('1.2w'), findsOneWidget);
expect(find.text('1.2b'), findsOneWidget);
final cardRect = tester.getRect(find.byKey(const ValueKey('extension-card-crowded-extension')));
final statsRect = tester.getRect(find.byKey(const ValueKey('extension-card-stats-crowded-extension')));
final actionsRect = tester.getRect(find.byKey(const ValueKey('extension-card-actions-crowded-extension')));
expect(cardRect.width, closeTo(290, 0.01));
expect(statsRect.right, lessThanOrEqualTo(actionsRect.left - 8));
expect(actionsRect.right, lessThanOrEqualTo(cardRect.right - 14));
expect(tester.takeException(), isNull);
});
testWidgets('extension details reuse the desktop detail drawer', (WidgetTester tester) async {
await _setTestSize(tester, const Size(1100, 900));
final controller = FakeExtensionsController();
@@ -3546,6 +3576,14 @@ void main() {
expect(urlValue.data, contains('\u200B'));
expect(urlValue.data!.replaceAll('\u200B', ''), task.url);
expect(urlValue.semanticsLabel, task.url);
final selectionArea = find.byKey(const ValueKey('task-details-selection-area'));
expect(selectionArea, findsOneWidget);
expect(tester.widget(selectionArea), isA<SelectionArea>());
expect(find.ancestor(of: find.text('details.zip'), matching: selectionArea), findsOneWidget);
expect(
find.ancestor(of: find.byKey(const ValueKey('task-details-url-value')), matching: selectionArea),
findsOneWidget,
);
expect(find.text('Task Details'), findsOneWidget);
expect(find.text('Task Name'), findsNothing);
final detailHeader = tester.widget<SizedBox>(find.byKey(const ValueKey('app-detail-drawer-header')));
@@ -5043,6 +5081,52 @@ class FakeExtensionsController extends ExtensionsController {
}
}
class CrowdedExtensionCardController extends ExtensionsController {
@override
Future<ExtensionsState> build() async {
final installed =
api_extension.Extension(
identity: 'crowded-extension',
name: 'crowded-extension',
author: 'Gopeed',
title: 'Crowded extension',
description: 'An extension with every available card action.',
icon: '',
version: '1.0.0',
homepage: 'https://gopeed.com',
repository: api_extension.Repository(url: 'https://github.com/GopeedLab/gopeed', directory: ''),
disabled: false,
devMode: false,
devPath: '',
)
..settings = [
api_extension.Setting(
name: 'enabled',
title: 'Enabled',
description: 'Enable the extension.',
required: false,
type: api_extension.SettingType.boolean,
),
];
final store = StoreExtension(
id: 'crowded-extension',
repoFullName: 'GopeedLab/gopeed',
repoUrl: 'https://github.com/GopeedLab/gopeed',
name: 'crowded-extension',
author: 'Gopeed',
title: 'Crowded extension',
description: 'An extension with every available card action.',
readme: '# Crowded extension',
homepage: 'https://gopeed.com',
version: '1.1.0',
installCount: 1234567890,
stars: 12345,
topics: ['download'],
);
return ExtensionsState(installedExtensions: [installed], storeExtensions: [store]);
}
}
class DevReadmeExtensionsController extends FakeExtensionsController {
DevReadmeExtensionsController(this.extensionDirectory);