mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 23:57:54 +00:00
fix(ui): preserve desktop platform listeners (#1483)
This commit is contained in:
2 files changed
+130
-15
No files matched your search
@@ -54,6 +54,9 @@ class AppPlatformState {
|
||||
enum AppUpdateStatus { idle, checking, upToDate, available, failed }
|
||||
|
||||
class AppPlatformController extends AsyncNotifier<AppPlatformState> with WindowListener, TrayListener {
|
||||
@protected
|
||||
bool get isDesktop => Util.isDesktop();
|
||||
|
||||
bool _started = false;
|
||||
String? _trayLocaleConfig;
|
||||
bool _updateInitialized = false;
|
||||
@@ -74,30 +77,54 @@ class AppPlatformController extends AsyncNotifier<AppPlatformState> with WindowL
|
||||
|
||||
@override
|
||||
Future<AppPlatformState> build() async {
|
||||
final runtime = ref.watch(appRuntimeControllerProvider).value;
|
||||
if (runtime == null || kIsWeb) {
|
||||
return _snapshot();
|
||||
}
|
||||
if (!Util.isDesktop()) {
|
||||
_scheduleInitialUpdateCheck();
|
||||
return _snapshot();
|
||||
}
|
||||
if (_started) {
|
||||
final localeConfig = runtime.downloaderConfig.extra.locale;
|
||||
if (_trayLocaleConfig != localeConfig) await _initTray();
|
||||
return _snapshot();
|
||||
}
|
||||
await _start();
|
||||
_scheduleInitialUpdateCheck();
|
||||
ref.listen(appRuntimeControllerProvider, (_, next) {
|
||||
unawaited(
|
||||
_handleRuntimeChange(next.value).catchError((Object error, StackTrace stackTrace) {
|
||||
if (ref.mounted) state = AsyncValue.error(error, stackTrace);
|
||||
}),
|
||||
);
|
||||
});
|
||||
ref.onDispose(() {
|
||||
if (!_started) return;
|
||||
_started = false;
|
||||
windowManager.removeListener(this);
|
||||
trayManager.removeListener(this);
|
||||
unawaited(HostRpcService.instance.stop());
|
||||
unawaited(AppWindowCapabilityHost.instance.stop());
|
||||
});
|
||||
final runtime = ref.read(appRuntimeControllerProvider).value;
|
||||
if (runtime == null || kIsWeb) {
|
||||
return _snapshot();
|
||||
}
|
||||
if (!isDesktop) {
|
||||
_scheduleInitialUpdateCheck();
|
||||
return _snapshot();
|
||||
}
|
||||
if (_started) {
|
||||
return _snapshot();
|
||||
}
|
||||
await _start();
|
||||
_scheduleInitialUpdateCheck();
|
||||
return _snapshot();
|
||||
}
|
||||
|
||||
Future<void> _handleRuntimeChange(AppRuntimeState? runtime) async {
|
||||
if (runtime == null || kIsWeb) return;
|
||||
if (!isDesktop) {
|
||||
_scheduleInitialUpdateCheck();
|
||||
return;
|
||||
}
|
||||
if (!_started) {
|
||||
await _start();
|
||||
_scheduleInitialUpdateCheck();
|
||||
_emit();
|
||||
return;
|
||||
}
|
||||
if (_trayLocaleConfig != runtime.downloaderConfig.extra.locale) {
|
||||
await _initTray();
|
||||
}
|
||||
}
|
||||
|
||||
void _scheduleInitialUpdateCheck() {
|
||||
if (_updateInitialized) return;
|
||||
_updateInitialized = true;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import 'dart:async';
|
||||
|
||||
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_platform_controller.dart';
|
||||
import 'package:gopeed/app/application/app_runtime_controller.dart';
|
||||
import 'package:gopeed/core/common/api_server_state.dart';
|
||||
import 'package:gopeed/core/common/start_config.dart';
|
||||
import 'package:gopeed/util/updater.dart';
|
||||
|
||||
void main() {
|
||||
test('runtime updates do not rebuild the platform controller', () async {
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
appRuntimeControllerProvider.overrideWith(_TestRuntimeController.new),
|
||||
appPlatformControllerProvider.overrideWith(_TestPlatformController.new),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
final subscription = container.listen(appPlatformControllerProvider, (_, _) {}, fireImmediately: true);
|
||||
addTearDown(subscription.close);
|
||||
|
||||
await container.read(appPlatformControllerProvider.future);
|
||||
final platformController = container.read(appPlatformControllerProvider.notifier) as _TestPlatformController;
|
||||
final runtimeController = container.read(appRuntimeControllerProvider.notifier) as _TestRuntimeController;
|
||||
|
||||
expect(platformController.buildCount, 1);
|
||||
|
||||
runtimeController.completeRuntime();
|
||||
await container.read(appRuntimeControllerProvider.future);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
expect(platformController.updateCheckCount, 1);
|
||||
|
||||
final config = DownloaderConfig.fromJson(runtimeController.state.requireValue.downloaderConfig.toJson());
|
||||
config.extra.locale = 'zh';
|
||||
runtimeController.replaceDownloaderConfig(config);
|
||||
await container.pump();
|
||||
|
||||
expect(platformController.buildCount, 1);
|
||||
});
|
||||
}
|
||||
|
||||
class _TestPlatformController extends AppPlatformController {
|
||||
int buildCount = 0;
|
||||
int updateCheckCount = 0;
|
||||
|
||||
@override
|
||||
bool get isDesktop => false;
|
||||
|
||||
@override
|
||||
Future<AppPlatformState> build() {
|
||||
buildCount++;
|
||||
return super.build();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VersionInfo?> checkForUpdate() async {
|
||||
updateCheckCount++;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class _TestRuntimeController extends AppRuntimeController {
|
||||
final _pendingRuntime = Completer<AppRuntimeState>();
|
||||
|
||||
@override
|
||||
Future<AppRuntimeState> build() => _pendingRuntime.future;
|
||||
|
||||
void completeRuntime() {
|
||||
_pendingRuntime.complete(
|
||||
AppRuntimeState(
|
||||
startConfig: StartConfig(),
|
||||
apiServerState: const ApiServerState(
|
||||
enabled: false,
|
||||
mcpEnabled: false,
|
||||
running: false,
|
||||
network: '',
|
||||
address: '',
|
||||
runningPort: 0,
|
||||
pendingApply: false,
|
||||
lastError: '',
|
||||
),
|
||||
downloaderConfig: DownloaderConfig(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user