Files
moonwell-launcher/lib/features/launcher/data/launcher_update_service.dart
T

100 lines
2.8 KiB
Dart

import 'dart:io';
import 'package:auto_updater/auto_updater.dart';
import 'package:injectable/injectable.dart';
import 'package:moonwell_launcher/config.dart';
import 'package:moonwell_launcher/features/launcher/data/launcher_log_service.dart';
abstract interface class LauncherUpdateClient {
Future<void> setFeedUrl(String feedUrl);
Future<void> disableScheduledChecks();
Future<void> checkInBackground();
}
final class AutoUpdaterLauncherUpdateClient implements LauncherUpdateClient {
@override
Future<void> setFeedUrl(String feedUrl) => autoUpdater.setFeedURL(feedUrl);
@override
Future<void> disableScheduledChecks() =>
autoUpdater.setScheduledCheckInterval(0);
@override
Future<void> checkInBackground() =>
autoUpdater.checkForUpdates(inBackground: true);
}
@lazySingleton
class LauncherUpdateService {
LauncherUpdateService(LauncherLogService launcherLogService)
: this.forTesting(
launcherLogService: launcherLogService,
updateClient: AutoUpdaterLauncherUpdateClient(),
isWindows: Platform.isWindows,
);
LauncherUpdateService.forTesting({
required LauncherLogService launcherLogService,
required LauncherUpdateClient updateClient,
required bool isWindows,
}) : _launcherLogService = launcherLogService,
_updateClient = updateClient,
_isWindows = isWindows;
final LauncherLogService _launcherLogService;
final LauncherUpdateClient _updateClient;
final bool _isWindows;
bool _hasChecked = false;
Future<void> checkForUpdates({
String feedUrl = Config.launcherAppcastUrl,
}) async {
if (!_isWindows || _hasChecked) {
return;
}
final normalizedFeedUrl = feedUrl.trim();
if (normalizedFeedUrl.isEmpty) {
await _launcherLogService.info(
'Launcher self-update is disabled because no AppCast URL is configured.',
);
return;
}
final uri = Uri.tryParse(normalizedFeedUrl);
if (uri == null ||
!uri.isAbsolute ||
uri.scheme != 'https' ||
!uri.hasAuthority ||
uri.host.isEmpty) {
await _launcherLogService.error(
'Launcher self-update AppCast URL is invalid.',
details: <String, Object?>{'feedUrl': normalizedFeedUrl},
);
return;
}
_hasChecked = true;
try {
await _updateClient.setFeedUrl(normalizedFeedUrl);
await _updateClient.disableScheduledChecks();
await _updateClient.checkInBackground();
await _launcherLogService.info(
'Launcher self-update check started.',
details: <String, Object?>{'feedUrl': normalizedFeedUrl},
);
} catch (error, stackTrace) {
await _launcherLogService.error(
'Launcher self-update check failed.',
details: <String, Object?>{'feedUrl': normalizedFeedUrl},
error: error,
stackTrace: stackTrace,
);
}
}
}