fix: restore only main macOS window and select active downloads

This commit is contained in:
Levi committed 2026-09-08 18:14:16 +08:00
1 parent 6568498850
commit 31fa0e5bc9
11 files changed
+219 -14

No files matched your search

@@ -1,4 +1,6 @@
import 'package:flutter/widgets.dart';
import 'package:flutter/services.dart';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/widgets.dart' as flutter show Row;
import 'package:flutter/foundation.dart' show TargetPlatform, debugDefaultTargetPlatformOverride;
import 'package:flutter/material.dart' show Icons;
@@ -10,6 +12,7 @@ import 'package:gopeed/api/model/downloader_config.dart';
import 'package:gopeed/api/model/options.dart';
import 'package:gopeed/api/model/request.dart';
import 'package:gopeed/core/capabilities/app_capabilities.dart';
import 'package:gopeed/core/capabilities/app_navigation_capability.dart';
import 'package:gopeed/core/capabilities/capability_rpc.dart';
import 'package:gopeed/core/capabilities/gopeed_capability.dart';
import 'package:gopeed/core/capabilities/storage_capability.dart';
@@ -22,6 +25,58 @@ import 'package:gopeed/shared/widgets/app_tooltip.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart' as shad;
void main() {
for (final navigationFails in [false, true]) {
testWidgets('child creation selects downloads before closing (navigation fails: $navigationFails)', (tester) async {
tester.view.physicalSize = const Size(1024, 720);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final events = <String>[];
const channel = MethodChannel('window_manager');
final messenger = TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger;
messenger.setMockMethodCallHandler(channel, (call) async {
events.add(call.method);
return null;
});
addTearDown(() => messenger.setMockMethodCallHandler(channel, null));
final config = DownloaderConfig(downloadDir: '/downloads')..extra.defaultDirectDownload = true;
final registry = CapabilityRegistry(createAppCapabilityCodecs())
..bind(GopeedMethods.getConfig, (_) => config)
..bind(StorageMethods.saveCreateHistory, (_) => const RpcUnit())
..bind(GopeedMethods.createTask, (_) {
events.add('created');
return 'task-id';
})
..bind(NavigationMethods.showDownloadingTasks, (_) {
events.add('downloads');
if (navigationFails) throw StateError('Navigation unavailable');
return const RpcUnit();
});
await tester.pumpWidget(
ProviderScope(
overrides: [appCapabilitiesProvider.overrideWithValue(AppCapabilities(LocalCapabilityInvoker(registry)))],
child: shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: AppComponentThemes(
child: CreateTaskWindowPage(
windowController: WindowController.fromWindowId('child'),
initialTask: CreateTask(req: Request(url: 'https://example.com/file.apk')),
),
),
),
),
);
await tester.pumpAndSettle();
await tester.tap(find.text('Confirm'));
// The mocked native close deliberately leaves the widget mounted.
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(events, ['created', 'downloads', 'close']);
await tester.pumpWidget(const SizedBox());
});
}
testWidgets('mobile create task page starts below the system status bar', (WidgetTester tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;
tester.view.physicalSize = const Size(700, 760);
+35
View File
@@ -13,6 +13,9 @@ import 'package:go_router/go_router.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart' as shad;
import 'package:window_manager/window_manager.dart';
import 'package:gopeed/app/app.dart';
import 'package:gopeed/app/router/app_router.dart';
import 'package:gopeed/core/capabilities/app_capabilities.dart';
import 'package:gopeed/core/capabilities/app_navigation_capability.dart';
import 'package:gopeed/app/application/app_appearance_controller.dart';
import 'package:gopeed/app/application/app_deep_link_controller.dart';
import 'package:gopeed/app/application/app_notification_controller.dart';
@@ -93,6 +96,38 @@ import 'package:gopeed/util/updater.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized().platformDispatcher.localeTestValue = const Locale('en');
testWidgets('child success returns to downloading from completed and another page', (tester) async {
await _setTestSize(tester, const Size(1024, 768));
await tester.pumpWidget(
ProviderScope(
overrides: [
appRuntimeControllerProvider.overrideWith(FakeRuntimeController.new),
tasksControllerProvider.overrideWith(CompletedTasksController.new),
settingsControllerProvider.overrideWith(FakeSettingsController.new),
],
child: const GopeedApp(),
),
);
await tester.pumpAndSettle();
await tester.tap(find.text('Completed'));
await tester.pumpAndSettle();
expect(find.text('done.zip'), findsOneWidget);
// Exercise the same serialized operation dispatched by a child window.
await LocalAppCapabilities.instance.registry.invoke(NavigationMethods.showDownloadingTasks.name, {});
await tester.pumpAndSettle();
expect(find.text('done.zip'), findsNothing);
expect(find.text('Create Task'), findsOneWidget);
GoRouter.of(AppRouter.rootNavigatorKey.currentContext!).go('/settings');
await tester.pumpAndSettle();
await LocalAppCapabilities.instance.capabilities.navigation.showDownloadingTasks();
await tester.pumpAndSettle();
expect(GoRouter.of(AppRouter.rootNavigatorKey.currentContext!).routeInformationProvider.value.uri.path, '/');
expect(find.text('done.zip'), findsNothing);
expect(find.text('Create Task'), findsOneWidget);
});
test('Web MCP endpoint excludes page path, query, and hash route', () {
expect(
webMcpEndpoint(Uri.parse('https://gopeed.example:8443/app?source=desktop#/settings/advanced')),