fetchUpdates method

Future<bool> fetchUpdates({
  1. bool force = false,
})

Fetches the Config.appcast file to _schedulePopup, if new Release is detected.

Returns true, if new update is detected.

If force is true, then ignores the _skippedLocal stored one.

Implementation

Future<bool> fetchUpdates({bool force = false}) async {
  Log.debug('fetchUpdates(force: $force)', '$runtimeType');

  if (Config.appcast.isEmpty) {
    return false;
  }

  try {
    final response = await (await PlatformUtils.dio).get(Config.appcast);

    if (response.statusCode != 200 || response.data == null) {
      throw DioException.connectionError(
        requestOptions: RequestOptions(),
        reason: 'Status code ${response.statusCode}',
      );
    }

    final XmlDocument document = XmlDocument.parse(response.data);
    final XmlElement? rss = document.findElements('rss').firstOrNull;
    final XmlElement? channel = rss?.findElements('channel').firstOrNull;

    if (channel != null) {
      final Iterable<XmlElement> items = channel.findElements('item');

      if (items.isNotEmpty) {
        final Release release = Release.fromXml(
          items.first,
          language: L10n.chosen.value,
        );

        // If the latest fetched [Release] is the same as this one, then don't
        // even try to compare it.
        if (_latest?.name == release.name) {
          return false;
        }

        bool silent = _latest != null;
        _latest = release;

        Log.debug(
          'Comparing `${release.name}` to `${Pubspec.ref}`',
          '$runtimeType',
        );

        if (release.name != Pubspec.ref) {
          Version? ours;
          try {
            ours = VersionExtension.parse(Pubspec.ref);
          } catch (e) {
            // No-op.
          }

          Version? their;
          try {
            their = VersionExtension.parse(release.name);
          } catch (e) {
            // No-op.
          }

          // Shouldn't prompt user with versions lower than current.
          final bool lower =
              ours != null && their != null
                  ? ours < their
                  : Pubspec.ref.compareTo(release.name) == -1;
          Log.info(
            'Whether `${Pubspec.ref}` is lower than `${release.name}`: $lower',
            '$runtimeType',
          );

          // Critical releases must always be displayed and can't be skipped.
          final bool critical = ours?.isCritical(their) ?? false;
          Log.info(
            'Whether `$ours` is considered critical relative to `$their`: $critical',
            '$runtimeType',
          );

          final bool skipped =
              !force && await _skippedLocal?.read() == release.name;
          if (critical || (lower && !skipped && Config.downloadable)) {
            _schedulePopup(
              release,
              critical: critical,
              delay: !force,
              silent: silent,
            );
            return true;
          }
        }
      }
    }
  } catch (e) {
    Log.info('Failed to fetch releases: $e', '$runtimeType');
  }

  return false;
}