open method

Future<PublicationTry<Publication>> open(
  1. PublicationAsset asset,
  2. bool allowUserInteraction, {
  3. String? credentials,
  4. dynamic sender,
  5. OnCreatePublication? onCreatePublication,
})

Parses a Publication from the given asset.

If you are opening the publication to render it in a Navigator, you must set allowUserInteraction to true to prompt the user for its credentials when the publication is protected. However, set it to false if you just want to import the Publication without reading its content, to avoid prompting the user.

When using Content Protections, you can use sender to provide a free object which can be used to give some context. For example, it could be the source Activity or Fragment which would be used to present a credentials dialog.

The warnings logger can be used to observe non-fatal parsing warnings, caused by publication authoring mistakes. This can be useful to warn users of potential rendering issues.

@param asset Digital medium (e.g. a file) used to access the publication. @param credentials Credentials that Content Protections can use to attempt to unlock a publication, for example a password. @param allowUserInteraction Indicates whether the user can be prompted, for example for its credentials. @param sender Free object that can be used by reading apps to give some UX context when presenting dialogs. @param onCreatePublication Transformation which will be applied on the Publication Builder. It can be used to modify the Manifest, the root Fetcher or the list of service factories of the Publication. @param warnings Logger used to broadcast non-fatal parsing warnings. @return Null if the asset was not recognized by any parser, or a Publication.UserException in case of failure.

Implementation

Future<PublicationTry<Publication>> open(
  PublicationAsset asset,
  bool allowUserInteraction, {
  String? credentials,
  dynamic sender,
  OnCreatePublication? onCreatePublication,
}) async {
  onCreatePublication ??= _emptyOnCreatePublication;
  try {
    Fetcher fetcher = (await asset.createFetcher(
            PublicationAssetDependencies(archiveFactory), credentials))
        .getOrThrow();

    Try<ProtectedAsset, UserException>? protectedAssetResult =
        (await contentProtections.lazyMapFirstNotNullOrNull((it) => it.open(
            asset, fetcher, credentials, allowUserInteraction, sender)));

    if (allowUserInteraction &&
        protectedAssetResult != null &&
        protectedAssetResult.isFailure) {
      throw protectedAssetResult.failure!;
    }

    ProtectedAsset? protectedAsset = protectedAssetResult?.getOrNull();
    if (protectedAsset != null) {
      asset = protectedAsset.asset;
      fetcher = protectedAsset.fetcher;
    }

    PublicationBuilder? builder =
        (await _getParsers().lazyMapFirstNotNullOrNull((it) {
      try {
        return it.parseFile(asset, fetcher).catchError((e, st) => null);
      } on Exception catch (e) {
        throw OpeningException.parsingFailed(e);
      }
    }));
    if (builder == null) {
      throw OpeningException.unsupportedFormat;
    }

    // Transform from the Content Protection.
    protectedAsset?.let((it) => it.onCreatePublication);
    // Transform provided by the reading app during the construction of the Streamer.
    builder.also(this.onCreatePublication);
    // Transform provided by the reading app in `Streamer.open()`.
    builder.also(onCreatePublication);

    Publication publication = builder.also(onCreatePublication).build();

    publication.addLegacyProperties(await asset.mediaType);
    Product2<int, Map<Link, LinkPagination>> infos =
        await PaginationInfosService.computePaginationInfos(publication);
    publication.nbPages = infos.item1;
    publication.paginationInfo = infos.item2;
    // Fimber.d("publication.manifest: ${publication.manifest}");

    return PublicationTry.success(publication);
  } on UserException catch (e, stacktrace) {
    Fimber.e("ERROR", ex: e, stacktrace: stacktrace);
    return PublicationTry.failure(e);
  }
}