checkForUpdate method

Future<UpdateCheckResult> checkForUpdate()

Check for available updates.

Returns an UpdateCheckResult indicating whether an update is available, no update is needed, or an error occurred.

Implementation

Future<UpdateCheckResult> checkForUpdate() async {
  if (config.isDisabled) {
    config.log('Update check disabled');
    return const UpdateCheckDisabled();
  }

  if (_isCheckingForUpdate) {
    config.log('Already checking for updates');
    return const UpdateCheckError('Already checking for updates');
  }

  if (!_isInitialized || _packageInfo == null) {
    config.log('Service not initialized');
    return const UpdateCheckError('Service not initialized');
  }

  _isCheckingForUpdate = true;

  try {
    final currentVersion = _packageInfo!.version;
    final rawBuild = int.tryParse(_packageInfo!.buildNumber) ?? 0;
    final currentBuild = _normalizeBuildNumber(rawBuild);

    config.log('=== UPDATE CHECK DEBUG ===');
    config.log('Package info - version: $currentVersion, buildNumber: ${_packageInfo!.buildNumber}');
    config.log('Raw build number: $rawBuild');
    config.log('Normalized build number: $currentBuild');
    config.log('Device architecture: $_deviceArchitecture');

    final url = config.versionCheckUrlWithArch(
      _deviceArchitecture,
      currentVersion: currentVersion,
      currentBuild: currentBuild,
    );
    config.log('Request URL: $url');

    final request = http.Request('GET', Uri.parse(url));
    if (config.httpHeaders != null) {
      request.headers.addAll(config.httpHeaders!);
    }

    final client = http.Client();
    try {
      final streamedResponse = await client.send(request).timeout(
        config.connectionTimeout,
      );
      final response = await http.Response.fromStream(streamedResponse);

      config.log('Response status: ${response.statusCode}');
      config.log('Response body: ${response.body}');

      if (response.statusCode == 200) {
        final versionData = json.decode(response.body) as Map<String, dynamic>;
        config.log('Parsed JSON: $versionData');

        // Handle ReleaseHub mode vs standard mode
        if (config.releaseHubMode) {
          // ReleaseHub returns hasUpdate flag directly
          final hasUpdate = versionData['hasUpdate'] as bool? ?? false;
          config.log('ReleaseHub hasUpdate flag: $hasUpdate');

          if (!hasUpdate) {
            config.log('No update available (ReleaseHub: hasUpdate=false)');
            config.log('=== END DEBUG ===');
            return const NoUpdateAvailable();
          }

          final versionInfo = VersionInfo.fromReleaseHub(versionData, config.baseUrl);

          config.log(
            'Version check - Current: $currentVersion (build $currentBuild), '
            'Server: ${versionInfo.version} (build ${versionInfo.build})',
          );

          config.log('New version available: ${versionInfo.displayVersion}');
          return UpdateAvailable(versionInfo);
        } else {
          // Standard mode - parse flat JSON
          final versionInfo = VersionInfo.fromJson(versionData, config.responseFields);

          config.log(
            'Version check - Current: $currentVersion (build $currentBuild), '
            'Server: ${versionInfo.version} (build ${versionInfo.build})',
          );

          if (_isNewerVersion(currentVersion, currentBuild, versionInfo)) {
            config.log('New version available: ${versionInfo.displayVersion}');
            return UpdateAvailable(versionInfo);
          } else {
            config.log('No update available - already on latest version');
            return const NoUpdateAvailable();
          }
        }
      } else if (response.statusCode == 404 && config.releaseHubMode) {
        // ReleaseHub returns 404 when project not found
        config.log('ReleaseHub: Project not found (404)');
        return const UpdateCheckError('Project not found on update server');
      } else {
        config.log('Version check failed with status: ${response.statusCode}');
        return UpdateCheckError(
          'Server returned status ${response.statusCode}',
        );
      }
    } finally {
      client.close();
    }
  } catch (e) {
    config.log('Error checking for update: $e');
    return UpdateCheckError('Could not check for updates', e);
  } finally {
    _isCheckingForUpdate = false;
  }
}