mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-05 16:15:43 +00:00
fix(android): via browser takeover handling (#1489)
This commit is contained in:
5 files changed
+90
-3
No files matched your search
@@ -32,6 +32,12 @@
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<!-- app_links and share_handler own external download intents. Letting
|
||||
Flutter's Router handle the same URI races with the explicit
|
||||
navigation to the create-task page. -->
|
||||
<meta-data
|
||||
android:name="flutter_deeplinking_enabled"
|
||||
android:value="false" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
@@ -37,10 +37,15 @@ class AppDeepLinkController extends AsyncNotifier<AppDeepLinkState> {
|
||||
|
||||
@override
|
||||
Future<AppDeepLinkState> build() async {
|
||||
final runtime = ref.watch(appRuntimeControllerProvider).value;
|
||||
if (runtime == null || _started || kIsWeb) {
|
||||
if (_started || kIsWeb) {
|
||||
return AppDeepLinkState(started: _started);
|
||||
}
|
||||
// Deep-link handling depends on the runtime being ready, but it must not
|
||||
// rebuild whenever runtime settings change. A rebuild disposes the active
|
||||
// platform subscriptions while `_started` remains true, leaving Android
|
||||
// unable to receive later browser takeover intents (for example after the
|
||||
// API server is started or stopped from Settings).
|
||||
await ref.read(appRuntimeControllerProvider.future);
|
||||
_started = true;
|
||||
final appLinks = AppLinks();
|
||||
_subscription = appLinks.uriLinkStream.listen((uri) {
|
||||
|
||||
@@ -50,7 +50,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
app_links_platform_interface:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: app_links_platform_interface
|
||||
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||
|
||||
@@ -108,6 +108,7 @@ dependency_overrides:
|
||||
path: permission_handler_windows
|
||||
|
||||
dev_dependencies:
|
||||
app_links_platform_interface: ^2.0.2
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:app_links_platform_interface/app_links_platform_interface.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gopeed/api/model/downloader_config.dart';
|
||||
import 'package:gopeed/app/application/app_runtime_controller.dart';
|
||||
import 'package:gopeed/app/application/app_deep_link_controller.dart';
|
||||
import 'package:gopeed/core/common/api_server_state.dart';
|
||||
import 'package:gopeed/core/common/start_config.dart';
|
||||
import 'package:share_handler/share_handler.dart';
|
||||
|
||||
void main() {
|
||||
@@ -27,4 +35,71 @@ void main() {
|
||||
|
||||
expect(sharedMediaUri(media), Uri.parse('magnet:?xt=urn:btih:example'));
|
||||
});
|
||||
|
||||
test('keeps listening for browser takeover links after runtime settings change', () async {
|
||||
final originalPlatform = AppLinksPlatform.instance;
|
||||
final appLinksPlatform = _FakeAppLinksPlatform();
|
||||
AppLinksPlatform.instance = appLinksPlatform;
|
||||
final container = ProviderContainer(
|
||||
overrides: [appRuntimeControllerProvider.overrideWith(_FakeRuntimeController.new)],
|
||||
);
|
||||
|
||||
try {
|
||||
await container.read(appDeepLinkControllerProvider.future);
|
||||
expect(appLinksPlatform.hasListener, isTrue);
|
||||
|
||||
container.read(appRuntimeControllerProvider.notifier).replaceDownloaderConfig(DownloaderConfig());
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
expect(appLinksPlatform.hasListener, isTrue);
|
||||
} finally {
|
||||
container.dispose();
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
AppLinksPlatform.instance = originalPlatform;
|
||||
await appLinksPlatform.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class _FakeAppLinksPlatform extends AppLinksPlatform {
|
||||
final _links = StreamController<Uri>.broadcast();
|
||||
|
||||
bool get hasListener => _links.hasListener;
|
||||
|
||||
@override
|
||||
Future<Uri?> getInitialLink() async => null;
|
||||
|
||||
@override
|
||||
Stream<Uri> get uriLinkStream => _links.stream;
|
||||
|
||||
Future<void> close() => _links.close();
|
||||
}
|
||||
|
||||
class _FakeRuntimeController extends AppRuntimeController {
|
||||
@override
|
||||
Future<AppRuntimeState> build() async {
|
||||
final config = StartConfig()
|
||||
..network = 'tcp'
|
||||
..address = '127.0.0.1:9999'
|
||||
..apiEnable = true
|
||||
..apiToken = ''
|
||||
..storage = 'bolt'
|
||||
..storageDir = ''
|
||||
..refreshInterval = 0;
|
||||
return AppRuntimeState(
|
||||
startConfig: config,
|
||||
apiServerState: const ApiServerState(
|
||||
enabled: true,
|
||||
mcpEnabled: false,
|
||||
running: true,
|
||||
network: 'tcp',
|
||||
address: '127.0.0.1:9999',
|
||||
runningPort: 9999,
|
||||
pendingApply: false,
|
||||
lastError: '',
|
||||
),
|
||||
downloaderConfig: DownloaderConfig(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user