From 00039b947163772ba7f69cdd87d748c6d132a124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Menu?= Date: Wed, 26 Jul 2023 10:10:39 +0200 Subject: [PATCH 1/2] Various changes for `v3` (#367) --- CHANGELOG.md | 8 + docs/migration-guide.md | 46 +++ readium/adapters/pdfium/build.gradle.kts | 4 + .../pdfium/pdfium-document/build.gradle.kts | 4 + .../pdfium/document/PdfiumDocument.kt | 15 +- .../pdfium/pdfium-navigator/build.gradle.kts | 4 + .../pdfium/navigator/PdfiumDefaults.kt | 2 +- .../navigator/PdfiumDocumentFragment.kt | 6 +- .../pdfium/navigator/PdfiumEngineProvider.kt | 4 +- .../pdfium/navigator/PdfiumPreferences.kt | 4 +- .../navigator/PdfiumPreferencesEditor.kt | 10 +- .../navigator/PdfiumPreferencesFilters.kt | 4 +- .../navigator/PdfiumPreferencesSerializer.kt | 2 +- .../pdfium/navigator/PdfiumSettings.kt | 2 +- readium/adapters/pspdfkit/build.gradle.kts | 4 + .../pspdfkit-document/build.gradle.kts | 4 + .../pspdfkit/document/PsPdfKitDocument.kt | 6 +- .../pspdfkit/document/ResourceDataProvider.kt | 2 +- .../pspdfkit-navigator/build.gradle.kts | 4 + .../pspdfkit/navigator/PsPdfKitDefaults.kt | 2 +- .../navigator/PsPdfKitEngineProvider.kt | 2 +- .../pspdfkit/navigator/PsPdfKitPreferences.kt | 4 +- .../navigator/PsPdfKitPreferencesEditor.kt | 16 +- .../navigator/PsPdfKitPreferencesFilters.kt | 4 +- .../PsPdfKitPreferencesSerializer.kt | 2 +- .../pspdfkit/navigator/PsPdfKitSettings.kt | 2 +- readium/lcp/build.gradle.kts | 4 + .../org/readium/r2/lcp/LcpAuthenticating.kt | 36 +- .../readium/r2/lcp/LcpContentProtection.kt | 2 +- .../r2/lcp/LcpContentProtectionService.kt | 15 +- .../org/readium/r2/lcp/LcpDecryptorTest.kt | 12 +- .../java/org/readium/r2/lcp/LcpException.kt | 106 +++--- .../java/org/readium/r2/lcp/LcpLicense.kt | 52 +-- .../java/org/readium/r2/lcp/LcpService.kt | 34 +- .../readium/r2/lcp/MaterialRenewListener.kt | 18 +- .../r2/lcp/auth/LcpDialogAuthentication.kt | 4 +- .../lcp/auth/LcpPassphraseAuthentication.kt | 2 +- .../r2/lcp/license/model/LicenseDocument.kt | 51 +-- .../r2/lcp/license/model/StatusDocument.kt | 70 ++-- .../r2/lcp/license/model/components/Link.kt | 6 +- .../r2/lcp/license/model/components/Links.kt | 8 +- .../model/components/lcp/ContentKey.kt | 2 +- .../model/components/lcp/Encryption.kt | 2 +- .../license/model/components/lcp/Rights.kt | 2 +- .../license/model/components/lcp/Signature.kt | 2 +- .../lcp/license/model/components/lcp/User.kt | 4 +- .../license/model/components/lcp/UserKey.kt | 2 +- .../lcp/license/model/components/lsd/Event.kt | 11 +- .../model/components/lsd/PotentialRights.kt | 2 +- .../org/readium/r2/lcp/persistence/LcpDao.kt | 2 +- .../org/readium/r2/lcp/persistence/License.kt | 2 +- .../readium/r2/lcp/persistence/Passphrase.kt | 2 +- .../org/readium/r2/lcp/public/Deprecated.kt | 20 +- .../readium/r2/lcp/service/LicensesService.kt | 2 +- .../readium/r2/lcp/service/NetworkService.kt | 6 +- readium/navigator-media2/build.gradle.kts | 4 + .../navigator/media2/ExoPlayerDataSource.kt | 12 +- .../navigator/media2/MediaMetadataFactory.kt | 6 +- .../navigator/media2/MediaNavigator.kt | 44 +-- .../org/readium/navigator/media2/OptIn.kt | 2 +- readium/navigator/build.gradle.kts | 4 + .../r2/navigator/DecorableNavigator.kt | 48 +-- .../org/readium/r2/navigator/Deprecated.kt | 35 +- .../org/readium/r2/navigator/GlobalVars.kt | 4 +- .../org/readium/r2/navigator/Navigator.kt | 92 +++-- .../java/org/readium/r2/navigator/OptIn.kt | 6 +- .../readium/r2/navigator/R2BasicWebView.kt | 2 +- .../org/readium/r2/navigator/R2WebView.kt | 2 +- .../r2/navigator/SelectableNavigator.kt | 8 +- .../r2/navigator/SimplePresentation.kt | 2 +- .../r2/navigator/audiobook/Deprecated.kt | 10 +- .../readium/r2/navigator/cbz/Deprecated.kt | 2 +- .../readium/r2/navigator/divina/Deprecated.kt | 2 +- .../readium/r2/navigator/epub/Deprecated.kt | 12 +- .../readium/r2/navigator/epub/EpubDefaults.kt | 2 +- .../r2/navigator/epub/EpubNavigatorFactory.kt | 8 +- .../navigator/epub/EpubNavigatorFragment.kt | 44 ++- .../r2/navigator/epub/EpubPreferences.kt | 233 ++++++------- .../navigator/epub/EpubPreferencesEditor.kt | 54 +-- .../navigator/epub/EpubPreferencesFilters.kt | 4 +- .../epub/EpubPreferencesSerializer.kt | 2 +- .../readium/r2/navigator/epub/EpubSettings.kt | 2 +- .../epub/css/FontFamilyDeclaration.kt | 28 +- .../r2/navigator/epub/css/Properties.kt | 70 ++-- .../r2/navigator/epub/fxl/R2FXLLayout.kt | 2 +- .../epub/fxl/R2FXLOnDoubleTapListener.kt | 2 +- .../r2/navigator/epub/fxl/R2FXLScroller.kt | 2 +- .../r2/navigator/epub/fxl/R2FXLUtils.kt | 2 +- .../r2/navigator/extensions/Extensions.kt | 4 +- .../readium/r2/navigator/extensions/JSON.kt | 2 +- .../r2/navigator/extensions/Locator.kt | 8 +- .../readium/r2/navigator/extensions/Number.kt | 2 +- .../navigator/html/HtmlDecorationTemplate.kt | 46 ++- .../navigator/image/ImageNavigatorFragment.kt | 12 +- .../readium/r2/navigator/input/DragEvent.kt | 4 +- .../r2/navigator/input/InputListener.kt | 8 +- .../r2/navigator/input/InputModifier.kt | 2 +- .../readium/r2/navigator/input/KeyEvent.kt | 324 +++++++++--------- .../readium/r2/navigator/input/TapEvent.kt | 2 +- .../r2/navigator/media/ExoMediaPlayer.kt | 4 +- .../r2/navigator/media/MediaPlayback.kt | 10 +- .../readium/r2/navigator/media/MediaPlayer.kt | 33 +- .../r2/navigator/media/MediaService.kt | 33 +- .../navigator/media/MediaSessionNavigator.kt | 14 +- .../r2/navigator/media/PendingMedia.kt | 2 +- .../api/DefaultMediaMetadataProvider.kt | 2 +- .../r2/navigator/media3/api/Media3Adapter.kt | 4 +- .../media3/api/MediaMetadataFactory.kt | 6 +- .../media3/api/MediaMetadataProvider.kt | 4 +- .../r2/navigator/media3/api/MediaNavigator.kt | 40 +-- .../media3/api/TextAwareMediaNavigator.kt | 34 +- .../media3/api/TimeBasedMediaNavigator.kt | 22 +- .../r2/navigator/media3/audio/AudioEngine.kt | 34 +- .../media3/audio/AudioEngineProvider.kt | 14 +- .../navigator/media3/audio/AudioNavigator.kt | 30 +- .../media3/audio/AudioNavigatorFactory.kt | 10 +- .../media3/exoplayer/ExoPlayerAliases.kt | 4 +- .../media3/exoplayer/ExoPlayerDataSource.kt | 8 +- .../media3/exoplayer/ExoPlayerDefaults.kt | 2 +- .../media3/exoplayer/ExoPlayerEngine.kt | 18 +- .../exoplayer/ExoPlayerEngineProvider.kt | 9 +- .../media3/exoplayer/ExoPlayerPreferences.kt | 2 +- .../exoplayer/ExoPlayerPreferencesEditor.kt | 6 +- .../ExoPlayerPreferencesSerializer.kt | 2 +- .../media3/exoplayer/ExoPlayerSettings.kt | 2 +- .../media3/syncmedia/GuidedMediaNavigator.kt | 10 +- .../r2/navigator/media3/tts/TtsAliases.kt | 4 +- .../r2/navigator/media3/tts/TtsEngine.kt | 42 +-- .../navigator/media3/tts/TtsEngineProvider.kt | 17 +- .../r2/navigator/media3/tts/TtsNavigator.kt | 34 +- .../media3/tts/TtsNavigatorFactory.kt | 12 +- .../media3/tts/android/AndroidTtsDefaults.kt | 2 +- .../media3/tts/android/AndroidTtsEngine.kt | 46 +-- .../tts/android/AndroidTtsEngineProvider.kt | 9 +- .../tts/android/AndroidTtsPreferences.kt | 2 +- .../android/AndroidTtsPreferencesEditor.kt | 10 +- .../android/AndroidTtsPreferencesFilters.kt | 4 +- .../AndroidTtsPreferencesSerializer.kt | 2 +- .../media3/tts/android/AndroidTtsSettings.kt | 2 +- .../pager/DelegatingPagerAdapter.java | 2 +- .../r2/navigator/pager/R2CbzPageFragment.kt | 2 +- .../r2/navigator/pager/R2EpubPageFragment.kt | 2 +- .../r2/navigator/pager/R2FXLPageFragment.kt | 2 +- .../navigator/pager/R2FragmentPagerAdapter.kt | 2 +- .../r2/navigator/pager/R2PagerAdapter.kt | 2 +- .../r2/navigator/pager/R2RTLViewPager.java | 5 +- .../readium/r2/navigator/pager/R2ViewPager.kt | 5 +- .../r2/navigator/pager/RtlViewPager.java | 2 +- .../readium/r2/navigator/pdf/Deprecated.kt | 2 +- .../r2/navigator/pdf/PdfEngineProvider.kt | 32 +- .../r2/navigator/pdf/PdfNavigatorFactory.kt | 6 +- .../r2/navigator/pdf/PdfNavigatorFragment.kt | 10 +- .../r2/navigator/preferences/Configurable.kt | 30 +- .../navigator/preferences/MappedPreference.kt | 20 +- .../r2/navigator/preferences/Preference.kt | 31 +- .../preferences/PreferenceDelegate.kt | 9 +- .../preferences/ProgressionStrategy.kt | 20 +- .../readium/r2/navigator/preferences/Types.kt | 43 +-- .../navigator/util/BaseActionModeCallback.kt | 2 +- .../util/DirectionalNavigationAdapter.kt | 6 +- .../r2/navigator/util/EdgeTapNavigation.kt | 10 +- .../r2/navigator/util/FragmentFactory.kt | 6 +- .../r2/navigator/util/ViewModelFactory.kt | 2 +- .../readium_baseline_forward_10_white_24.png | Bin 1015 -> 0 bytes .../readium_baseline_replay_10_white_24.png | Bin 1028 -> 0 bytes .../drawable/readium_ic_pause_white_24dp.png | Bin 94 -> 0 bytes .../readium_ic_play_arrow_white_24dp.png | Bin 343 -> 0 bytes .../readium_ic_skip_next_white_24dp.png | Bin 357 -> 0 bytes .../readium_ic_skip_previous_white_24dp.png | Bin 372 -> 0 bytes .../readium_navigator_item_spinner_font.xml | 12 - .../navigator/src/main/res/values/colors.xml | 18 - readium/opds/build.gradle.kts | 4 + .../java/org/readium/r2/opds/OPDS1Parser.kt | 33 +- .../java/org/readium/r2/opds/OPDS2Parser.kt | 15 +- readium/shared/build.gradle.kts | 4 + .../java/org/readium/r2/shared/Deprecated.kt | 96 +++--- .../java/org/readium/r2/shared/Injectable.kt | 8 +- .../java/org/readium/r2/shared/JSONable.kt | 6 +- .../org/readium/r2/shared/MediaOverlayNode.kt | 6 +- .../org/readium/r2/shared/MediaOverlays.kt | 9 +- .../main/java/org/readium/r2/shared/OptIn.kt | 10 +- .../java/org/readium/r2/shared/ReadiumCSS.kt | 122 +++---- .../java/org/readium/r2/shared/RootFile.kt | 24 +- .../org/readium/r2/shared/UserException.kt | 34 +- .../org/readium/r2/shared/UserProperties.kt | 101 ++---- .../java/org/readium/r2/shared/asset/Asset.kt | 18 +- .../readium/r2/shared/asset/AssetRetriever.kt | 54 +-- .../org/readium/r2/shared/asset/AssetType.kt | 4 +- .../java/org/readium/r2/shared/drm/DRM.kt | 33 +- .../java/org/readium/r2/shared/error/Error.kt | 12 +- .../java/org/readium/r2/shared/error/Try.kt | 43 +-- .../readium/r2/shared/extensions/Bitmap.kt | 4 +- .../readium/r2/shared/extensions/ByteArray.kt | 7 +- .../org/readium/r2/shared/extensions/Date.kt | 4 +- .../readium/r2/shared/extensions/Exception.kt | 16 +- .../org/readium/r2/shared/extensions/File.kt | 9 +- .../org/readium/r2/shared/extensions/Float.kt | 4 +- .../org/readium/r2/shared/extensions/Flow.kt | 4 +- .../readium/r2/shared/extensions/Intent.kt | 22 +- .../org/readium/r2/shared/extensions/JSON.kt | 53 ++- .../readium/r2/shared/extensions/LongRange.kt | 11 +- .../readium/r2/shared/extensions/String.kt | 7 +- .../org/readium/r2/shared/extensions/URL.kt | 7 +- .../r2/shared/fetcher/BytesResource.kt | 16 +- .../r2/shared/fetcher/ContainerFetcher.kt | 5 +- .../org/readium/r2/shared/fetcher/Fetcher.kt | 26 +- .../readium/r2/shared/fetcher/FileFetcher.kt | 14 +- .../org/readium/r2/shared/fetcher/Resource.kt | 53 +-- .../fetcher/ResourceContentExtractor.kt | 20 +- .../r2/shared/fetcher/RoutingFetcher.kt | 9 +- .../r2/shared/fetcher/TransformingFetcher.kt | 4 +- .../org/readium/r2/shared/opds/Acquisition.kt | 22 +- .../readium/r2/shared/opds/Availability.kt | 12 +- .../java/org/readium/r2/shared/opds/Copies.kt | 8 +- .../java/org/readium/r2/shared/opds/Facet.kt | 2 +- .../java/org/readium/r2/shared/opds/Feed.kt | 4 +- .../java/org/readium/r2/shared/opds/Group.kt | 8 +- .../java/org/readium/r2/shared/opds/Holds.kt | 8 +- .../readium/r2/shared/opds/OpdsMetadata.kt | 2 +- .../java/org/readium/r2/shared/opds/Price.kt | 8 +- .../readium/r2/shared/parser/xml/XmlParser.kt | 40 ++- .../r2/shared/publication/Accessibility.kt | 158 ++++----- .../r2/shared/publication/Collection.kt | 2 +- .../r2/shared/publication/ContentLayout.kt | 17 +- .../r2/shared/publication/Contributor.kt | 14 +- .../org/readium/r2/shared/publication/Link.kt | 45 +-- .../r2/shared/publication/LocalizedString.kt | 26 +- .../readium/r2/shared/publication/Locator.kt | 58 ++-- .../readium/r2/shared/publication/Manifest.kt | 22 +- .../readium/r2/shared/publication/Metadata.kt | 16 +- .../r2/shared/publication/Properties.kt | 12 +- .../r2/shared/publication/Publication.kt | 209 +++++------ .../publication/PublicationCollection.kt | 14 +- .../shared/publication/ReadingProgression.kt | 4 +- .../readium/r2/shared/publication/Subject.kt | 14 +- .../shared/publication/archive/Properties.kt | 8 +- .../publication/encryption/Encryption.kt | 8 +- .../publication/encryption/Properties.kt | 2 +- .../r2/shared/publication/epub/EpubLayout.kt | 12 +- .../shared/publication/epub/Presentation.kt | 2 +- .../r2/shared/publication/epub/Properties.kt | 4 +- .../r2/shared/publication/epub/Publication.kt | 12 +- .../r2/shared/publication/html/DomRange.kt | 16 +- .../r2/shared/publication/html/Locator.kt | 6 +- .../r2/shared/publication/opds/Properties.kt | 16 +- .../r2/shared/publication/opds/Publication.kt | 2 +- .../publication/presentation/Metadata.kt | 2 +- .../publication/presentation/Presentation.kt | 100 +++--- .../publication/presentation/Properties.kt | 12 +- .../AdeptFallbackContentProtection.kt | 4 +- .../protection/ContentProtection.kt | 32 +- .../ContentProtectionSchemeRetriever.kt | 4 +- .../LcpFallbackContentProtection.kt | 4 +- .../publication/services/CacheService.kt | 14 +- .../services/ContentProtectionService.kt | 50 +-- .../publication/services/CoverService.kt | 20 +- .../publication/services/LocatorService.kt | 22 +- .../publication/services/PositionsService.kt | 22 +- .../publication/services/content/Content.kt | 76 ++-- .../services/content/ContentService.kt | 14 +- .../services/content/ContentTokenizer.kt | 10 +- .../iterators/HtmlResourceContentIterator.kt | 6 +- .../iterators/PublicationContentIterator.kt | 12 +- .../services/search/SearchService.kt | 70 ++-- .../services/search/StringSearchService.kt | 22 +- .../r2/shared/resource/BytesResource.kt | 12 +- .../readium/r2/shared/resource/Container.kt | 14 +- .../r2/shared/resource/ContentResource.kt | 4 +- .../shared/resource/DefaultArchiveFactory.kt | 2 +- .../r2/shared/resource/DirectoryContainer.kt | 2 +- .../readium/r2/shared/resource/Factories.kt | 70 ++-- .../r2/shared/resource/FileResource.kt | 14 +- .../readium/r2/shared/resource/Resource.kt | 51 +-- .../r2/shared/resource/ResourceInputStream.kt | 32 +- .../r2/shared/resource/ZipContainer.kt | 6 +- .../java/org/readium/r2/shared/units/Hertz.kt | 4 +- .../org/readium/r2/shared/util/Closeable.kt | 10 +- .../org/readium/r2/shared/util/CursorList.kt | 10 +- .../org/readium/r2/shared/util/Deprecated.kt | 2 +- .../java/org/readium/r2/shared/util/Either.kt | 18 +- .../java/org/readium/r2/shared/util/Href.kt | 14 +- .../org/readium/r2/shared/util/Language.kt | 14 +- .../java/org/readium/r2/shared/util/Lazy.kt | 4 +- .../readium/r2/shared/util/MapCompanion.kt | 20 +- .../readium/r2/shared/util/MemoryObserver.kt | 16 +- .../java/org/readium/r2/shared/util/Ref.kt | 2 +- .../org/readium/r2/shared/util/URITemplate.kt | 9 +- .../java/org/readium/r2/shared/util/Url.kt | 26 +- .../org/readium/r2/shared/util/WebLauncher.kt | 2 +- .../archive/channel/ChannelZipContainer.kt | 4 +- .../org/readium/r2/shared/util/cache/Cache.kt | 18 +- .../r2/shared/util/http/DefaultHttpClient.kt | 21 +- .../readium/r2/shared/util/http/HttpClient.kt | 35 +- .../r2/shared/util/http/HttpException.kt | 32 +- .../r2/shared/util/http/HttpFetcher.kt | 8 +- .../r2/shared/util/http/HttpHeaders.kt | 14 +- .../r2/shared/util/http/HttpRequest.kt | 62 ++-- .../r2/shared/util/http/HttpResource.kt | 8 +- .../shared/util/http/HttpResourceFactory.kt | 2 +- .../readium/r2/shared/util/http/MediaType.kt | 6 +- .../r2/shared/util/http/ProblemDetails.kt | 10 +- .../r2/shared/util/io/CountingInputStream.kt | 6 +- .../r2/shared/util/logging/WarningLogger.kt | 27 +- .../r2/shared/util/mediatype/Extensions.kt | 4 +- .../r2/shared/util/mediatype/MediaType.kt | 252 +++++++------- .../util/mediatype/MediaTypeRetriever.kt | 20 +- .../r2/shared/util/mediatype/Sniffer.kt | 38 +- .../shared/util/mediatype/SnifferContext.kt | 44 +-- .../readium/r2/shared/util/pdf/PdfDocument.kt | 40 ++- .../r2/shared/util/tokenizer/TextTokenizer.kt | 12 +- .../r2/shared/util/tokenizer/Tokenizer.kt | 4 +- .../r2/shared/publication/PublicationTest.kt | 22 -- readium/streamer/build.gradle.kts | 4 + .../readium/r2/streamer/PublicationFactory.kt | 25 +- .../r2/streamer/container/Container.kt | 39 ++- .../readium/r2/streamer/fetcher/Fetcher.kt | 10 +- .../r2/streamer/parser/PublicationParser.kt | 20 +- .../parser/audio/AudioLocatorService.kt | 6 +- .../r2/streamer/parser/audio/AudioParser.kt | 2 +- .../streamer/parser/epub/EncryptionParser.kt | 4 +- .../r2/streamer/parser/epub/EpubParser.kt | 6 +- .../parser/epub/EpubPositionsService.kt | 20 +- .../r2/streamer/parser/image/ImageParser.kt | 2 +- .../r2/streamer/parser/pdf/PdfParser.kt | 2 +- .../parser/readium/ReadiumWebPubParser.kt | 2 +- .../org/readium/r2/streamer/server/Globals.kt | 2 +- .../readium/r2/streamer/server/Resources.kt | 20 +- .../org/readium/r2/streamer/server/Server.kt | 10 +- .../r2/testapp/bookshelf/BookRepository.kt | 4 +- .../readium/r2/testapp/domain/model/Book.kt | 2 +- .../r2/testapp/drm/LcpManagementViewModel.kt | 2 +- .../reader/preferences/PreferencesManagers.kt | 2 +- .../org/readium/r2/testapp/utils/Exception.kt | 25 ++ .../testapp/utils/extensions/InputStream.kt | 2 +- .../r2/testapp/utils/extensions/URL.kt | 38 -- test-app/src/main/res/drawable/cnl.png | Bin 20299 -> 0 bytes .../drawable/ic_baseline_fast_forward_24.xml | 10 - .../drawable/ic_baseline_fast_rewind_24.xml | 10 - .../res/drawable/ic_baseline_skip_next_24.xml | 10 - .../drawable/ic_baseline_skip_previous_24.xml | 10 - .../res/drawable/ic_dashboard_black_24dp.xml | 9 - .../main/res/drawable/ic_info_black_24dp.xml | 9 - .../main/res/drawable/ic_outline_add_24.xml | 10 - .../ic_outline_format_align_justify_24.xml | 10 - .../ic_outline_format_align_left_24.xml | 11 - .../res/drawable/ic_outline_light_mode_24.xml | 10 - .../res/drawable/ic_outline_remove_24.xml | 10 - .../res/drawable/ic_outline_wb_sunny_24.xml | 10 - .../main/res/drawable/icon_font_decrease.png | Bin 676 -> 0 bytes .../main/res/drawable/icon_font_increase.png | Bin 599 -> 0 bytes .../src/main/res/drawable/rbtn_selector.xml | 22 -- .../res/drawable/rbtn_textcolor_selector.xml | 13 - test-app/src/main/res/layout/filter_row.xml | 30 -- .../src/main/res/layout/filter_window.xml | 20 -- .../layout/fragment_publication_detail.xml | 1 - .../res/layout/fragment_screen_reader.xml | 143 -------- .../src/main/res/layout/fragment_search.xml | 2 +- .../src/main/res/layout/item_spinner_days.xml | 14 - test-app/src/main/res/layout/popup_delete.xml | 24 -- .../src/main/res/layout/popup_passphrase.xml | 126 ------- .../src/main/res/layout/section_header.xml | 1 - test-app/src/main/res/menu/menu_filter.xml | 17 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 11 - .../res/mipmap-hdpi/ic_launcher_round.png | Bin 6668 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 3938 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 9994 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 17264 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 27423 -> 0 bytes test-app/src/main/res/values/arrays.xml | 10 - test-app/src/main/res/values/colors.xml | 10 - test-app/src/main/res/values/refs.xml | 5 - test-app/src/main/res/values/strings.xml | 82 ----- test-app/src/main/res/values/styles.xml | 20 -- 373 files changed, 3073 insertions(+), 3775 deletions(-) delete mode 100755 readium/navigator/src/main/res/drawable/readium_baseline_forward_10_white_24.png delete mode 100755 readium/navigator/src/main/res/drawable/readium_baseline_replay_10_white_24.png delete mode 100644 readium/navigator/src/main/res/drawable/readium_ic_pause_white_24dp.png delete mode 100644 readium/navigator/src/main/res/drawable/readium_ic_play_arrow_white_24dp.png delete mode 100644 readium/navigator/src/main/res/drawable/readium_ic_skip_next_white_24dp.png delete mode 100644 readium/navigator/src/main/res/drawable/readium_ic_skip_previous_white_24dp.png delete mode 100644 readium/navigator/src/main/res/layout/readium_navigator_item_spinner_font.xml delete mode 100644 readium/navigator/src/main/res/values/colors.xml create mode 100644 test-app/src/main/java/org/readium/r2/testapp/utils/Exception.kt delete mode 100644 test-app/src/main/java/org/readium/r2/testapp/utils/extensions/URL.kt delete mode 100644 test-app/src/main/res/drawable/cnl.png delete mode 100644 test-app/src/main/res/drawable/ic_baseline_fast_forward_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_baseline_fast_rewind_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_baseline_skip_next_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_baseline_skip_previous_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_dashboard_black_24dp.xml delete mode 100644 test-app/src/main/res/drawable/ic_info_black_24dp.xml delete mode 100644 test-app/src/main/res/drawable/ic_outline_add_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_outline_format_align_justify_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_outline_format_align_left_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_outline_light_mode_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_outline_remove_24.xml delete mode 100644 test-app/src/main/res/drawable/ic_outline_wb_sunny_24.xml delete mode 100644 test-app/src/main/res/drawable/icon_font_decrease.png delete mode 100644 test-app/src/main/res/drawable/icon_font_increase.png delete mode 100644 test-app/src/main/res/drawable/rbtn_selector.xml delete mode 100644 test-app/src/main/res/drawable/rbtn_textcolor_selector.xml delete mode 100644 test-app/src/main/res/layout/filter_row.xml delete mode 100644 test-app/src/main/res/layout/filter_window.xml delete mode 100644 test-app/src/main/res/layout/fragment_screen_reader.xml delete mode 100644 test-app/src/main/res/layout/item_spinner_days.xml delete mode 100644 test-app/src/main/res/layout/popup_delete.xml delete mode 100644 test-app/src/main/res/layout/popup_passphrase.xml delete mode 100644 test-app/src/main/res/menu/menu_filter.xml delete mode 100644 test-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 test-app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 test-app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 test-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 test-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 test-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 test-app/src/main/res/values/colors.xml delete mode 100644 test-app/src/main/res/values/refs.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 749b15ebd7..895e903e9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ All notable changes to this project will be documented in this file. Take a look ### Changed +* Readium resources are now prefixed with `readium_`. Take care of updating any overridden resource by following [the migration guide](docs/migration-guide.md#300). + #### Navigator * `EpubNavigatorFragment.firstVisibleElementLocator()` now returns the first *block* element that is visible on the screen, even if it starts on previous pages. @@ -31,6 +33,12 @@ All notable changes to this project will be documented in this file. Take a look * The `VisualNavigator`'s drag and tap listener events are moved to a new `addInputListener()` API. * The new `DirectionalNavigationAdapter` component replaces `EdgeTapNavigation`, helping you turn pages with the arrow and space keyboard keys, or taps on the edge of the screen. +### Deprecated + +#### Navigator + +* All the navigator `Activity` are deprecated in favor of the `Fragment` variants. + ### Fixed #### Navigator diff --git a/docs/migration-guide.md b/docs/migration-guide.md index 09f50ceba9..d95b4a2a58 100644 --- a/docs/migration-guide.md +++ b/docs/migration-guide.md @@ -29,6 +29,52 @@ dependencies { } ``` +### All resources now have the prefix `readium_`. + +To avoid conflicts when merging your app resources, all resources declared in the Readium toolkit now have the prefix `readium_`. This means that you must rename any layouts or strings you have overridden. Here is a comprehensive list of the changes. + +#### Layouts + +| Deprecated | New | +|-----------------------------|-----------------------------------------------| +| `activity_r2_viewpager` | `readium_navigator_viewpager` | +| `fragment_fxllayout_double` | `readium_navigator_fragment_fxllayout_double` | +| `fragment_fxllayout_single` | `readium_navigator_fragment_fxllayout_single` | +| `popup_footnote` | `readium_navigator_popup_footnote` | +| `r2_lcp_auth_dialog` | `readium_lcp_auth_dialog` | +| `viewpager_fragment_cbz` | `readium_navigator_viewpager_fragment_cbz` | +| `viewpager_fragment_epub` | `readium_navigator_viewpager_fragment_epub` | + +#### Dimensions + +| Deprecated | New | +|--------------------------------------|-------------------------------------------| +| `r2_navigator_epub_vertical_padding` | `readium_navigator_epub_vertical_padding` | + +#### Strings + +| Deprecated | New | +|---------------------------------------------|--------------------------------------------------| +| `r2_lcp_dialog_cancel` | `readium_lcp_dialog_cancel` | +| `r2_lcp_dialog_continue` | `readium_lcp_dialog_continue` | +| `r2_lcp_dialog_forgotPassphrase` | `readium_lcp_dialog_forgotPassphrase` | +| `r2_lcp_dialog_help` | `readium_lcp_dialog_help` | +| `r2_lcp_dialog_prompt` | `readium_lcp_dialog_prompt` | +| `r2_lcp_dialog_reason_invalidPassphrase` | `readium_lcp_dialog_reason_invalidPassphrase` | +| `r2_lcp_dialog_reason_passphraseNotFound` | `readium_lcp_dialog_reason_passphraseNotFound` | +| `r2_lcp_dialog_support_mail` | `readium_lcp_dialog_support_mail` | +| `r2_lcp_dialog_support_phone` | `readium_lcp_dialog_support_phone` | +| `r2_lcp_dialog_support_web` | `readium_lcp_dialog_support_web` | +| `r2_media_notification_channel_description` | `readium_media_notification_channel_description` | +| `r2_media_notification_channel_name` | `readium_media_notification_channel_name` | + +#### Drawables + +| Deprecated | New | +|-----------------------------------------|----------------------------------------------| +| `r2_media_notification_fastforward.xml` | `readium_media_notification_fastforward.xml` | +| `r2_media_notification_rewind.xml` | `readium_media_notification_rewind.xml` | + ### Publication assets In most cases, you no longer need to manually create a `PublicationAsset` to open a publication with diff --git a/readium/adapters/pdfium/build.gradle.kts b/readium/adapters/pdfium/build.gradle.kts index 8021c8dee7..b7a6fa47e9 100644 --- a/readium/adapters/pdfium/build.gradle.kts +++ b/readium/adapters/pdfium/build.gradle.kts @@ -40,6 +40,10 @@ android { namespace = "org.readium.adapters.pdfium" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-adapter-pdfium" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/adapters/pdfium/pdfium-document/build.gradle.kts b/readium/adapters/pdfium/pdfium-document/build.gradle.kts index 6113dec3c1..213d15c9e1 100644 --- a/readium/adapters/pdfium/pdfium-document/build.gradle.kts +++ b/readium/adapters/pdfium/pdfium-document/build.gradle.kts @@ -43,6 +43,10 @@ android { namespace = "org.readium.adapters.pdfium.document" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-adapter-pdfium-document" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/adapters/pdfium/pdfium-document/src/main/java/org/readium/adapters/pdfium/document/PdfiumDocument.kt b/readium/adapters/pdfium/pdfium-document/src/main/java/org/readium/adapters/pdfium/document/PdfiumDocument.kt index d6ffbff06e..baf4429263 100644 --- a/readium/adapters/pdfium/pdfium-document/src/main/java/org/readium/adapters/pdfium/document/PdfiumDocument.kt +++ b/readium/adapters/pdfium/pdfium-document/src/main/java/org/readium/adapters/pdfium/document/PdfiumDocument.kt @@ -15,7 +15,7 @@ import java.io.File import kotlin.reflect.KClass import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.readium.r2.shared.PdfSupport +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.error.getOrThrow import org.readium.r2.shared.extensions.md5 import org.readium.r2.shared.extensions.tryOrNull @@ -25,10 +25,9 @@ import org.readium.r2.shared.util.pdf.PdfDocumentFactory import org.readium.r2.shared.util.use import timber.log.Timber -@OptIn(PdfSupport::class) -class PdfiumDocument( - val core: PdfiumCore, - val document: _PdfiumDocument, +public class PdfiumDocument( + @InternalReadiumApi public val core: PdfiumCore, + @InternalReadiumApi public val document: _PdfiumDocument, override val identifier: String?, override val pageCount: Int ) : PdfDocument { @@ -69,10 +68,9 @@ class PdfiumDocument( override suspend fun close() {} - companion object + public companion object } -@OptIn(PdfSupport::class) private fun _PdfiumDocument.Bookmark.toOutlineNode(): PdfDocument.OutlineNode = PdfDocument.OutlineNode( title = title, @@ -80,8 +78,7 @@ private fun _PdfiumDocument.Bookmark.toOutlineNode(): PdfDocument.OutlineNode = children = children.map { it.toOutlineNode() } ) -@OptIn(PdfSupport::class) -class PdfiumDocumentFactory(context: Context) : PdfDocumentFactory { +public class PdfiumDocumentFactory(context: Context) : PdfDocumentFactory { override val documentType: KClass = PdfiumDocument::class diff --git a/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts b/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts index 31ce3a0f4d..f24ad57de2 100644 --- a/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts +++ b/readium/adapters/pdfium/pdfium-navigator/build.gradle.kts @@ -44,6 +44,10 @@ android { namespace = "org.readium.adapters.pdfium.navigator" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-adapter-pdfium-navigator" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDefaults.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDefaults.kt index 0515064caa..71234e372d 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDefaults.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDefaults.kt @@ -17,7 +17,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @see PdfiumPreferences */ @ExperimentalReadiumApi -data class PdfiumDefaults( +public data class PdfiumDefaults( val pageSpacing: Double? = null, val readingProgression: ReadingProgression? = null, ) diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDocumentFragment.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDocumentFragment.kt index d46f119120..d0185131b5 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDocumentFragment.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumDocumentFragment.kt @@ -27,7 +27,7 @@ import org.readium.r2.shared.resource.Resource import timber.log.Timber @ExperimentalReadiumApi -class PdfiumDocumentFragment internal constructor( +public class PdfiumDocumentFragment internal constructor( private val publication: Publication, private val link: Link, private val initialPageIndex: Int, @@ -36,9 +36,9 @@ class PdfiumDocumentFragment internal constructor( private val navigatorListener: PdfDocumentFragment.Listener? ) : PdfDocumentFragment() { - interface Listener { + public interface Listener { /** Called when configuring [PDFView]. */ - fun onConfigurePdfView(configurator: PDFView.Configurator) {} + public fun onConfigurePdfView(configurator: PDFView.Configurator) {} } override var settings: PdfiumSettings = settings diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumEngineProvider.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumEngineProvider.kt index 9f2d1c5e1d..1aa57bc84a 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumEngineProvider.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumEngineProvider.kt @@ -21,12 +21,12 @@ import org.readium.r2.shared.publication.Publication * the navigator for some preferences. */ @ExperimentalReadiumApi -class PdfiumEngineProvider( +public class PdfiumEngineProvider( private val listener: PdfiumDocumentFragment.Listener? = null, private val defaults: PdfiumDefaults = PdfiumDefaults() ) : PdfEngineProvider { - override suspend fun createDocumentFragment(input: PdfDocumentFragmentInput) = + override suspend fun createDocumentFragment(input: PdfDocumentFragmentInput): PdfiumDocumentFragment = PdfiumDocumentFragment( publication = input.publication, link = input.link, diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferences.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferences.kt index 951d56c58f..ccda67f7e3 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferences.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferences.kt @@ -23,7 +23,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi */ @ExperimentalReadiumApi @Serializable -data class PdfiumPreferences( +public data class PdfiumPreferences( val fit: Fit? = null, val pageSpacing: Double? = null, val readingProgression: ReadingProgression? = null, @@ -35,7 +35,7 @@ data class PdfiumPreferences( require(pageSpacing == null || pageSpacing >= 0) } - override operator fun plus(other: PdfiumPreferences) = + override operator fun plus(other: PdfiumPreferences): PdfiumPreferences = PdfiumPreferences( fit = other.fit ?: fit, pageSpacing = other.pageSpacing ?: pageSpacing, diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesEditor.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesEditor.kt index c4d0b2b768..1008054e0f 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesEditor.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesEditor.kt @@ -19,7 +19,7 @@ import org.readium.r2.shared.publication.Metadata * or ranges. */ @ExperimentalReadiumApi -class PdfiumPreferencesEditor internal constructor( +public class PdfiumPreferencesEditor internal constructor( initialPreferences: PdfiumPreferences, publicationMetadata: Metadata, defaults: PdfiumDefaults, @@ -49,7 +49,7 @@ class PdfiumPreferencesEditor internal constructor( /** * Indicates how pages should be laid out within the viewport. */ - val fit: EnumPreference = + public val fit: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.fit }, getEffectiveValue = { state.settings.fit }, @@ -61,7 +61,7 @@ class PdfiumPreferencesEditor internal constructor( /** * Space between pages in dp. */ - val pageSpacing: RangePreference = + public val pageSpacing: RangePreference = RangePreferenceDelegate( getValue = { preferences.pageSpacing }, getEffectiveValue = { state.settings.pageSpacing }, @@ -75,7 +75,7 @@ class PdfiumPreferencesEditor internal constructor( /** * Direction of the horizontal progression across pages. */ - val readingProgression: EnumPreference = + public val readingProgression: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.readingProgression }, getEffectiveValue = { state.settings.readingProgression }, @@ -87,7 +87,7 @@ class PdfiumPreferencesEditor internal constructor( /** * Indicates the axis along which pages should be laid out in scroll mode. */ - val scrollAxis: EnumPreference = + public val scrollAxis: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.scrollAxis }, getEffectiveValue = { state.settings.scrollAxis }, diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesFilters.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesFilters.kt index 75a1dc5f93..80c5a1f0b2 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesFilters.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesFilters.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * Suggested filter to keep only shared [PdfiumPreferences]. */ @ExperimentalReadiumApi -object PdfiumSharedPreferencesFilter : PreferencesFilter { +public object PdfiumSharedPreferencesFilter : PreferencesFilter { override fun filter(preferences: PdfiumPreferences): PdfiumPreferences = preferences.copy( @@ -25,7 +25,7 @@ object PdfiumSharedPreferencesFilter : PreferencesFilter { * Suggested filter to keep only publication-specific [PdfiumPreferences]. */ @ExperimentalReadiumApi -object PdfiumPublicationPreferencesFilter : PreferencesFilter { +public object PdfiumPublicationPreferencesFilter : PreferencesFilter { override fun filter(preferences: PdfiumPreferences): PdfiumPreferences = PdfiumPreferences( diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesSerializer.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesSerializer.kt index 8353a636d4..b0c3c595aa 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesSerializer.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumPreferencesSerializer.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * JSON serializer of [PdfiumPreferences]. */ @ExperimentalReadiumApi -class PdfiumPreferencesSerializer : PreferencesSerializer { +public class PdfiumPreferencesSerializer : PreferencesSerializer { override fun serialize(preferences: PdfiumPreferences): String = Json.encodeToString(PdfiumPreferences.serializer(), preferences) diff --git a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumSettings.kt b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumSettings.kt index dc83987411..99facf73a5 100644 --- a/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumSettings.kt +++ b/readium/adapters/pdfium/pdfium-navigator/src/main/java/org/readium/adapters/pdfium/navigator/PdfiumSettings.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @see PdfiumPreferences */ @ExperimentalReadiumApi -data class PdfiumSettings( +public data class PdfiumSettings( val fit: Fit, val pageSpacing: Double, val readingProgression: ReadingProgression, diff --git a/readium/adapters/pspdfkit/build.gradle.kts b/readium/adapters/pspdfkit/build.gradle.kts index e09623883c..4dd86a85bb 100644 --- a/readium/adapters/pspdfkit/build.gradle.kts +++ b/readium/adapters/pspdfkit/build.gradle.kts @@ -40,6 +40,10 @@ android { namespace = "org.readium.adapters.pspdfkit" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-adapter-pspdfkit" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts b/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts index a8ab144c29..da99ccbfdf 100644 --- a/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts +++ b/readium/adapters/pspdfkit/pspdfkit-document/build.gradle.kts @@ -43,6 +43,10 @@ android { namespace = "org.readium.adapters.pspdfkit.document" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-adapter-pspdfkit-document" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/adapters/pspdfkit/pspdfkit-document/src/main/java/org/readium/adapters/pspdfkit/document/PsPdfKitDocument.kt b/readium/adapters/pspdfkit/pspdfkit-document/src/main/java/org/readium/adapters/pspdfkit/document/PsPdfKitDocument.kt index f9445ca40e..5fa848f89f 100644 --- a/readium/adapters/pspdfkit/pspdfkit-document/src/main/java/org/readium/adapters/pspdfkit/document/PsPdfKitDocument.kt +++ b/readium/adapters/pspdfkit/pspdfkit-document/src/main/java/org/readium/adapters/pspdfkit/document/PsPdfKitDocument.kt @@ -25,7 +25,7 @@ import org.readium.r2.shared.util.pdf.PdfDocument import org.readium.r2.shared.util.pdf.PdfDocumentFactory import timber.log.Timber -class PsPdfKitDocumentFactory(context: Context) : PdfDocumentFactory { +public class PsPdfKitDocumentFactory(context: Context) : PdfDocumentFactory { private val context = context.applicationContext override val documentType: KClass = PsPdfKitDocument::class @@ -42,8 +42,8 @@ class PsPdfKitDocumentFactory(context: Context) : PdfDocumentFactory Unit = { Timber.e(it) } ) : DataProvider { diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts b/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts index 0b9a53a6e3..e3cda2e849 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/build.gradle.kts @@ -44,6 +44,10 @@ android { namespace = "org.readium.adapters.pspdfkit.navigator" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-adapter-pspdfkit-navigator" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitDefaults.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitDefaults.kt index e29906b6b7..3720958af9 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitDefaults.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitDefaults.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @see PsPdfKitPreferences */ @ExperimentalReadiumApi -data class PsPdfKitDefaults( +public data class PsPdfKitDefaults( val offsetFirstPage: Boolean? = null, val pageSpacing: Double? = null, val readingProgression: ReadingProgression? = null, diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitEngineProvider.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitEngineProvider.kt index 5fbc8d8f5c..7bbe6eb2e9 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitEngineProvider.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitEngineProvider.kt @@ -26,7 +26,7 @@ import org.readium.r2.shared.util.pdf.cachedIn * the navigator for some preferences. */ @ExperimentalReadiumApi -class PsPdfKitEngineProvider( +public class PsPdfKitEngineProvider( private val context: Context, private val defaults: PsPdfKitDefaults = PsPdfKitDefaults() ) : PdfEngineProvider { diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferences.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferences.kt index 329adfe66b..4f8910a1a1 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferences.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferences.kt @@ -23,7 +23,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi */ @ExperimentalReadiumApi @Serializable -data class PsPdfKitPreferences( +public data class PsPdfKitPreferences( val fit: Fit? = null, val offsetFirstPage: Boolean? = null, val pageSpacing: Double? = null, @@ -38,7 +38,7 @@ data class PsPdfKitPreferences( require(pageSpacing == null || pageSpacing >= 0) } - override operator fun plus(other: PsPdfKitPreferences) = + override operator fun plus(other: PsPdfKitPreferences): PsPdfKitPreferences = PsPdfKitPreferences( fit = other.fit ?: fit, offsetFirstPage = other.offsetFirstPage ?: offsetFirstPage, diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesEditor.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesEditor.kt index 5b01eca390..4791abbf23 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesEditor.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesEditor.kt @@ -30,7 +30,7 @@ import org.readium.r2.shared.publication.Metadata * or ranges. */ @ExperimentalReadiumApi -class PsPdfKitPreferencesEditor internal constructor( +public class PsPdfKitPreferencesEditor internal constructor( initialPreferences: PsPdfKitPreferences, publicationMetadata: Metadata, defaults: PsPdfKitDefaults, @@ -60,7 +60,7 @@ class PsPdfKitPreferencesEditor internal constructor( /** * Indicates how pages should be laid out within the viewport. */ - val fit: EnumPreference = + public val fit: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.fit }, getEffectiveValue = { state.settings.fit }, @@ -76,7 +76,7 @@ class PsPdfKitPreferencesEditor internal constructor( * - [scroll] is off * - [spread] are not disabled */ - val offsetFirstPage: Preference = + public val offsetFirstPage: Preference = PreferenceDelegate( getValue = { preferences.offsetFirstPage }, getEffectiveValue = { state.settings.offsetFirstPage }, @@ -87,7 +87,7 @@ class PsPdfKitPreferencesEditor internal constructor( /** * Space between pages in dp. */ - val pageSpacing: RangePreference = + public val pageSpacing: RangePreference = RangePreferenceDelegate( getValue = { preferences.pageSpacing }, getEffectiveValue = { state.settings.pageSpacing }, @@ -101,7 +101,7 @@ class PsPdfKitPreferencesEditor internal constructor( /** * Direction of the horizontal progression across pages. */ - val readingProgression: EnumPreference = + public val readingProgression: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.readingProgression }, getEffectiveValue = { state.settings.readingProgression }, @@ -113,7 +113,7 @@ class PsPdfKitPreferencesEditor internal constructor( /** * Indicates if pages should be handled using scrolling instead of pagination. */ - val scroll: Preference = + public val scroll: Preference = PreferenceDelegate( getValue = { preferences.scroll }, getEffectiveValue = { state.settings.scroll }, @@ -126,7 +126,7 @@ class PsPdfKitPreferencesEditor internal constructor( * * Only effective when [scroll] is on. */ - val scrollAxis: EnumPreference = + public val scrollAxis: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.scrollAxis }, getEffectiveValue = { state.settings.scrollAxis }, @@ -140,7 +140,7 @@ class PsPdfKitPreferencesEditor internal constructor( * * Only effective when [scroll] is off. */ - val spread: EnumPreference = + public val spread: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.spread }, getEffectiveValue = { state.settings.spread }, diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesFilters.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesFilters.kt index 28d01056e4..9a681699bc 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesFilters.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesFilters.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * Suggested filter to keep only shared [PsPdfKitPreferences]. */ @ExperimentalReadiumApi -object PsPdfKitSharedPreferencesFilter : PreferencesFilter { +public object PsPdfKitSharedPreferencesFilter : PreferencesFilter { override fun filter(preferences: PsPdfKitPreferences): PsPdfKitPreferences = preferences.copy( @@ -27,7 +27,7 @@ object PsPdfKitSharedPreferencesFilter : PreferencesFilter * Suggested filter to keep only publication-specific [PsPdfKitPreferences]. */ @ExperimentalReadiumApi -object PsPdfKitPublicationPreferencesFilter : PreferencesFilter { +public object PsPdfKitPublicationPreferencesFilter : PreferencesFilter { override fun filter(preferences: PsPdfKitPreferences): PsPdfKitPreferences = PsPdfKitPreferences( diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesSerializer.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesSerializer.kt index b461c1a9d9..e6f99faf3c 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesSerializer.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitPreferencesSerializer.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * JSON serializer of [PsPdfKitPreferences]. */ @ExperimentalReadiumApi -class PsPdfKitPreferencesSerializer : PreferencesSerializer { +public class PsPdfKitPreferencesSerializer : PreferencesSerializer { override fun serialize(preferences: PsPdfKitPreferences): String = Json.encodeToString(PsPdfKitPreferences.serializer(), preferences) diff --git a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitSettings.kt b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitSettings.kt index 7f90046e12..98898b455b 100644 --- a/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitSettings.kt +++ b/readium/adapters/pspdfkit/pspdfkit-navigator/src/main/java/org/readium/adapters/pspdfkit/navigator/PsPdfKitSettings.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @see PsPdfKitPreferences */ @ExperimentalReadiumApi -data class PsPdfKitSettings( +public data class PsPdfKitSettings( val fit: Fit, val offsetFirstPage: Boolean, val pageSpacing: Double, diff --git a/readium/lcp/build.gradle.kts b/readium/lcp/build.gradle.kts index 2c2d1842cd..c5a52f1ea3 100644 --- a/readium/lcp/build.gradle.kts +++ b/readium/lcp/build.gradle.kts @@ -41,6 +41,10 @@ android { namespace = "org.readium.r2.lcp" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-lcp" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpAuthenticating.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpAuthenticating.kt index 96a9ebc4a7..ca60ec85a8 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpAuthenticating.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpAuthenticating.kt @@ -13,7 +13,7 @@ import org.readium.r2.lcp.license.model.LicenseDocument import org.readium.r2.lcp.license.model.components.Link import org.readium.r2.lcp.license.model.components.lcp.User -interface LcpAuthenticating { +public interface LcpAuthenticating { /** * Retrieves the passphrase used to decrypt the given license. @@ -44,14 +44,14 @@ interface LcpAuthenticating { * @param sender Free object that can be used by reading apps to give some UX context when * presenting dialogs. */ - suspend fun retrievePassphrase( + public suspend fun retrievePassphrase( license: AuthenticatedLicense, reason: AuthenticationReason, allowUserInteraction: Boolean, sender: Any? = null ): String? - enum class AuthenticationReason { + public enum class AuthenticationReason { /** No matching passphrase was found. */ PassphraseNotFound, @@ -59,13 +59,13 @@ interface LcpAuthenticating { /** The provided passphrase was invalid. */ InvalidPassphrase; - companion object + public companion object } /** * @param document License Document being opened. */ - data class AuthenticatedLicense(val document: LicenseDocument) { + public data class AuthenticatedLicense(val document: LicenseDocument) { /** * A hint to be displayed to the User to help them remember the User Passphrase. @@ -100,22 +100,22 @@ interface LcpAuthenticating { } } -@Deprecated("Renamed to `LcpAuthenticating`", replaceWith = ReplaceWith("LcpAuthenticating")) -typealias LCPAuthenticating = LcpAuthenticating +@Deprecated("Renamed to `LcpAuthenticating`", replaceWith = ReplaceWith("LcpAuthenticating"), level = DeprecationLevel.ERROR) +public typealias LCPAuthenticating = LcpAuthenticating @Deprecated("Not used anymore", level = DeprecationLevel.ERROR) -interface LCPAuthenticationDelegate +public interface LCPAuthenticationDelegate -@Deprecated("Renamed to `LcpAuthenticating.AuthenticationReason`", replaceWith = ReplaceWith("LcpAuthenticating.AuthenticationReason")) -typealias LCPAuthenticationReason = LcpAuthenticating.AuthenticationReason +@Deprecated("Renamed to `LcpAuthenticating.AuthenticationReason`", replaceWith = ReplaceWith("LcpAuthenticating.AuthenticationReason"), level = DeprecationLevel.ERROR) +public typealias LCPAuthenticationReason = LcpAuthenticating.AuthenticationReason -@Deprecated("Renamed to `LcpAuthenticating.AuthenticatedLicense`", replaceWith = ReplaceWith("LcpAuthenticating.AuthenticatedLicense")) -typealias LCPAuthenticatedLicense = LcpAuthenticating.AuthenticatedLicense +@Deprecated("Renamed to `LcpAuthenticating.AuthenticatedLicense`", replaceWith = ReplaceWith("LcpAuthenticating.AuthenticatedLicense"), level = DeprecationLevel.ERROR) +public typealias LCPAuthenticatedLicense = LcpAuthenticating.AuthenticatedLicense -@Deprecated("Renamed to `PassphraseNotFound`", replaceWith = ReplaceWith("PassphraseNotFound")) -val LcpAuthenticating.AuthenticationReason.Companion.passphraseNotFound get() = - LcpAuthenticating.AuthenticationReason.PassphraseNotFound +@Deprecated("Renamed to `PassphraseNotFound`", replaceWith = ReplaceWith("PassphraseNotFound"), level = DeprecationLevel.ERROR) +public val LcpAuthenticating.AuthenticationReason.Companion.passphraseNotFound: LcpAuthenticating.AuthenticationReason + get() = LcpAuthenticating.AuthenticationReason.PassphraseNotFound -@Deprecated("Renamed to `InvalidPassphrase`", replaceWith = ReplaceWith("InvalidPassphrase")) -val LcpAuthenticating.AuthenticationReason.Companion.invalidPassphrase get() = - LcpAuthenticating.AuthenticationReason.InvalidPassphrase +@Deprecated("Renamed to `InvalidPassphrase`", replaceWith = ReplaceWith("InvalidPassphrase"), level = DeprecationLevel.ERROR) +public val LcpAuthenticating.AuthenticationReason.Companion.invalidPassphrase: LcpAuthenticating.AuthenticationReason + get() = LcpAuthenticating.AuthenticationReason.InvalidPassphrase diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt index d687447808..d756b7caa4 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt @@ -136,7 +136,7 @@ internal class LcpContentProtection( ?: return Try.failure( Publication.OpeningException.ParsingFailed( ThrowableError( - LcpException.Parsing.Url(rel = LicenseDocument.Rel.publication.rawValue) + LcpException.Parsing.Url(rel = LicenseDocument.Rel.publication.value) ) ) ) diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtectionService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtectionService.kt index 4512832d25..30e6af44b1 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtectionService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtectionService.kt @@ -13,7 +13,10 @@ import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.protection.ContentProtection import org.readium.r2.shared.publication.services.ContentProtectionService -class LcpContentProtectionService(val license: LcpLicense?, override val error: LcpException?) : ContentProtectionService { +public class LcpContentProtectionService( + public val license: LcpLicense?, + override val error: LcpException? +) : ContentProtectionService { override val isRestricted: Boolean = license == null @@ -22,11 +25,13 @@ class LcpContentProtectionService(val license: LcpLicense?, override val error: override val rights: ContentProtectionService.UserRights = license ?: ContentProtectionService.UserRights.AllRestricted - override val scheme = ContentProtection.Scheme.Lcp + override val scheme: ContentProtection.Scheme = ContentProtection.Scheme.Lcp - companion object { + public companion object { - fun createFactory(license: LcpLicense?, error: LcpException?): (Publication.Service.Context) -> LcpContentProtectionService = + public fun createFactory(license: LcpLicense?, error: LcpException?): ( + Publication.Service.Context + ) -> LcpContentProtectionService = { LcpContentProtectionService(license, error) } } } @@ -34,5 +39,5 @@ class LcpContentProtectionService(val license: LcpLicense?, override val error: /** * Returns the [LcpLicense] if the [Publication] is protected by LCP and the license is opened. */ -val Publication.lcpLicense: LcpLicense? +public val Publication.lcpLicense: LcpLicense? get() = findService(LcpContentProtectionService::class)?.license diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpDecryptorTest.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpDecryptorTest.kt index 978ef987e5..f26674ed15 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpDecryptorTest.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpDecryptorTest.kt @@ -19,7 +19,7 @@ import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.util.use import timber.log.Timber -suspend fun Publication.checkDecryption() { +internal suspend fun Publication.checkDecryption() { checkResourcesAreReadableInOneBlock(this) @@ -30,7 +30,7 @@ suspend fun Publication.checkDecryption() { checkExceedingRangesAreAllowed(this) } -private suspend fun checkResourcesAreReadableInOneBlock(publication: Publication) { +internal suspend fun checkResourcesAreReadableInOneBlock(publication: Publication) { Timber.d("checking resources are readable in one block") (publication.readingOrder + publication.resources) @@ -43,7 +43,7 @@ private suspend fun checkResourcesAreReadableInOneBlock(publication: Publication } } -private suspend fun checkLengthComputationIsCorrect(publication: Publication) { +internal suspend fun checkLengthComputationIsCorrect(publication: Publication) { Timber.d("checking length computation is correct") (publication.readingOrder + publication.resources) @@ -60,7 +60,7 @@ private suspend fun checkLengthComputationIsCorrect(publication: Publication) { } } -private suspend fun checkAllResourcesAreReadableByChunks(publication: Publication) { +internal suspend fun checkAllResourcesAreReadableByChunks(publication: Publication) { Timber.d("checking all resources are readable by chunks") (publication.readingOrder + publication.resources) @@ -77,7 +77,7 @@ private suspend fun checkAllResourcesAreReadableByChunks(publication: Publicatio } } -private suspend fun checkExceedingRangesAreAllowed(publication: Publication) { +internal suspend fun checkExceedingRangesAreAllowed(publication: Publication) { Timber.d("checking exceeding ranges are allowed") (publication.readingOrder + publication.resources) @@ -111,7 +111,7 @@ private suspend fun checkExceedingRangesAreAllowed(publication: Publication) { } } -private suspend fun Fetcher.Resource.readByChunks( +internal suspend fun Fetcher.Resource.readByChunks( chunkSize: Long, groundTruth: ByteArray, shuffle: Boolean = true diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpException.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpException.kt index dfa4bb5ba5..c5f6fdd495 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpException.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpException.kt @@ -12,14 +12,14 @@ import java.net.SocketTimeoutException import java.util.* import org.readium.r2.shared.UserException -sealed class LcpException( +public sealed class LcpException( userMessageId: Int, vararg args: Any, quantity: Int? = null, cause: Throwable? = null ) : UserException(userMessageId, quantity, *args, cause = cause) { - constructor(@StringRes userMessageId: Int, vararg args: Any, cause: Throwable? = null) : this(userMessageId, *args, quantity = null, cause = cause) - constructor( + protected constructor(@StringRes userMessageId: Int, vararg args: Any, cause: Throwable? = null) : this(userMessageId, *args, quantity = null, cause = cause) + protected constructor( @PluralsRes userMessageId: Int, quantity: Int, vararg args: Any, @@ -27,25 +27,25 @@ sealed class LcpException( ) : this(userMessageId, *args, quantity = quantity, cause = cause) /** The interaction is not available with this License. */ - object LicenseInteractionNotAvailable : LcpException(R.string.readium_lcp_exception_license_interaction_not_available) + public object LicenseInteractionNotAvailable : LcpException(R.string.readium_lcp_exception_license_interaction_not_available) /** This License's profile is not supported by liblcp. */ - object LicenseProfileNotSupported : LcpException(R.string.readium_lcp_exception_license_profile_not_supported) + public object LicenseProfileNotSupported : LcpException(R.string.readium_lcp_exception_license_profile_not_supported) /** Failed to retrieve the Certificate Revocation List. */ - object CrlFetching : LcpException(R.string.readium_lcp_exception_crl_fetching) + public object CrlFetching : LcpException(R.string.readium_lcp_exception_crl_fetching) /** A network request failed with the given exception. */ - class Network(override val cause: Throwable?) : LcpException(R.string.readium_lcp_exception_network, cause = cause) + public class Network(override val cause: Throwable?) : LcpException(R.string.readium_lcp_exception_network, cause = cause) /** * An unexpected LCP exception occurred. Please post an issue on r2-lcp-kotlin with the error * message and how to reproduce it. */ - class Runtime(override val message: String) : LcpException(R.string.readium_lcp_exception_runtime) + public class Runtime(override val message: String) : LcpException(R.string.readium_lcp_exception_runtime) /** An unknown low-level exception was reported. */ - class Unknown(override val cause: Throwable?) : LcpException(R.string.readium_lcp_exception_unknown) + public class Unknown(override val cause: Throwable?) : LcpException(R.string.readium_lcp_exception_unknown) /** * Errors while checking the status of the License, using the Status Document. @@ -55,17 +55,17 @@ sealed class LcpException( * time corresponding to the new status should be displayed (e.g. "The license expired on 01 * January 2018"). */ - sealed class LicenseStatus(userMessageId: Int, vararg args: Any, quantity: Int? = null) : LcpException(userMessageId, *args, quantity = quantity) { - constructor(@StringRes userMessageId: Int, vararg args: Any) : this(userMessageId, *args, quantity = null) - constructor(@PluralsRes userMessageId: Int, quantity: Int, vararg args: Any) : this(userMessageId, *args, quantity = quantity) + public sealed class LicenseStatus(userMessageId: Int, vararg args: Any, quantity: Int? = null) : LcpException(userMessageId, *args, quantity = quantity) { + protected constructor(@StringRes userMessageId: Int, vararg args: Any) : this(userMessageId, *args, quantity = null) + protected constructor(@PluralsRes userMessageId: Int, quantity: Int, vararg args: Any) : this(userMessageId, *args, quantity = quantity) - class Cancelled(val date: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_cancelled, date) + public class Cancelled(public val date: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_cancelled, date) - class Returned(val date: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_returned, date) + public class Returned(public val date: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_returned, date) - class NotStarted(val start: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_not_started, start) + public class NotStarted(public val start: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_not_started, start) - class Expired(val end: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_expired, end) + public class Expired(public val end: Date) : LicenseStatus(R.string.readium_lcp_exception_license_status_expired, end) /** * If the license has been revoked, the user message should display the number of devices which @@ -73,110 +73,112 @@ sealed class LcpException( * in the status document. If no event is logged in the status document, no such message should * appear (certainly not "The license was registered by 0 devices"). */ - class Revoked(val date: Date, val devicesCount: Int) : + public class Revoked(public val date: Date, public val devicesCount: Int) : LicenseStatus(R.plurals.readium_lcp_exception_license_status_revoked, devicesCount, date, devicesCount) } /** * Errors while renewing a loan. */ - sealed class Renew(@StringRes userMessageId: Int) : LcpException(userMessageId) { + public sealed class Renew(@StringRes userMessageId: Int) : LcpException(userMessageId) { /** Your publication could not be renewed properly. */ - object RenewFailed : Renew(R.string.readium_lcp_exception_renew_renew_failed) + public object RenewFailed : Renew(R.string.readium_lcp_exception_renew_renew_failed) /** Incorrect renewal period, your publication could not be renewed. */ - class InvalidRenewalPeriod(val maxRenewDate: Date?) : Renew(R.string.readium_lcp_exception_renew_invalid_renewal_period) + public class InvalidRenewalPeriod(public val maxRenewDate: Date?) : Renew(R.string.readium_lcp_exception_renew_invalid_renewal_period) /** An unexpected error has occurred on the licensing server. */ - object UnexpectedServerError : Renew(R.string.readium_lcp_exception_renew_unexpected_server_error) + public object UnexpectedServerError : Renew(R.string.readium_lcp_exception_renew_unexpected_server_error) } /** * Errors while returning a loan. */ - sealed class Return(@StringRes userMessageId: Int) : LcpException(userMessageId) { + public sealed class Return(@StringRes userMessageId: Int) : LcpException(userMessageId) { /** Your publication could not be returned properly. */ - object ReturnFailed : Return(R.string.readium_lcp_exception_return_return_failed) + public object ReturnFailed : Return(R.string.readium_lcp_exception_return_return_failed) /** Your publication has already been returned before or is expired. */ - object AlreadyReturnedOrExpired : Return(R.string.readium_lcp_exception_return_already_returned_or_expired) + public object AlreadyReturnedOrExpired : Return(R.string.readium_lcp_exception_return_already_returned_or_expired) /** An unexpected error has occurred on the licensing server. */ - object UnexpectedServerError : Return(R.string.readium_lcp_exception_return_unexpected_server_error) + public object UnexpectedServerError : Return(R.string.readium_lcp_exception_return_unexpected_server_error) } /** * Errors while parsing the License or Status JSON Documents. */ - sealed class Parsing(@StringRes userMessageId: Int = R.string.readium_lcp_exception_parsing) : LcpException(userMessageId) { + public sealed class Parsing( + @StringRes userMessageId: Int = R.string.readium_lcp_exception_parsing + ) : LcpException(userMessageId) { /** The JSON is malformed and can't be parsed. */ - object MalformedJSON : Parsing(R.string.readium_lcp_exception_parsing_malformed_json) + public object MalformedJSON : Parsing(R.string.readium_lcp_exception_parsing_malformed_json) /** The JSON is not representing a valid License Document. */ - object LicenseDocument : Parsing(R.string.readium_lcp_exception_parsing_license_document) + public object LicenseDocument : Parsing(R.string.readium_lcp_exception_parsing_license_document) /** The JSON is not representing a valid Status Document. */ - object StatusDocument : Parsing(R.string.readium_lcp_exception_parsing_status_document) + public object StatusDocument : Parsing(R.string.readium_lcp_exception_parsing_status_document) /** Invalid Link. */ - object Link : Parsing() + public object Link : Parsing() /** Invalid Encryption. */ - object Encryption : Parsing() + public object Encryption : Parsing() /** Invalid License Document Signature. */ - object Signature : Parsing() + public object Signature : Parsing() /** Invalid URL for link with [rel]. */ - class Url(val rel: String) : Parsing() + public class Url(public val rel: String) : Parsing() } /** * Errors while reading or writing a LCP container (LCPL, EPUB, LCPDF, etc.) */ - sealed class Container(@StringRes userMessageId: Int) : LcpException(userMessageId) { + public sealed class Container(@StringRes userMessageId: Int) : LcpException(userMessageId) { /** Can't access the container, it's format is wrong. */ - object OpenFailed : Container(R.string.readium_lcp_exception_container_open_failed) + public object OpenFailed : Container(R.string.readium_lcp_exception_container_open_failed) /** The file at given relative path is not found in the Container. */ - class FileNotFound(val path: String) : Container(R.string.readium_lcp_exception_container_file_not_found) + public class FileNotFound(public val path: String) : Container(R.string.readium_lcp_exception_container_file_not_found) /** Can't read the file at given relative path in the Container. */ - class ReadFailed(val path: String) : Container(R.string.readium_lcp_exception_container_read_failed) + public class ReadFailed(public val path: String) : Container(R.string.readium_lcp_exception_container_read_failed) /** Can't write the file at given relative path in the Container. */ - class WriteFailed(val path: String) : Container(R.string.readium_lcp_exception_container_write_failed) + public class WriteFailed(public val path: String) : Container(R.string.readium_lcp_exception_container_write_failed) } /** * An error occurred while checking the integrity of the License, it can't be retrieved. */ - sealed class LicenseIntegrity(@StringRes userMessageId: Int) : LcpException(userMessageId) { + public sealed class LicenseIntegrity(@StringRes userMessageId: Int) : LcpException(userMessageId) { - object CertificateRevoked : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_certificate_revoked) + public object CertificateRevoked : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_certificate_revoked) - object InvalidCertificateSignature : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_certificate_signature) + public object InvalidCertificateSignature : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_certificate_signature) - object InvalidLicenseSignatureDate : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_license_signature_date) + public object InvalidLicenseSignatureDate : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_license_signature_date) - object InvalidLicenseSignature : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_license_signature) + public object InvalidLicenseSignature : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_license_signature) - object InvalidUserKeyCheck : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_user_key_check) + public object InvalidUserKeyCheck : LicenseIntegrity(R.string.readium_lcp_exception_license_integrity_invalid_user_key_check) } - sealed class Decryption(@StringRes userMessageId: Int) : LcpException(userMessageId) { + public sealed class Decryption(@StringRes userMessageId: Int) : LcpException(userMessageId) { - object ContentKeyDecryptError : Decryption(R.string.readium_lcp_exception_decryption_content_key_decrypt_error) + public object ContentKeyDecryptError : Decryption(R.string.readium_lcp_exception_decryption_content_key_decrypt_error) - object ContentDecryptError : Decryption(R.string.readium_lcp_exception_decryption_content_decrypt_error) + public object ContentDecryptError : Decryption(R.string.readium_lcp_exception_decryption_content_decrypt_error) } - companion object { + public companion object { internal fun wrap(e: Exception?): LcpException = when (e) { is LcpException -> e @@ -186,8 +188,8 @@ sealed class LcpException( } } -@Deprecated("Renamed to `LcpException`", replaceWith = ReplaceWith("LcpException")) -typealias LCPError = LcpException +@Deprecated("Renamed to `LcpException`", replaceWith = ReplaceWith("LcpException"), level = DeprecationLevel.ERROR) +public typealias LCPError = LcpException -@Deprecated("Use `getUserMessage()` instead", replaceWith = ReplaceWith("getUserMessage(context)")) -val LcpException.errorDescription: String? get() = message +@Deprecated("Use `getUserMessage()` instead", replaceWith = ReplaceWith("getUserMessage(context)"), level = DeprecationLevel.ERROR) +public val LcpException.errorDescription: String? get() = message diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpLicense.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpLicense.kt index 87a077f16e..587bc6cc0f 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpLicense.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpLicense.kt @@ -22,40 +22,40 @@ import timber.log.Timber /** * Opened license, used to decipher a protected publication and manage its license. */ -interface LcpLicense : ContentProtectionService.UserRights { +public interface LcpLicense : ContentProtectionService.UserRights { /** * License Document information. * https://readium.org/lcp-specs/releases/lcp/latest.html */ - val license: LicenseDocument + public val license: LicenseDocument /** * License Status Document information. * https://readium.org/lcp-specs/releases/lsd/latest.html */ - val status: StatusDocument? + public val status: StatusDocument? /** * Number of remaining characters allowed to be copied by the user. If null, there's no limit. */ - val charactersToCopyLeft: Int? + public val charactersToCopyLeft: Int? /** * Number of pages allowed to be printed by the user. If null, there's no limit. */ - val pagesToPrintLeft: Int? + public val pagesToPrintLeft: Int? /** * Can the user renew the loaned publication? */ - val canRenewLoan: Boolean + public val canRenewLoan: Boolean /** * The maximum potential date to renew to. * If null, then the renew date might not be customizable. */ - val maxRenewDate: Date? + public val maxRenewDate: Date? /** * Renews the loan by starting a renew LSD interaction. @@ -63,22 +63,22 @@ interface LcpLicense : ContentProtectionService.UserRights { * @param prefersWebPage Indicates whether the loan should be renewed through a web page if * available, instead of programmatically. */ - suspend fun renewLoan(listener: RenewListener, prefersWebPage: Boolean = false): Try + public suspend fun renewLoan(listener: RenewListener, prefersWebPage: Boolean = false): Try /** * Can the user return the loaned publication? */ - val canReturnPublication: Boolean + public val canReturnPublication: Boolean /** * Returns the publication to its provider. */ - suspend fun returnPublication(): Try + public suspend fun returnPublication(): Try /** * Decrypts the given [data] encrypted with the license's content key. */ - suspend fun decrypt(data: ByteArray): Try + public suspend fun decrypt(data: ByteArray): Try /** * UX delegate for the loan renew LSD interaction. @@ -86,7 +86,7 @@ interface LcpLicense : ContentProtectionService.UserRights { * If your application fits Material Design guidelines, take a look at [MaterialRenewListener] * for a default implementation. */ - interface RenewListener { + public interface RenewListener { /** * Called when the renew interaction allows to customize the end date programmatically. @@ -94,7 +94,7 @@ interface LcpLicense : ContentProtectionService.UserRights { * * The returned date can't exceed [maximumDate]. */ - suspend fun preferredEndDate(maximumDate: Date?): Date? + public suspend fun preferredEndDate(maximumDate: Date?): Date? /** * Called when the renew interaction uses an HTML web page. @@ -102,40 +102,40 @@ interface LcpLicense : ContentProtectionService.UserRights { * You should present the URL in a Chrome Custom Tab and terminate the function when the * web page is dismissed by the user. */ - suspend fun openWebPage(url: URL) + public suspend fun openWebPage(url: URL) } - @Deprecated("Use `license.encryption.profile` instead", ReplaceWith("license.encryption.profile")) - val encryptionProfile: String? get() = + @Deprecated("Use `license.encryption.profile` instead", ReplaceWith("license.encryption.profile"), level = DeprecationLevel.ERROR) + public val encryptionProfile: String? get() = license.encryption.profile - @Deprecated("Use `decrypt()` with coroutines instead", ReplaceWith("decrypt(data)")) - fun decipher(data: ByteArray): ByteArray? = + @Deprecated("Use `decrypt()` with coroutines instead", ReplaceWith("decrypt(data)"), level = DeprecationLevel.ERROR) + public fun decipher(data: ByteArray): ByteArray? = runBlocking { decrypt(data) } .onFailure { Timber.e(it) } .getOrNull() @Deprecated("Use `renewLoan` with `RenewListener` instead", ReplaceWith("renewLoan(LcpLicense.RenewListener)"), level = DeprecationLevel.ERROR) - suspend fun renewLoan(end: DateTime?, urlPresenter: suspend (URL) -> Unit): Try = Try.success(Unit) + public suspend fun renewLoan(end: DateTime?, urlPresenter: suspend (URL) -> Unit): Try = Try.success(Unit) @Deprecated("Use `renewLoan` with `RenewListener` instead", ReplaceWith("renewLoan(LcpLicense.RenewListener)"), level = DeprecationLevel.ERROR) - fun renewLoan( + public fun renewLoan( end: DateTime?, present: (URL, dismissed: () -> Unit) -> Unit, completion: (LcpException?) -> Unit ) {} - @Deprecated("Use `returnPublication()` with coroutines instead", ReplaceWith("returnPublication")) + @Deprecated("Use `returnPublication()` with coroutines instead", ReplaceWith("returnPublication"), level = DeprecationLevel.ERROR) @DelicateCoroutinesApi - fun returnPublication(completion: (LcpException?) -> Unit) { + public fun returnPublication(completion: (LcpException?) -> Unit) { GlobalScope.launch { completion(returnPublication().failureOrNull()) } } } -@Deprecated("Renamed to `LcpService`", replaceWith = ReplaceWith("LcpService")) -typealias LCPService = LcpService +@Deprecated("Renamed to `LcpService`", replaceWith = ReplaceWith("LcpService"), level = DeprecationLevel.ERROR) +public typealias LCPService = LcpService -@Deprecated("Renamed to `LcpLicense`", replaceWith = ReplaceWith("LcpLicense")) -typealias LCPLicense = LcpLicense +@Deprecated("Renamed to `LcpLicense`", replaceWith = ReplaceWith("LcpLicense"), level = DeprecationLevel.ERROR) +public typealias LCPLicense = LcpLicense diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt index 68e098b463..9ed8491896 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt @@ -40,17 +40,17 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever /** * Service used to acquire and open publications protected with LCP. */ -interface LcpService { +public interface LcpService { /** * Returns if the file is a LCP license document or a publication protected by LCP. */ - suspend fun isLcpProtected(file: File): Boolean + public suspend fun isLcpProtected(file: File): Boolean /** * Returns if the asset is a LCP license document or a publication protected by LCP. */ - suspend fun isLcpProtected(asset: Asset): Boolean + public suspend fun isLcpProtected(asset: Asset): Boolean /** * Acquires a protected publication from a standalone LCPL's bytes. @@ -59,7 +59,7 @@ interface LcpService { * * @param onProgress Callback to follow the acquisition progress from 0.0 to 1.0. */ - suspend fun acquirePublication(lcpl: ByteArray, onProgress: (Double) -> Unit = {}): Try + public suspend fun acquirePublication(lcpl: ByteArray, onProgress: (Double) -> Unit = {}): Try /** * Acquires a protected publication from a standalone LCPL file. @@ -68,7 +68,7 @@ interface LcpService { * * @param onProgress Callback to follow the acquisition progress from 0.0 to 1.0. */ - suspend fun acquirePublication(lcpl: File, onProgress: (Double) -> Unit = {}): Try = withContext(Dispatchers.IO) { + public suspend fun acquirePublication(lcpl: File, onProgress: (Double) -> Unit = {}): Try = withContext(Dispatchers.IO) { try { acquirePublication(lcpl.readBytes(), onProgress) } catch (e: Exception) { @@ -87,7 +87,7 @@ interface LcpService { * @param sender Free object that can be used by reading apps to give some UX context when * presenting dialogs with [LcpAuthenticating]. */ - suspend fun retrieveLicense( + public suspend fun retrieveLicense( file: File, mediaType: MediaType, authentication: LcpAuthenticating = LcpDialogAuthentication(), @@ -108,7 +108,7 @@ interface LcpService { * @param sender Free object that can be used by reading apps to give some UX context when * presenting dialogs with [LcpAuthenticating]. */ - suspend fun retrieveLicense( + public suspend fun retrieveLicense( asset: Asset, authentication: LcpAuthenticating = LcpDialogAuthentication(), allowUserInteraction: Boolean, @@ -123,7 +123,7 @@ interface LcpService { * LCP license. The default implementation [LcpDialogAuthentication] presents a dialog to the * user to enter their passphrase. */ - fun contentProtection( + public fun contentProtection( authentication: LcpAuthenticating = LcpDialogAuthentication(), ): ContentProtection @@ -135,20 +135,20 @@ interface LcpService { * @param suggestedFilename Filename that should be used for the publication when importing it in * the user library. */ - data class AcquiredPublication( + public data class AcquiredPublication( val localFile: File, val suggestedFilename: String ) { - @Deprecated("Use `localFile` instead", replaceWith = ReplaceWith("localFile")) + @Deprecated("Use `localFile` instead", replaceWith = ReplaceWith("localFile"), level = DeprecationLevel.ERROR) val localURL: String get() = localFile.path } - companion object { + public companion object { /** * LCP service factory. */ - operator fun invoke( + public operator fun invoke( context: Context, mediaTypeRetriever: MediaTypeRetriever = MediaTypeRetriever(), resourceFactory: ResourceFactory = FileResourceFactory(), @@ -179,12 +179,12 @@ interface LcpService { } @Deprecated("Use `LcpService()` instead", ReplaceWith("LcpService(context)"), level = DeprecationLevel.ERROR) - fun create(context: Context): LcpService? = invoke(context) + public fun create(context: Context): LcpService? = invoke(context) } @Deprecated("Use `acquirePublication()` with coroutines instead", ReplaceWith("acquirePublication(lcpl)"), level = DeprecationLevel.ERROR) @DelicateCoroutinesApi - fun importPublication( + public fun importPublication( lcpl: ByteArray, authentication: LcpAuthenticating?, completion: (AcquiredPublication?, LcpException?) -> Unit @@ -198,7 +198,7 @@ interface LcpService { @Deprecated("Use `retrieveLicense()` with coroutines instead", ReplaceWith("retrieveLicense(File(publication), authentication, allowUserInteraction = true)"), level = DeprecationLevel.ERROR) @DelicateCoroutinesApi - fun retrieveLicense( + public fun retrieveLicense( publication: String, authentication: LcpAuthenticating?, completion: (LcpLicense?, LcpException?) -> Unit @@ -208,8 +208,8 @@ interface LcpService { } @Deprecated("Renamed to `LcpService()`", replaceWith = ReplaceWith("LcpService(context)"), level = DeprecationLevel.ERROR) -fun R2MakeLCPService(context: Context): LcpService = +public fun R2MakeLCPService(context: Context): LcpService = LcpService(context) ?: throw Exception("liblcp is missing on the classpath") @Deprecated("Renamed to `LcpService.AcquiredPublication`", replaceWith = ReplaceWith("LcpService.AcquiredPublication"), level = DeprecationLevel.ERROR) -typealias LCPImportedPublication = LcpService.AcquiredPublication +public typealias LCPImportedPublication = LcpService.AcquiredPublication diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/MaterialRenewListener.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/MaterialRenewListener.kt index 5661a01aaa..8748e50801 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/MaterialRenewListener.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/MaterialRenewListener.kt @@ -31,7 +31,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine * @param caller Activity or Fragment used to register the ActivityResultLauncher. * @param fragmentManager FragmentManager used to present the date picker. */ -class MaterialRenewListener( +public class MaterialRenewListener( private val license: LcpLicense, private val caller: ActivityResultCaller, private val fragmentManager: FragmentManager @@ -73,14 +73,16 @@ class MaterialRenewListener( .show(fragmentManager, "MaterialRenewListener.DatePicker") } - override suspend fun openWebPage(url: URL) = suspendCoroutine { cont -> - webPageContinuation = cont + override suspend fun openWebPage(url: URL) { + suspendCoroutine { cont -> + webPageContinuation = cont - webPageLauncher.launch( - CustomTabsIntent.Builder().build().intent.apply { - data = Uri.parse(url.toString()) - } - ) + webPageLauncher.launch( + CustomTabsIntent.Builder().build().intent.apply { + data = Uri.parse(url.toString()) + } + ) + } } private var webPageContinuation: Continuation? = null diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpDialogAuthentication.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpDialogAuthentication.kt index 50f033e93e..6f75000c4f 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpDialogAuthentication.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpDialogAuthentication.kt @@ -39,11 +39,11 @@ import timber.log.Timber /** * An [LcpAuthenticating] implementation presenting a dialog to the user. * - * For this authentication to trigger, you must provide a [sender] parameter of type [Activity], + * For this authentication to trigger, you must provide a sender parameter of type [Activity], * [Fragment] or [View] to `Streamer::open()` or `LcpService::retrieveLicense()`. It will be used as * the host view for the dialog. */ -class LcpDialogAuthentication : LcpAuthenticating { +public class LcpDialogAuthentication : LcpAuthenticating { override suspend fun retrievePassphrase( license: LcpAuthenticating.AuthenticatedLicense, diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpPassphraseAuthentication.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpPassphraseAuthentication.kt index 84f87b0462..f05df57f5e 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpPassphraseAuthentication.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/auth/LcpPassphraseAuthentication.kt @@ -14,7 +14,7 @@ import org.readium.r2.lcp.LcpAuthenticating * * If the provided [passphrase] is incorrect, the given [fallback] authentication is used. */ -class LcpPassphraseAuthentication( +public class LcpPassphraseAuthentication( private val passphrase: String, private val fallback: LcpAuthenticating? = null ) : LcpAuthenticating { diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/LicenseDocument.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/LicenseDocument.kt index 0843124d27..34cf6f76b0 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/LicenseDocument.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/LicenseDocument.kt @@ -25,27 +25,30 @@ import org.readium.r2.shared.extensions.iso8601ToDate import org.readium.r2.shared.extensions.optNullableString import org.readium.r2.shared.util.mediatype.MediaType -class LicenseDocument(val data: ByteArray) { - val provider: String - val id: String - val issued: Date - val updated: Date - val encryption: Encryption - val links: Links - val user: User - val rights: Rights - val signature: Signature - val json: JSONObject +public class LicenseDocument(public val data: ByteArray) { + public val provider: String + public val id: String + public val issued: Date + public val updated: Date + public val encryption: Encryption + public val links: Links + public val user: User + public val rights: Rights + public val signature: Signature + public val json: JSONObject - enum class Rel(val rawValue: String) { + public enum class Rel(public val value: String) { hint("hint"), publication("publication"), self("self"), support("support"), status("status"); - companion object { - operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue } + @Deprecated("Use [value] instead", ReplaceWith("value"), level = DeprecationLevel.ERROR) + public val rawValue: String get() = value + + public companion object { + public operator fun invoke(value: String): Rel? = values().firstOrNull { it.value == value } } } @@ -71,20 +74,24 @@ class LicenseDocument(val data: ByteArray) { } } - fun link(rel: Rel, type: MediaType? = null): Link? = - links.firstWithRel(rel.rawValue, type) + public fun link(rel: Rel, type: MediaType? = null): Link? = + links.firstWithRel(rel.value, type) - fun links(rel: Rel, type: MediaType? = null): List = - links.allWithRel(rel.rawValue, type) + public fun links(rel: Rel, type: MediaType? = null): List = + links.allWithRel(rel.value, type) - fun url(rel: Rel, preferredType: MediaType? = null, parameters: URLParameters = emptyMap()): URL { + public fun url( + rel: Rel, + preferredType: MediaType? = null, + parameters: URLParameters = emptyMap() + ): URL { val link = link(rel, preferredType) - ?: links.firstWithRelAndNoType(rel.rawValue) - ?: throw LcpException.Parsing.Url(rel = rel.rawValue) + ?: links.firstWithRelAndNoType(rel.value) + ?: throw LcpException.Parsing.Url(rel = rel.value) return link.url(parameters) } - val description: String + public val description: String get() = "License($id)" } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/StatusDocument.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/StatusDocument.kt index b15c8671f0..fc0e03e1c3 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/StatusDocument.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/StatusDocument.kt @@ -24,19 +24,19 @@ import org.readium.r2.shared.extensions.mapNotNull import org.readium.r2.shared.extensions.optNullableString import org.readium.r2.shared.util.mediatype.MediaType -class StatusDocument(val data: ByteArray) { - val id: String - val status: Status - val message: String - val licenseUpdated: Date - val statusUpdated: Date - val links: Links - val potentialRights: PotentialRights? - val events: List - - val json: JSONObject - - enum class Status(val rawValue: String) { +public class StatusDocument(public val data: ByteArray) { + public val id: String + public val status: Status + public val message: String + public val licenseUpdated: Date + public val statusUpdated: Date + public val links: Links + public val potentialRights: PotentialRights? + public val events: List + + public val json: JSONObject + + public enum class Status(public val value: String) { ready("ready"), active("active"), revoked("revoked"), @@ -44,19 +44,25 @@ class StatusDocument(val data: ByteArray) { cancelled("cancelled"), expired("expired"); - companion object { - operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue } + @Deprecated("Use [value] instead", ReplaceWith("value"), level = DeprecationLevel.ERROR) + public val rawValue: String get() = value + + public companion object { + public operator fun invoke(value: String): Status? = values().firstOrNull { it.value == value } } } - enum class Rel(val rawValue: String) { + public enum class Rel(public val value: String) { register("register"), license("license"), `return`("return"), renew("renew"); - companion object { - operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue } + @Deprecated("Use [value] instead", ReplaceWith("value"), level = DeprecationLevel.ERROR) + public val rawValue: String get() = value + + public companion object { + public operator fun invoke(value: String): Rel? = values().firstOrNull { it.value == value } } } @@ -86,29 +92,33 @@ class StatusDocument(val data: ByteArray) { ?: emptyList() } - fun link(rel: Rel, type: MediaType? = null): Link? = - links.firstWithRel(rel.rawValue, type) + public fun link(rel: Rel, type: MediaType? = null): Link? = + links.firstWithRel(rel.value, type) - fun links(rel: Rel, type: MediaType? = null): List = - links.allWithRel(rel.rawValue, type) + public fun links(rel: Rel, type: MediaType? = null): List = + links.allWithRel(rel.value, type) internal fun linkWithNoType(rel: Rel): Link? = - links.firstWithRelAndNoType(rel.rawValue) + links.firstWithRelAndNoType(rel.value) - fun url(rel: Rel, preferredType: MediaType? = null, parameters: URLParameters = emptyMap()): URL { + public fun url( + rel: Rel, + preferredType: MediaType? = null, + parameters: URLParameters = emptyMap() + ): URL { val link = link(rel, preferredType) ?: linkWithNoType(rel) - ?: throw LcpException.Parsing.Url(rel = rel.rawValue) + ?: throw LcpException.Parsing.Url(rel = rel.value) return link.url(parameters) } - fun events(type: Event.EventType): List = - events(type.rawValue) + public fun events(type: Event.EventType): List = + events(type.value) - fun events(type: String): List = + public fun events(type: String): List = events.filter { it.type == type } - val description: String - get() = "Status(${status.rawValue})" + public val description: String + get() = "Status(${status.value})" } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Link.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Link.kt index b001bf4315..da669629c6 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Link.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Link.kt @@ -19,9 +19,9 @@ import org.readium.r2.shared.publication.Link import org.readium.r2.shared.util.URITemplate import org.readium.r2.shared.util.mediatype.MediaType -data class Link(val json: JSONObject) { +public data class Link(val json: JSONObject) { val href: String - var rel = mutableListOf() + var rel: MutableList = mutableListOf() val title: String? val type: String? val templated: Boolean @@ -56,7 +56,7 @@ data class Link(val json: JSONObject) { hash = if (json.has("hash")) json.getString("hash") else null } - fun url(parameters: URLParameters): URL { + public fun url(parameters: URLParameters): URL { if (!templated) { return URL(href) } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Links.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Links.kt index 02fda8880b..d7e236345c 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Links.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/Links.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.extensions.mapNotNull import org.readium.r2.shared.extensions.tryOrNull import org.readium.r2.shared.util.mediatype.MediaType -data class Links(val json: JSONArray) { +public data class Links(val json: JSONArray) { val links: List = json .mapNotNull { item -> @@ -24,17 +24,17 @@ data class Links(val json: JSONArray) { } } - fun firstWithRel(rel: String, type: MediaType? = null): Link? = + public fun firstWithRel(rel: String, type: MediaType? = null): Link? = links.firstOrNull { it.matches(rel, type) } internal fun firstWithRelAndNoType(rel: String): Link? = links.firstOrNull { it.rel.contains(rel) && it.type == null } - fun allWithRel(rel: String, type: MediaType? = null): List = + public fun allWithRel(rel: String, type: MediaType? = null): List = links.filter { it.matches(rel, type) } private fun Link.matches(rel: String, type: MediaType?): Boolean = this.rel.contains(rel) && (type?.matches(this.type) ?: true) - operator fun get(rel: String): List = allWithRel(rel) + public operator fun get(rel: String): List = allWithRel(rel) } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/ContentKey.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/ContentKey.kt index c28dbe6dfb..cc74da1fcb 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/ContentKey.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/ContentKey.kt @@ -12,7 +12,7 @@ package org.readium.r2.lcp.license.model.components.lcp import org.json.JSONObject import org.readium.r2.lcp.LcpException -data class ContentKey(val json: JSONObject) { +public data class ContentKey(val json: JSONObject) { val algorithm: String val encryptedValue: String diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Encryption.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Encryption.kt index d25f1366bd..90ed33d836 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Encryption.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Encryption.kt @@ -12,7 +12,7 @@ package org.readium.r2.lcp.license.model.components.lcp import org.json.JSONObject import org.readium.r2.lcp.LcpException -data class Encryption(val json: JSONObject) { +public data class Encryption(val json: JSONObject) { val profile: String val contentKey: ContentKey val userKey: UserKey diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Rights.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Rights.kt index 104cdde54e..a3ca648390 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Rights.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Rights.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.extensions.iso8601ToDate import org.readium.r2.shared.extensions.optNullableInt import org.readium.r2.shared.extensions.optNullableString -data class Rights(val json: JSONObject) { +public data class Rights(val json: JSONObject) { val print: Int? val copy: Int? val start: Date? diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Signature.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Signature.kt index a8dd863f80..0e28d48b77 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Signature.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Signature.kt @@ -13,7 +13,7 @@ import org.json.JSONObject import org.readium.r2.lcp.LcpException import org.readium.r2.shared.extensions.optNullableString -data class Signature(val json: JSONObject) { +public data class Signature(val json: JSONObject) { val algorithm: String = json.optNullableString("algorithm") ?: throw LcpException.Parsing.Signature val certificate: String = json.optNullableString("certificate") ?: throw LcpException.Parsing.Signature val value: String = json.optNullableString("value") ?: throw LcpException.Parsing.Signature diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/User.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/User.kt index ad5a5081fc..9411d85575 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/User.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/User.kt @@ -12,12 +12,12 @@ package org.readium.r2.lcp.license.model.components.lcp import org.json.JSONObject -data class User(val json: JSONObject) { +public data class User(val json: JSONObject) { val id: String? val email: String? val name: String? var extensions: JSONObject - var encrypted = mutableListOf() + var encrypted: MutableList = mutableListOf() init { id = if (json.has("id")) json.getString("id") else null diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/UserKey.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/UserKey.kt index 8e55c83548..f61f2a4bf6 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/UserKey.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/UserKey.kt @@ -12,7 +12,7 @@ package org.readium.r2.lcp.license.model.components.lcp import org.json.JSONObject import org.readium.r2.lcp.LcpException -data class UserKey(val json: JSONObject) { +public data class UserKey(val json: JSONObject) { val textHint: String val algorithm: String val keyCheck: String diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/Event.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/Event.kt index 291c175d21..c87ce9e63c 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/Event.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/Event.kt @@ -14,21 +14,24 @@ import org.json.JSONObject import org.readium.r2.shared.extensions.iso8601ToDate import org.readium.r2.shared.extensions.optNullableString -data class Event(val json: JSONObject) { +public data class Event(val json: JSONObject) { val type: String = json.optNullableString("type") ?: "" val name: String = json.optNullableString("name") ?: "" val id: String = json.optNullableString("id") ?: "" val date: Date? = json.optNullableString("timestamp")?.iso8601ToDate() - enum class EventType(val rawValue: String) { + public enum class EventType(public val value: String) { register("register"), renew("renew"), `return`("return"), revoke("revoke"), cancel("cancel"); - companion object { - operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue } + @Deprecated("Use [value] instead", ReplaceWith("value"), level = DeprecationLevel.ERROR) + public val rawValue: String get() = value + + public companion object { + public operator fun invoke(value: String): EventType? = values().firstOrNull { it.value == value } } } } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/PotentialRights.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/PotentialRights.kt index 519740b860..389fc23fa3 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/PotentialRights.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lsd/PotentialRights.kt @@ -14,6 +14,6 @@ import org.json.JSONObject import org.readium.r2.shared.extensions.iso8601ToDate import org.readium.r2.shared.extensions.optNullableString -data class PotentialRights(val json: JSONObject) { +public data class PotentialRights(val json: JSONObject) { val end: Date? = json.optNullableString("end")?.iso8601ToDate() } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDao.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDao.kt index 80f6b22975..0bc65434d3 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDao.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDao.kt @@ -6,7 +6,7 @@ import androidx.room.OnConflictStrategy import androidx.room.Query @Dao -interface LcpDao { +internal interface LcpDao { /** * Retrieve passphrase diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/License.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/License.kt index 7f0f31be04..de02041a4c 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/License.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/License.kt @@ -14,7 +14,7 @@ import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = License.TABLE_NAME) -data class License( +internal data class License( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = ID) var id: Long? = null, diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/Passphrase.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/Passphrase.kt index 4b7fbfbc15..8e64c3ceae 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/Passphrase.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/persistence/Passphrase.kt @@ -14,7 +14,7 @@ import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = Passphrase.TABLE_NAME) -data class Passphrase( +internal data class Passphrase( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = ID) var id: Long? = null, diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/public/Deprecated.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/public/Deprecated.kt index f6b44cfa8f..18dd684d5e 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/public/Deprecated.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/public/Deprecated.kt @@ -16,26 +16,26 @@ import org.readium.r2.lcp.LcpLicense import org.readium.r2.lcp.LcpService @Deprecated("Renamed to `LcpService`", ReplaceWith("org.readium.r2.lcp.LcpService"), level = DeprecationLevel.ERROR) -typealias LCPService = LcpService +public typealias LCPService = LcpService @Deprecated("Renamed to `LcpService.AcquiredPublication`", ReplaceWith("org.readium.r2.lcp.LcpService.AcquiredPublication"), level = DeprecationLevel.ERROR) -typealias LCPImportedPublication = LcpService.AcquiredPublication +public typealias LCPImportedPublication = LcpService.AcquiredPublication @Deprecated("Not used anymore", level = DeprecationLevel.ERROR) -typealias URLPresenter = () -> Unit +public typealias URLPresenter = () -> Unit @Deprecated("Renamed to `LcpLicense`", ReplaceWith("org.readium.r2.lcp.LcpLicense"), level = DeprecationLevel.ERROR) -typealias LCPLicense = LcpLicense +public typealias LCPLicense = LcpLicense @Deprecated("Renamed to `LcpAuthenticating`", ReplaceWith("org.readium.r2.lcp.LcpAuthenticating"), level = DeprecationLevel.ERROR) -typealias LCPAuthenticating = LcpAuthenticating +public typealias LCPAuthenticating = LcpAuthenticating @Deprecated("Not used anymore", level = DeprecationLevel.ERROR) -interface LCPAuthenticationDelegate +public interface LCPAuthenticationDelegate @Deprecated("Renamed to `LcpAuthenticating.AuthenticationReason`", ReplaceWith("org.readium.r2.lcp.LcpAuthenticating.AuthenticationReason"), level = DeprecationLevel.ERROR) -typealias LCPAuthenticationReason = LcpAuthenticating.AuthenticationReason +public typealias LCPAuthenticationReason = LcpAuthenticating.AuthenticationReason @Deprecated("Renamed to `LcpAuthenticating.AuthenticatedLicense`", ReplaceWith("org.readium.r2.lcp.LcpAuthenticating.AuthenticatedLicense"), level = DeprecationLevel.ERROR) -typealias LCPAuthenticatedLicense = LcpAuthenticating.AuthenticatedLicense +public typealias LCPAuthenticatedLicense = LcpAuthenticating.AuthenticatedLicense @Deprecated("Renamed to `LcpException", ReplaceWith("org.readium.r2.lcp.LcpException"), level = DeprecationLevel.ERROR) -typealias LCPError = LcpException +public typealias LCPError = LcpException @Deprecated("Renamed to `LcpService()`", ReplaceWith("LcpService()"), level = DeprecationLevel.ERROR) -fun R2MakeLCPService(context: Context) = +public fun R2MakeLCPService(context: Context): LcpService? = LcpService(context) diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt index 9e0de40c18..d73b5bbfea 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt @@ -220,7 +220,7 @@ internal class LicensesService( private suspend fun fetchPublication(license: LicenseDocument, onProgress: (Double) -> Unit): LcpService.AcquiredPublication { val link = license.link(LicenseDocument.Rel.publication) val url = link?.url - ?: throw LcpException.Parsing.Url(rel = LicenseDocument.Rel.publication.rawValue) + ?: throw LcpException.Parsing.Url(rel = LicenseDocument.Rel.publication.value) val destination = withContext(Dispatchers.IO) { File.createTempFile("lcp-${System.currentTimeMillis()}", ".tmp") diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/service/NetworkService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/service/NetworkService.kt index ff4d7524fa..1de9ddf4e7 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/service/NetworkService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/service/NetworkService.kt @@ -33,11 +33,11 @@ internal class NetworkException(val status: Int?, cause: Throwable? = null) : Ex internal class NetworkService( private val mediaTypeRetriever: MediaTypeRetriever ) { - enum class Method(val rawValue: String) { + enum class Method(val value: String) { GET("GET"), POST("POST"), PUT("PUT"); companion object { - operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue } + operator fun invoke(value: String) = values().firstOrNull { it.value == value } } } @@ -54,7 +54,7 @@ internal class NetworkService( val url = URL(Uri.parse(url).buildUpon().appendQueryParameters(parameters).build().toString()) val connection = url.openConnection() as HttpURLConnection - connection.requestMethod = method.rawValue + connection.requestMethod = method.value if (timeout != null) { connection.connectTimeout = timeout.inWholeMilliseconds.toInt() } diff --git a/readium/navigator-media2/build.gradle.kts b/readium/navigator-media2/build.gradle.kts index 2512435bf7..9d1368ac77 100644 --- a/readium/navigator-media2/build.gradle.kts +++ b/readium/navigator-media2/build.gradle.kts @@ -43,6 +43,10 @@ android { namespace = "org.readium.navigator.media2" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-navigator-media2" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/ExoPlayerDataSource.kt b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/ExoPlayerDataSource.kt index 88cc175613..639ae6839e 100644 --- a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/ExoPlayerDataSource.kt +++ b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/ExoPlayerDataSource.kt @@ -20,18 +20,18 @@ import org.readium.r2.shared.fetcher.Fetcher import org.readium.r2.shared.fetcher.buffered import org.readium.r2.shared.publication.Publication -sealed class ExoPlayerDataSourceException(message: String, cause: Throwable?) : IOException(message, cause) { - class NotOpened(message: String) : ExoPlayerDataSourceException(message, null) - class NotFound(message: String) : ExoPlayerDataSourceException(message, null) - class ReadFailed(uri: Uri, offset: Int, readLength: Int, cause: Throwable) : ExoPlayerDataSourceException("Failed to read $readLength bytes of URI $uri at offset $offset.", cause) +public sealed class ExoPlayerDataSourceException(message: String, cause: Throwable?) : IOException(message, cause) { + public class NotOpened(message: String) : ExoPlayerDataSourceException(message, null) + public class NotFound(message: String) : ExoPlayerDataSourceException(message, null) + public class ReadFailed(uri: Uri, offset: Int, readLength: Int, cause: Throwable) : ExoPlayerDataSourceException("Failed to read $readLength bytes of URI $uri at offset $offset.", cause) } /** * An ExoPlayer's [DataSource] which retrieves resources from a [Publication]. */ -class ExoPlayerDataSource internal constructor(private val publication: Publication) : BaseDataSource(/* isNetwork = */ true) { +public class ExoPlayerDataSource internal constructor(private val publication: Publication) : BaseDataSource(/* isNetwork = */ true) { - class Factory( + public class Factory( private val publication: Publication, private val transferListener: TransferListener? = null ) : DataSource.Factory { diff --git a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaMetadataFactory.kt b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaMetadataFactory.kt index 02ba2b3ce3..3f64013d13 100644 --- a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaMetadataFactory.kt +++ b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaMetadataFactory.kt @@ -8,15 +8,15 @@ import androidx.media2.common.MediaMetadata * The metadata are used for example in the media-style Android notification. */ @ExperimentalMedia2 -interface MediaMetadataFactory { +public interface MediaMetadataFactory { /** * Creates the [MediaMetadata] for the whole publication. */ - suspend fun publicationMetadata(): MediaMetadata + public suspend fun publicationMetadata(): MediaMetadata /** * Creates the [MediaMetadata] for the reading order resource at the given [index]. */ - suspend fun resourceMetadata(index: Int): MediaMetadata + public suspend fun resourceMetadata(index: Int): MediaMetadata } diff --git a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt index 017b4f6b04..24c00d9996 100644 --- a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt +++ b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/MediaNavigator.kt @@ -52,7 +52,7 @@ import timber.log.Timber */ @ExperimentalMedia2 @OptIn(ExperimentalTime::class) -class MediaNavigator private constructor( +public class MediaNavigator private constructor( override val publication: Publication, private val playerFacade: SessionPlayerFacade, private val playerCallback: SessionPlayerCallback, @@ -200,7 +200,7 @@ class MediaNavigator private constructor( /** * Indicates the navigator current state. */ - val playback: StateFlow = + public val playback: StateFlow = playbackMutable /** @@ -208,35 +208,35 @@ class MediaNavigator private constructor( * * Normal speed is 1.0 and 0.0 is incorrect. */ - suspend fun setPlaybackRate(rate: Double): Try = executeCommand { + public suspend fun setPlaybackRate(rate: Double): Try = executeCommand { playerFacade.setPlaybackSpeed(rate).toNavigatorResult() } /** * Resumes or start the playback at the current location. */ - suspend fun play(): Try = executeCommand { + public suspend fun play(): Try = executeCommand { playerFacade.play().toNavigatorResult() } /** * Pauses the playback. */ - suspend fun pause(): Try = executeCommand { + public suspend fun pause(): Try = executeCommand { playerFacade.pause().toNavigatorResult() } /** * Seeks to the given time at the given resource. */ - suspend fun seek(index: Int, position: Duration): Try = executeCommand { + public suspend fun seek(index: Int, position: Duration): Try = executeCommand { playerFacade.seekTo(index, position).toNavigatorResult() } /** * Seeks to the given locator. */ - suspend fun go(locator: Locator): Try { + public suspend fun go(locator: Locator): Try { val itemIndex = publication.readingOrder.indexOfFirstWithHref(locator.href) ?: return Try.failure(Exception.InvalidArgument("Invalid href ${locator.href}.")) val position = locator.locations.time ?: Duration.ZERO @@ -247,7 +247,7 @@ class MediaNavigator private constructor( /** * Seeks to the beginning of the given link. */ - suspend fun go(link: Link): Try { + public suspend fun go(link: Link): Try { val locator = publication.locatorFromLink(link) ?: return Try.failure(Exception.InvalidArgument("Resource not found at ${link.href}")) return go(locator) @@ -256,13 +256,13 @@ class MediaNavigator private constructor( /** * Skips to a little amount of time later. */ - suspend fun goForward(): Try = + public suspend fun goForward(): Try = seekBy(configuration.skipForwardInterval) /** * Skips to a little amount of time before. */ - suspend fun goBackward(): Try = + public suspend fun goBackward(): Try = seekBy(-configuration.skipBackwardInterval) private suspend fun seekBy(offset: Duration): Try = executeCommand { @@ -298,7 +298,7 @@ class MediaNavigator private constructor( * Compared to [pause], the navigator may clear its state in whatever way is appropriate. For * example, recovering a player's resources. */ - fun close() { + public fun close() { playerFacade.unregisterPlayerCallback(playerCallback) playerCallback.close() playerFacade.close() @@ -308,50 +308,50 @@ class MediaNavigator private constructor( /** * Builds a [MediaSession] for this navigator. */ - fun session(context: Context, activityIntent: PendingIntent, id: String? = null): MediaSession = + public fun session(context: Context, activityIntent: PendingIntent, id: String? = null): MediaSession = playerFacade.session(context, id, activityIntent) - data class Configuration( + public data class Configuration( val positionRefreshRate: Double = 2.0, // Hz val skipForwardInterval: Duration = 30.seconds, val skipBackwardInterval: Duration = 30.seconds, ) @ExperimentalTime - data class Playback( + public data class Playback( val state: State, val rate: Double, val resource: Resource, val buffer: Buffer ) { - enum class State { + public enum class State { Playing, Paused, Finished, Error } - data class Resource( + public data class Resource( val index: Int, val link: Link, val position: Duration, val duration: Duration? ) - data class Buffer( + public data class Buffer( val isPlayable: Boolean, val position: Duration ) } - sealed class Exception(override val message: String) : kotlin.Exception(message) { + public sealed class Exception(override val message: String) : kotlin.Exception(message) { - class SessionPlayer internal constructor( + public class SessionPlayer internal constructor( internal val error: SessionPlayerError ) : Exception("${error.name} error occurred in SessionPlayer.") - class InvalidArgument(message: String) : Exception(message) + public class InvalidArgument(message: String) : Exception(message) } /* @@ -381,9 +381,9 @@ class MediaNavigator private constructor( return true } - companion object { + public companion object { - suspend fun create( + public suspend fun create( context: Context, publication: Publication, initialLocator: Locator?, diff --git a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/OptIn.kt b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/OptIn.kt index d67319d39d..a7a8d423e5 100644 --- a/readium/navigator-media2/src/main/java/org/readium/navigator/media2/OptIn.kt +++ b/readium/navigator-media2/src/main/java/org/readium/navigator/media2/OptIn.kt @@ -14,4 +14,4 @@ package org.readium.navigator.media2 ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class ExperimentalMedia2 +public annotation class ExperimentalMedia2 diff --git a/readium/navigator/build.gradle.kts b/readium/navigator/build.gradle.kts index d6a3aade20..d845d4ace5 100644 --- a/readium/navigator/build.gradle.kts +++ b/readium/navigator/build.gradle.kts @@ -47,6 +47,10 @@ android { namespace = "org.readium.r2.navigator" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-navigator" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/DecorableNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/DecorableNavigator.kt index 4798609188..4cdfe7f5d9 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/DecorableNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/DecorableNavigator.kt @@ -26,7 +26,7 @@ import org.readium.r2.shared.publication.Locator * A navigator able to render arbitrary decorations over a publication. */ @ExperimentalDecorator -interface DecorableNavigator : Navigator { +public interface DecorableNavigator : Navigator { /** * Declares the current state of the decorations in the given decoration [group]. * @@ -35,7 +35,7 @@ interface DecorableNavigator : Navigator { * Name each decoration group as you see fit. A good practice is to use the name of the feature * requiring decorations, e.g. annotation, search, tts, etc. */ - suspend fun applyDecorations(decorations: List, group: String) + public suspend fun applyDecorations(decorations: List, group: String) /** * Indicates whether the Navigator supports the given decoration [style] class. @@ -44,19 +44,19 @@ interface DecorableNavigator : Navigator { * particular feature before enabling it. For example, underlining an audiobook does not make * sense, so an Audiobook Navigator would not support the `underline` decoration style. */ - fun supportsDecorationStyle(style: KClass): Boolean + public fun supportsDecorationStyle(style: KClass): Boolean /** * Registers a new [listener] for decoration interactions in the given [group]. */ - fun addDecorationListener(group: String, listener: Listener) + public fun addDecorationListener(group: String, listener: Listener) /** * Removes the given [listener] for all decoration interactions. */ - fun removeDecorationListener(listener: Listener) + public fun removeDecorationListener(listener: Listener) - interface Listener { + public interface Listener { /** * Called when the user activates a decoration, e.g. with a click or tap. @@ -64,7 +64,7 @@ interface DecorableNavigator : Navigator { * @param event Holds the metadata about the interaction event. * @return Whether the listener handled the interaction. */ - fun onDecorationActivated(event: OnActivatedEvent): Boolean + public fun onDecorationActivated(event: OnActivatedEvent): Boolean } /** @@ -77,7 +77,7 @@ interface DecorableNavigator : Navigator { * @param point Event point of the interaction, in the coordinate of the navigator view. This is * only useful in the context of a VisualNavigator. */ - data class OnActivatedEvent( + public data class OnActivatedEvent( val decoration: Decoration, val group: String, val rect: RectF? = null, @@ -98,7 +98,7 @@ interface DecorableNavigator : Navigator { */ @Parcelize @ExperimentalDecorator -data class Decoration( +public data class Decoration( val id: DecorationId, val locator: Locator, val style: Style, @@ -112,30 +112,30 @@ data class Decoration( * It is media type agnostic, meaning that each Navigator will translate the style into a set of * rendering instructions which makes sense for the resource type. */ - interface Style : Parcelable { + public interface Style : Parcelable { @Parcelize - data class Highlight( + public data class Highlight( @ColorInt override val tint: Int, override val isActive: Boolean = false ) : Style, Tinted, Activable @Parcelize - data class Underline( + public data class Underline( @ColorInt override val tint: Int, override val isActive: Boolean = false ) : Style, Tinted, Activable /** A type of [Style] which has a tint color. */ - interface Tinted { - @get:ColorInt val tint: Int + public interface Tinted { + @get:ColorInt public val tint: Int } /** A type of [Style] which can be in an "active" state. */ - interface Activable { - val isActive: Boolean + public interface Activable { + public val isActive: Boolean } } - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("id", id) put("locator", locator.toJSON()) putOpt("style", style::class.qualifiedName) @@ -144,15 +144,15 @@ data class Decoration( /** Unique identifier for a decoration. */ @ExperimentalDecorator -typealias DecorationId = String +public typealias DecorationId = String /** Represents an atomic change in a list of [Decoration] objects. */ @ExperimentalDecorator -sealed class DecorationChange { - data class Added(val decoration: Decoration) : DecorationChange() - data class Updated(val decoration: Decoration) : DecorationChange() - data class Moved(val id: DecorationId, val fromPosition: Int, val toPosition: Int) : DecorationChange() - data class Removed(val id: DecorationId) : DecorationChange() +public sealed class DecorationChange { + public data class Added(val decoration: Decoration) : DecorationChange() + public data class Updated(val decoration: Decoration) : DecorationChange() + public data class Moved(val id: DecorationId, val fromPosition: Int, val toPosition: Int) : DecorationChange() + public data class Removed(val id: DecorationId) : DecorationChange() } /** @@ -161,7 +161,7 @@ sealed class DecorationChange { * The changes need to be applied in the same order, one by one. */ @ExperimentalDecorator -suspend fun List.changesByHref(target: List): Map> = withContext(Dispatchers.Default) { +public suspend fun List.changesByHref(target: List): Map> = withContext(Dispatchers.Default) { val source = this@changesByHref val result = DiffUtil.calculateDiff(object : DiffUtil.Callback() { override fun getOldListSize(): Int = source.size diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/Deprecated.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/Deprecated.kt index 2b2b39551e..9ee9949758 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/Deprecated.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/Deprecated.kt @@ -9,39 +9,8 @@ package org.readium.r2.navigator -import android.content.SharedPreferences -import android.view.View -import org.readium.r2.navigator.pager.R2ViewPager -import org.readium.r2.shared.publication.Publication - @Deprecated("Use navigator fragments.", level = DeprecationLevel.ERROR) -interface IR2Activity { - - val publication: Publication - val preferences: SharedPreferences - val publicationIdentifier: String - val publicationFileName: String - val publicationPath: String - val bookId: Long - val resourcePager: R2ViewPager? - get() = null - val allowToggleActionBar: Boolean - get() = true - - fun toggleActionBar() {} - fun toggleActionBar(v: View? = null) {} - fun nextResource(v: View? = null) {} - fun previousResource(v: View? = null) {} - fun onPageChanged(pageIndex: Int, totalPages: Int, url: String) {} - fun onPageEnded(end: Boolean) {} - fun onPageLoaded() {} - fun highlightActivated(id: String) {} - fun highlightAnnotationMarkActivated(id: String) {} -} +public interface IR2Activity @Deprecated("Use TtsNavigator.", level = DeprecationLevel.ERROR) -interface IR2TTS { - fun playTextChanged(text: String) {} - fun playStateChanged(playing: Boolean) {} - fun dismissScreenReader() {} -} +public interface IR2TTS diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/GlobalVars.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/GlobalVars.kt index 875e3791ae..97207f501c 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/GlobalVars.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/GlobalVars.kt @@ -16,5 +16,5 @@ package org.readium.r2.navigator /** * Global Parameters */ -@Deprecated("Use Publication::localBaseUrlOf() instead") -const val BASE_URL = "http://127.0.0.1" +@Deprecated("Use Publication::localBaseUrlOf() instead", level = DeprecationLevel.ERROR) +public const val BASE_URL: String = "http://127.0.0.1" diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/Navigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/Navigator.kt index 5f482b273e..c3cc78c5e9 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/Navigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/Navigator.kt @@ -9,7 +9,6 @@ package org.readium.r2.navigator import android.graphics.PointF import android.view.View import kotlin.time.Duration -import kotlin.time.ExperimentalTime import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import org.readium.r2.navigator.input.InputListener @@ -42,40 +41,40 @@ import org.readium.r2.shared.publication.ReadingProgression as PublicationReadin * interactions such as tapping/clicking the edge of the page to skip to the next one should be * implemented by the reading app, and not the navigator. */ -interface Navigator { +public interface Navigator { /** * Publication rendered by this navigator. */ - val publication: Publication + public val publication: Publication /** * Current position in the publication. * Can be used to save a bookmark to the current position. */ - val currentLocator: StateFlow + public val currentLocator: StateFlow /** * Moves to the position in the publication corresponding to the given [Locator]. */ - fun go(locator: Locator, animated: Boolean = false, completion: () -> Unit = {}): Boolean + public fun go(locator: Locator, animated: Boolean = false, completion: () -> Unit = {}): Boolean /** * Moves to the position in the publication targeted by the given link. */ - fun go(link: Link, animated: Boolean = false, completion: () -> Unit = {}): Boolean + public fun go(link: Link, animated: Boolean = false, completion: () -> Unit = {}): Boolean /** * Moves to the next content portion (eg. page) in the reading progression direction. */ - fun goForward(animated: Boolean = false, completion: () -> Unit = {}): Boolean + public fun goForward(animated: Boolean = false, completion: () -> Unit = {}): Boolean /** * Moves to the previous content portion (eg. page) in the reading progression direction. */ - fun goBackward(animated: Boolean = false, completion: () -> Unit = {}): Boolean + public fun goBackward(animated: Boolean = false, completion: () -> Unit = {}): Boolean - interface Listener { + public interface Listener { /** * Called when the navigator jumps to an explicit location, which might break the linear @@ -87,59 +86,59 @@ interface Navigator { * You can use this callback to implement a navigation history by differentiating between * continuous and discontinuous moves. */ - fun onJumpToLocator(locator: Locator) {} + public fun onJumpToLocator(locator: Locator) {} } - @Deprecated("Use [currentLocator.value] instead", ReplaceWith("currentLocator.value")) - val currentLocation: Locator? get() = currentLocator.value - @Deprecated("Use [VisualNavigator.Listener] instead", ReplaceWith("VisualNavigator.Listener")) - interface VisualListener : VisualNavigator.Listener + @Deprecated("Use [currentLocator.value] instead", ReplaceWith("currentLocator.value"), level = DeprecationLevel.ERROR) + public val currentLocation: Locator? get() = currentLocator.value + @Deprecated("Use [VisualNavigator.Listener] instead", ReplaceWith("VisualNavigator.Listener"), level = DeprecationLevel.ERROR) + public interface VisualListener : VisualNavigator.Listener } -interface NavigatorDelegate { - @Deprecated("Observe [currentLocator] instead") - fun locationDidChange(navigator: Navigator? = null, locator: Locator) {} +public interface NavigatorDelegate { + @Deprecated("Observe [currentLocator] instead", level = DeprecationLevel.ERROR) + public fun locationDidChange(navigator: Navigator? = null, locator: Locator) {} } /** * A navigator rendering the publication visually on-screen. */ -interface VisualNavigator : Navigator { +public interface VisualNavigator : Navigator { /** * View displaying the publication. */ - val publicationView: View + public val publicationView: View /** * Current presentation rendered by the navigator. */ @ExperimentalReadiumApi - val presentation: StateFlow + public val presentation: StateFlow @ExperimentalReadiumApi - interface Presentation { + public interface Presentation { /** * Horizontal direction of progression across resources. */ - val readingProgression: ReadingProgression + public val readingProgression: ReadingProgression /** * If the overflow of the content is managed through scroll instead of pagination. */ - val scroll: Boolean + public val scroll: Boolean /** * Main axis along which the resources are laid out. */ - val axis: Axis + public val axis: Axis } /** * Returns the [Locator] to the first content element that begins on the current screen. */ @ExperimentalReadiumApi - suspend fun firstVisibleElementLocator(): Locator? = + public suspend fun firstVisibleElementLocator(): Locator? = currentLocator.value /** @@ -149,37 +148,37 @@ interface VisualNavigator : Navigator { * receiving them. */ @ExperimentalReadiumApi - fun addInputListener(listener: InputListener) + public fun addInputListener(listener: InputListener) /** * Removes a previously registered [InputListener]. */ @ExperimentalReadiumApi - fun removeInputListener(listener: InputListener) + public fun removeInputListener(listener: InputListener) - interface Listener : Navigator.Listener { + public interface Listener : Navigator.Listener { @Deprecated("Use `addInputListener` instead", level = DeprecationLevel.ERROR) - fun onTap(point: PointF): Boolean = false + public fun onTap(point: PointF): Boolean = false @Deprecated("Use `addInputListener` instead", level = DeprecationLevel.ERROR) - fun onDragStart(startPoint: PointF, offset: PointF): Boolean = false + public fun onDragStart(startPoint: PointF, offset: PointF): Boolean = false @Deprecated("Use `addInputListener` instead", level = DeprecationLevel.ERROR) - fun onDragMove(startPoint: PointF, offset: PointF): Boolean = false + public fun onDragMove(startPoint: PointF, offset: PointF): Boolean = false @Deprecated("Use `addInputListener` instead", level = DeprecationLevel.ERROR) - fun onDragEnd(startPoint: PointF, offset: PointF): Boolean = false + public fun onDragEnd(startPoint: PointF, offset: PointF): Boolean = false } /** * Current reading progression direction. */ @Deprecated("Use `presentation.value.readingProgression` instead", ReplaceWith("presentation.value.readingProgression"), level = DeprecationLevel.ERROR) - val readingProgression: PublicationReadingProgression + public val readingProgression: PublicationReadingProgression } /** * Moves to the left content portion (eg. page) relative to the reading progression direction. */ @OptIn(ExperimentalReadiumApi::class) -fun VisualNavigator.goLeft(animated: Boolean = false, completion: () -> Unit = {}): Boolean { +public fun VisualNavigator.goLeft(animated: Boolean = false, completion: () -> Unit = {}): Boolean { return when (presentation.value.readingProgression) { ReadingProgression.LTR -> goBackward(animated = animated, completion = completion) @@ -193,7 +192,7 @@ fun VisualNavigator.goLeft(animated: Boolean = false, completion: () -> Unit = { * Moves to the right content portion (eg. page) relative to the reading progression direction. */ @OptIn(ExperimentalReadiumApi::class) -fun VisualNavigator.goRight(animated: Boolean = false, completion: () -> Unit = {}): Boolean { +public fun VisualNavigator.goRight(animated: Boolean = false, completion: () -> Unit = {}): Boolean { return when (presentation.value.readingProgression) { ReadingProgression.LTR -> goForward(animated = animated, completion = completion) @@ -206,42 +205,41 @@ fun VisualNavigator.goRight(animated: Boolean = false, completion: () -> Unit = /** * A navigator rendering an audio or video publication. */ -@OptIn(ExperimentalTime::class) @ExperimentalAudiobook -interface MediaNavigator : Navigator { +public interface MediaNavigator : Navigator { /** * Current playback information. */ - val playback: Flow + public val playback: Flow /** * Indicates whether the navigator is currently playing. */ - val isPlaying: Boolean + public val isPlaying: Boolean /** * Sets the speed of the media playback. * * Normal speed is 1.0 and 0.0 is incorrect. */ - fun setPlaybackRate(rate: Double) + public fun setPlaybackRate(rate: Double) /** * Resumes or start the playback at the current location. */ - fun play() + public fun play() /** * Pauses the playback. */ - fun pause() + public fun pause() /** * Toggles the playback. * Can be useful as a handler for play/pause button. */ - fun playPause() + public fun playPause() /** * Stops the playback. @@ -249,17 +247,17 @@ interface MediaNavigator : Navigator { * Compared to [pause], the navigator may clear its state in whatever way is appropriate. For * example, recovering a player's resources. */ - fun stop() + public fun stop() /** * Seeks to the given time in the current resource. */ - fun seekTo(position: Duration) + public fun seekTo(position: Duration) /** * Seeks relatively from the current position in the current resource. */ - fun seekRelative(offset: Duration) + public fun seekRelative(offset: Duration) - interface Listener : Navigator.Listener + public interface Listener : Navigator.Listener } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/OptIn.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/OptIn.kt index 38702fa7de..8f6a6bcc0d 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/OptIn.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/OptIn.kt @@ -12,7 +12,7 @@ package org.readium.r2.navigator ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class ExperimentalDecorator +public annotation class ExperimentalDecorator @RequiresOptIn( level = RequiresOptIn.Level.WARNING, @@ -20,7 +20,7 @@ annotation class ExperimentalDecorator ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class ExperimentalAudiobook +public annotation class ExperimentalAudiobook @RequiresOptIn( level = RequiresOptIn.Level.WARNING, @@ -28,4 +28,4 @@ annotation class ExperimentalAudiobook ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class ExperimentalDragGesture +public annotation class ExperimentalDragGesture diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/R2BasicWebView.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/R2BasicWebView.kt index 42bc4b07d4..f34da5d47b 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/R2BasicWebView.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/R2BasicWebView.kt @@ -54,7 +54,7 @@ import org.readium.r2.shared.util.use import timber.log.Timber @OptIn(ExperimentalDecorator::class, ExperimentalReadiumApi::class) -open class R2BasicWebView(context: Context, attrs: AttributeSet) : WebView(context, attrs) { +internal open class R2BasicWebView(context: Context, attrs: AttributeSet) : WebView(context, attrs) { interface Listener { val readingProgression: ReadingProgression diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/R2WebView.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/R2WebView.kt index 21936910d3..1e752a50ca 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/R2WebView.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/R2WebView.kt @@ -32,7 +32,7 @@ import timber.log.Timber * Created by Aferdita Muriqi on 12/2/17. */ -class R2WebView(context: Context, attrs: AttributeSet) : R2BasicWebView(context, attrs) { +internal class R2WebView(context: Context, attrs: AttributeSet) : R2BasicWebView(context, attrs) { init { initWebPager() diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/SelectableNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/SelectableNavigator.kt index 4e60a87a8c..7a4de33621 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/SelectableNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/SelectableNavigator.kt @@ -12,13 +12,13 @@ import org.readium.r2.shared.publication.Locator /** * A navigator supporting user selection. */ -interface SelectableNavigator : Navigator { +public interface SelectableNavigator : Navigator { /** Currently selected content. */ - suspend fun currentSelection(): Selection? + public suspend fun currentSelection(): Selection? /** Clears the current selection. */ - fun clearSelection() + public fun clearSelection() } /** @@ -28,7 +28,7 @@ interface SelectableNavigator : Navigator { * @param rect Frame of the bounding rect for the selection, in the coordinate of the navigator * view. This is only useful in the context of a VisualNavigator. */ -data class Selection( +public data class Selection( val locator: Locator, val rect: RectF?, ) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/SimplePresentation.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/SimplePresentation.kt index c9b217eefc..2ed0701376 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/SimplePresentation.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/SimplePresentation.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.InternalReadiumApi @InternalReadiumApi @OptIn(ExperimentalReadiumApi::class) -data class SimplePresentation( +public data class SimplePresentation( override val readingProgression: ReadingProgression, override val scroll: Boolean, override val axis: Axis, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/audiobook/Deprecated.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/audiobook/Deprecated.kt index bc807c3806..bdd68570f0 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/audiobook/Deprecated.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/audiobook/Deprecated.kt @@ -4,10 +4,10 @@ import android.media.MediaPlayer import org.readium.r2.shared.publication.Link @Deprecated("Build your own UI upon AudiobookNavigator instead.", level = DeprecationLevel.ERROR) -open class R2AudiobookActivity +public open class R2AudiobookActivity @Deprecated("Use the new MediaNavigator API.", level = DeprecationLevel.ERROR) -class R2MediaPlayer(private var items: List) : +public class R2MediaPlayer(private var items: List) : MediaPlayer.OnPreparedListener { override fun onPrepared(mp: MediaPlayer?) { @@ -15,7 +15,7 @@ class R2MediaPlayer(private var items: List) : } @Deprecated("Use the new MediaNavigator API.", level = DeprecationLevel.ERROR) -interface MediaPlayerCallback { - fun onPrepared() - fun onComplete(index: Int, currentPosition: Int, duration: Int) +public interface MediaPlayerCallback { + public fun onPrepared() + public fun onComplete(index: Int, currentPosition: Int, duration: Int) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/cbz/Deprecated.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/cbz/Deprecated.kt index 7d963b4eb2..d211019076 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/cbz/Deprecated.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/cbz/Deprecated.kt @@ -10,7 +10,7 @@ package org.readium.r2.navigator.cbz @Deprecated("Use ImageNavigatorFragment in your own activity instead.", level = DeprecationLevel.ERROR) -open class R2CbzActivity +public open class R2CbzActivity // This is for lint to pass. private val fake = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/divina/Deprecated.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/divina/Deprecated.kt index b322ff5208..7e29966515 100755 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/divina/Deprecated.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/divina/Deprecated.kt @@ -13,7 +13,7 @@ package org.readium.r2.navigator.divina "Use ImageNavigatorFragment in your own activity to get a basic support for DiViNa.", level = DeprecationLevel.ERROR ) -open class R2DiViNaActivity +public open class R2DiViNaActivity // This is for lint to pass. private val fake = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/Deprecated.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/Deprecated.kt index 2809060147..85772e8a3e 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/Deprecated.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/Deprecated.kt @@ -9,22 +9,22 @@ package org.readium.r2.navigator.epub import org.readium.r2.shared.publication.Locator @Deprecated("Use EpubNavigatorFragment in your own activity instead.", level = DeprecationLevel.ERROR) -open class R2EpubActivity +public open class R2EpubActivity @Deprecated("Use Decorator API instead.", level = DeprecationLevel.ERROR) -interface IR2Highlightable +public interface IR2Highlightable @Deprecated("Use Decorator API instead.", level = DeprecationLevel.ERROR) -data class Highlight( +public data class Highlight( val id: String ) @Deprecated("Use Decorator API instead.", level = DeprecationLevel.ERROR) -enum class Style { +public enum class Style { highlight, underline, strikethrough } @Deprecated("Use navigator fragments.", level = DeprecationLevel.ERROR) -interface IR2Selectable { - fun currentSelection(callback: (Locator?) -> Unit) +public interface IR2Selectable { + public fun currentSelection(callback: (Locator?) -> Unit) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubDefaults.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubDefaults.kt index f0d2a62206..705e4a67d2 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubDefaults.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubDefaults.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.util.Language * @see EpubPreferences */ @ExperimentalReadiumApi -data class EpubDefaults( +public data class EpubDefaults( val columnCount: ColumnCount? = null, val fontSize: Double? = null, val fontWeight: Double? = null, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFactory.kt index 53b0021676..56f0437459 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFactory.kt @@ -21,7 +21,7 @@ import org.readium.r2.shared.publication.presentation.presentation * @param configuration Configuration of the factory to create. */ @ExperimentalReadiumApi -class EpubNavigatorFactory( +public class EpubNavigatorFactory( private val publication: Publication, private val configuration: Configuration = Configuration() ) { @@ -31,7 +31,7 @@ class EpubNavigatorFactory( * * @param defaults navigator fallbacks for some preferences */ - data class Configuration( + public data class Configuration( val defaults: EpubDefaults = EpubDefaults(), ) @@ -39,7 +39,7 @@ class EpubNavigatorFactory( publication.metadata.presentation.layout ?: EpubLayout.REFLOWABLE @OptIn(ExperimentalDecorator::class) - fun createFragmentFactory( + public fun createFragmentFactory( initialLocator: Locator?, initialPreferences: EpubPreferences = EpubPreferences(), listener: EpubNavigatorFragment.Listener? = null, @@ -58,7 +58,7 @@ class EpubNavigatorFactory( ) } - fun createPreferencesEditor( + public fun createPreferencesEditor( currentPreferences: EpubPreferences, ): EpubPreferencesEditor = EpubPreferencesEditor( diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt index 83bd34d315..dd2c9bea76 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt @@ -84,7 +84,7 @@ import org.readium.r2.shared.util.mediatype.MediaType * * Return `null` if you don't want to inject the interface for the given resource. */ -typealias JavascriptInterfaceFactory = (resource: Link) -> Any? +public typealias JavascriptInterfaceFactory = (resource: Link) -> Any? /** * Navigator for EPUB publications. @@ -92,7 +92,7 @@ typealias JavascriptInterfaceFactory = (resource: Link) -> Any? * To use this [Fragment], create a factory with `EpubNavigatorFragment.createFactory()`. */ @OptIn(ExperimentalDecorator::class, ExperimentalReadiumApi::class, DelicateReadiumApi::class) -class EpubNavigatorFragment internal constructor( +public class EpubNavigatorFragment internal constructor( override val publication: Publication, private val initialLocator: Locator?, private val initialPreferences: EpubPreferences, @@ -114,7 +114,7 @@ class EpubNavigatorFragment internal constructor( } } - data class Configuration internal constructor( + public data class Configuration internal constructor( /** * Patterns for asset paths which will be available to EPUB resources under @@ -183,7 +183,7 @@ class EpubNavigatorFragment internal constructor( internal var fontFamilyDeclarations: List, internal var javascriptInterfaces: Map ) { - constructor( + public constructor( servedAssets: List = emptyList(), readiumCssRsProperties: RsProperties = RsProperties(), decorationTemplates: HtmlDecorationTemplates = HtmlDecorationTemplates.defaultTemplates(), @@ -206,7 +206,7 @@ class EpubNavigatorFragment internal constructor( * Return `null` in [factory] to prevent adding the Javascript interface for a given * resource. */ - fun registerJavascriptInterface(name: String, factory: JavascriptInterfaceFactory) { + public fun registerJavascriptInterface(name: String, factory: JavascriptInterfaceFactory) { javascriptInterfaces += name to factory } @@ -217,7 +217,7 @@ class EpubNavigatorFragment internal constructor( * symbols are missing from [fontFamily]. */ @ExperimentalReadiumApi - fun addFontFamilyDeclaration( + public fun addFontFamilyDeclaration( fontFamily: FontFamily, alternates: List = emptyList(), builderAction: (MutableFontFamilyDeclaration).() -> Unit @@ -229,18 +229,18 @@ class EpubNavigatorFragment internal constructor( ) } - companion object { - operator fun invoke(builder: Configuration.() -> Unit): Configuration = + public companion object { + public operator fun invoke(builder: Configuration.() -> Unit): Configuration = Configuration().apply(builder) } } - interface PaginationListener { - fun onPageChanged(pageIndex: Int, totalPages: Int, locator: Locator) {} - fun onPageLoaded() {} + public interface PaginationListener { + public fun onPageChanged(pageIndex: Int, totalPages: Int, locator: Locator) {} + public fun onPageLoaded() {} } - interface Listener : VisualNavigator.Listener + public interface Listener : VisualNavigator.Listener init { require(!publication.isRestricted) { "The provided publication is restricted. Check that any DRM was properly unlocked using a Content Protection." } @@ -259,7 +259,7 @@ class EpubNavigatorFragment internal constructor( * * Note that this only work with reflowable resources. */ - suspend fun evaluateJavascript(script: String): String? { + public suspend fun evaluateJavascript(script: String): String? { val page = currentReflowablePageFragment ?: return null page.awaitLoaded() val webView = page.webView ?: return null @@ -278,22 +278,21 @@ class EpubNavigatorFragment internal constructor( internal lateinit var positionsByReadingOrder: List> internal lateinit var positions: List - lateinit var resourcePager: R2ViewPager + + internal lateinit var resourcePager: R2ViewPager private lateinit var resourcesSingle: List private lateinit var resourcesDouble: List @Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) - val preferences: SharedPreferences get() = throw NotImplementedError() + public val preferences: SharedPreferences get() = throw NotImplementedError() - internal lateinit var publicationIdentifier: String + private lateinit var publicationIdentifier: String internal var currentPagerPosition: Int = 0 internal lateinit var adapter: R2PagerAdapter private lateinit var currentActivity: FragmentActivity - internal var navigatorDelegate: NavigatorDelegate? = null - private var _binding: ReadiumNavigatorViewpagerBinding? = null private val binding get() = _binding!! @@ -976,7 +975,6 @@ class EpubNavigatorFragment internal constructor( // Make sure viewLifecycleOwner is accessible. view ?: return - val navigator = this debounceLocationNotificationJob?.cancel() debounceLocationNotificationJob = viewLifecycleOwner.lifecycleScope.launch { delay(100L) @@ -1016,8 +1014,6 @@ class EpubNavigatorFragment internal constructor( _currentLocator.value = currentLocator // Deprecated notifications - @Suppress("DEPRECATION") - navigatorDelegate?.locationDidChange(navigator = navigator, locator = currentLocator) reflowableWebView?.let { paginationListener?.onPageChanged( pageIndex = it.mCurItem, @@ -1028,7 +1024,7 @@ class EpubNavigatorFragment internal constructor( } } - companion object { + public companion object { /** * Creates a factory for [EpubNavigatorFragment]. @@ -1042,7 +1038,7 @@ class EpubNavigatorFragment internal constructor( * @param config Additional configuration. */ @Deprecated("Use `EpubNavigatorFactory().createFragmentFactory()` instead", level = DeprecationLevel.ERROR) - fun createFactory( + public fun createFactory( publication: Publication, baseUrl: String? = null, initialLocator: Locator? = null, @@ -1055,7 +1051,7 @@ class EpubNavigatorFragment internal constructor( /** * Returns a URL to the application asset at [path], served in the web views. */ - fun assetUrl(path: String): String = + public fun assetUrl(path: String): String = WebViewServer.assetUrl(path) } } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferences.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferences.kt index cb739ae57f..32f0472bc4 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferences.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferences.kt @@ -49,7 +49,7 @@ import org.readium.r2.shared.util.Language */ @ExperimentalReadiumApi @Serializable -data class EpubPreferences( +public data class EpubPreferences( val backgroundColor: Color? = null, val columnCount: ColumnCount? = null, val fontFamily: FontFamily? = null, @@ -116,120 +116,123 @@ data class EpubPreferences( verticalText = other.verticalText ?: verticalText, wordSpacing = other.wordSpacing ?: wordSpacing ) -} - -/** - * Loads the preferences from the legacy EPUB settings stored in the [SharedPreferences] with - * given [sharedPreferencesName]. - * - * This can be used to migrate the legacy settings to the new [EpubPreferences] format. - * - * If you changed the `fontFamilyValues` in the original Test App `UserSettings`, pass it to - * [fontFamilies] to migrate the font family properly. - */ -@ExperimentalReadiumApi -fun EpubPreferences.Companion.fromLegacyEpubSettings( - context: Context, - sharedPreferencesName: String = "org.readium.r2.settings", - fontFamilies: List = listOf( - "Original", "PT Serif", "Roboto", "Source Sans Pro", "Vollkorn", "OpenDyslexic", - "AccessibleDfA", "IA Writer Duospace" - ) -): EpubPreferences { - - val sp: SharedPreferences = - context.getSharedPreferences(sharedPreferencesName, Context.MODE_PRIVATE) - - val fontFamily = sp - .takeIf { it.contains("fontFamily") } - ?.getInt("fontFamily", 0) - ?.let { fontFamilies.getOrNull(it) } - ?.takeUnless { it == "Original" } - ?.let { FontFamily(it) } - - val theme = sp - .takeIf { sp.contains("appearance") } - ?.getInt("appearance", 0) - ?.let { - when (it) { - 0 -> Theme.LIGHT - 1 -> Theme.SEPIA - 2 -> Theme.DARK - else -> null - } - } - - val scroll = sp - .takeIf { sp.contains("scroll") } - ?.getBoolean("scroll", false) - - val colCount = sp - .takeIf { sp.contains("colCount") } - ?.getInt("colCount", 0) - ?.let { - when (it) { - 0 -> ColumnCount.AUTO - 1 -> ColumnCount.ONE - 2 -> ColumnCount.TWO - else -> null - } - } - val pageMargins = sp - .takeIf { sp.contains("pageMargins") } - ?.getFloat("pageMargins", 1.0f) - ?.toDouble() - - val fontSize = sp - .takeIf { sp.contains("fontSize") } - ?.let { sp.getFloat("fontSize", 0f) } - ?.toDouble() - ?.let { it / 100 } - - val textAlign = sp - .takeIf { sp.contains("textAlign") } - ?.getInt("textAlign", 0) - ?.let { - when (it) { - 0 -> TextAlign.JUSTIFY - 1 -> TextAlign.START - else -> null - } + public companion object { + + /** + * Loads the preferences from the legacy EPUB settings stored in the [SharedPreferences] with + * given [sharedPreferencesName]. + * + * This can be used to migrate the legacy settings to the new [EpubPreferences] format. + * + * If you changed the `fontFamilyValues` in the original Test App `UserSettings`, pass it to + * [fontFamilies] to migrate the font family properly. + */ + @ExperimentalReadiumApi + public fun fromLegacyEpubSettings( + context: Context, + sharedPreferencesName: String = "org.readium.r2.settings", + fontFamilies: List = listOf( + "Original", "PT Serif", "Roboto", "Source Sans Pro", "Vollkorn", "OpenDyslexic", + "AccessibleDfA", "IA Writer Duospace" + ) + ): EpubPreferences { + + val sp: SharedPreferences = + context.getSharedPreferences(sharedPreferencesName, Context.MODE_PRIVATE) + + val fontFamily = sp + .takeIf { it.contains("fontFamily") } + ?.getInt("fontFamily", 0) + ?.let { fontFamilies.getOrNull(it) } + ?.takeUnless { it == "Original" } + ?.let { FontFamily(it) } + + val theme = sp + .takeIf { sp.contains("appearance") } + ?.getInt("appearance", 0) + ?.let { + when (it) { + 0 -> Theme.LIGHT + 1 -> Theme.SEPIA + 2 -> Theme.DARK + else -> null + } + } + + val scroll = sp + .takeIf { sp.contains("scroll") } + ?.getBoolean("scroll", false) + + val colCount = sp + .takeIf { sp.contains("colCount") } + ?.getInt("colCount", 0) + ?.let { + when (it) { + 0 -> ColumnCount.AUTO + 1 -> ColumnCount.ONE + 2 -> ColumnCount.TWO + else -> null + } + } + + val pageMargins = sp + .takeIf { sp.contains("pageMargins") } + ?.getFloat("pageMargins", 1.0f) + ?.toDouble() + + val fontSize = sp + .takeIf { sp.contains("fontSize") } + ?.let { sp.getFloat("fontSize", 0f) } + ?.toDouble() + ?.let { it / 100 } + + val textAlign = sp + .takeIf { sp.contains("textAlign") } + ?.getInt("textAlign", 0) + ?.let { + when (it) { + 0 -> TextAlign.JUSTIFY + 1 -> TextAlign.START + else -> null + } + } + + val wordSpacing = sp + .takeIf { sp.contains("wordSpacing") } + ?.getFloat("wordSpacing", 0f) + ?.toDouble() + + val letterSpacing = sp + .takeIf { sp.contains("letterSpacing") } + ?.getFloat("letterSpacing", 0f) + ?.toDouble() + ?.let { it * 2 } + + val lineHeight = sp + .takeIf { sp.contains("lineHeight") } + ?.getFloat("lineHeight", 1.2f) + ?.toDouble() + + // Note that in the legacy preferences storage, "advanced settings" was incorrectly synonym to + // "publisher styles", hence we don't need to flip the value. + val publisherStyles = sp + .takeIf { sp.contains("advancedSettings") } + ?.getBoolean("advancedSettings", false) + + return EpubPreferences( + fontFamily = fontFamily, + theme = theme, + scroll = scroll, + columnCount = colCount, + pageMargins = pageMargins, + fontSize = fontSize, + textAlign = textAlign, + wordSpacing = wordSpacing, + letterSpacing = letterSpacing, + lineHeight = lineHeight, + publisherStyles = publisherStyles + ) } - - val wordSpacing = sp - .takeIf { sp.contains("wordSpacing") } - ?.getFloat("wordSpacing", 0f) - ?.toDouble() - - val letterSpacing = sp - .takeIf { sp.contains("letterSpacing") } - ?.getFloat("letterSpacing", 0f) - ?.toDouble() - ?.let { it * 2 } - - val lineHeight = sp - .takeIf { sp.contains("lineHeight") } - ?.getFloat("lineHeight", 1.2f) - ?.toDouble() - - // Note that in the legacy preferences storage, "advanced settings" was incorrectly synonym to - // "publisher styles", hence we don't need to flip the value. - val publisherStyles = sp - .takeIf { sp.contains("advancedSettings") } - ?.getBoolean("advancedSettings", false) - - return EpubPreferences( - fontFamily = fontFamily, - theme = theme, - scroll = scroll, - columnCount = colCount, - pageMargins = pageMargins, - fontSize = fontSize, - textAlign = textAlign, - wordSpacing = wordSpacing, - letterSpacing = letterSpacing, - lineHeight = lineHeight, - publisherStyles = publisherStyles - ) + } } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesEditor.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesEditor.kt index c3458afba4..53ccc74139 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesEditor.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesEditor.kt @@ -22,10 +22,10 @@ import org.readium.r2.shared.util.Language * or ranges. */ @ExperimentalReadiumApi -class EpubPreferencesEditor internal constructor( +public class EpubPreferencesEditor internal constructor( initialPreferences: EpubPreferences, publicationMetadata: Metadata, - val layout: EpubLayout, + public val layout: EpubLayout, defaults: EpubDefaults ) : PreferencesEditor { @@ -59,7 +59,7 @@ class EpubPreferencesEditor internal constructor( * * When unset, the current [theme] background color is effective. */ - val backgroundColor: Preference = + public val backgroundColor: Preference = PreferenceDelegate( getValue = { preferences.backgroundColor }, getEffectiveValue = { state.settings.backgroundColor ?: Color((theme.value ?: theme.effectiveValue).backgroundColor) }, @@ -74,7 +74,7 @@ class EpubPreferencesEditor internal constructor( * - the publication is reflowable * - [scroll] is off */ - val columnCount: EnumPreference = + public val columnCount: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.columnCount }, getEffectiveValue = { state.settings.columnCount }, @@ -88,7 +88,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val fontFamily: Preference = + public val fontFamily: Preference = PreferenceDelegate( getValue = { preferences.fontFamily }, getEffectiveValue = { state.settings.fontFamily }, @@ -103,7 +103,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val fontSize: RangePreference = + public val fontSize: RangePreference = RangePreferenceDelegate( getValue = { preferences.fontSize }, getEffectiveValue = { state.settings.fontSize }, @@ -122,7 +122,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val fontWeight: RangePreference = + public val fontWeight: RangePreference = RangePreferenceDelegate( getValue = { preferences.fontWeight }, getEffectiveValue = { state.settings.fontWeight ?: 1.0 }, @@ -141,7 +141,7 @@ class EpubPreferencesEditor internal constructor( * - [publisherStyles] is off * - the layout is LTR */ - val hyphens: Preference = + public val hyphens: Preference = PreferenceDelegate( getValue = { preferences.hyphens }, getEffectiveValue = { @@ -159,7 +159,7 @@ class EpubPreferencesEditor internal constructor( * - the publication is reflowable * - the [theme] is set to [Theme.DARK] */ - val imageFilter: EnumPreference = + public val imageFilter: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.imageFilter }, getEffectiveValue = { state.settings.imageFilter }, @@ -173,7 +173,7 @@ class EpubPreferencesEditor internal constructor( * * This has an impact on the resolved layout (e.g. LTR, RTL). */ - val language: Preference = + public val language: Preference = PreferenceDelegate( getValue = { preferences.language }, getEffectiveValue = { state.settings.language }, @@ -189,7 +189,7 @@ class EpubPreferencesEditor internal constructor( * - [publisherStyles] is off * - the layout is LTR */ - val letterSpacing: RangePreference = + public val letterSpacing: RangePreference = RangePreferenceDelegate( getValue = { preferences.letterSpacing }, getEffectiveValue = { state.settings.letterSpacing ?: 0.0 }, @@ -208,7 +208,7 @@ class EpubPreferencesEditor internal constructor( * - [publisherStyles] is off * - the layout is RTL */ - val ligatures: Preference = + public val ligatures: Preference = PreferenceDelegate( getValue = { preferences.ligatures }, getEffectiveValue = { state.settings.ligatures ?: false }, @@ -223,7 +223,7 @@ class EpubPreferencesEditor internal constructor( * - the publication is reflowable * - [publisherStyles] is off */ - val lineHeight: RangePreference = + public val lineHeight: RangePreference = RangePreferenceDelegate( getValue = { preferences.lineHeight }, getEffectiveValue = { state.settings.lineHeight ?: 1.2 }, @@ -239,7 +239,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val pageMargins: RangePreference = + public val pageMargins: RangePreference = RangePreferenceDelegate( getValue = { preferences.pageMargins }, getEffectiveValue = { state.settings.pageMargins }, @@ -258,7 +258,7 @@ class EpubPreferencesEditor internal constructor( * - [publisherStyles] is off * - the layout is LTR or RTL */ - val paragraphIndent: RangePreference = + public val paragraphIndent: RangePreference = RangePreferenceDelegate( getValue = { preferences.paragraphIndent }, getEffectiveValue = { state.settings.paragraphIndent ?: 0.0 }, @@ -276,7 +276,7 @@ class EpubPreferencesEditor internal constructor( * - the publication is reflowable * - [publisherStyles] is off */ - val paragraphSpacing: RangePreference = + public val paragraphSpacing: RangePreference = RangePreferenceDelegate( getValue = { preferences.paragraphSpacing }, getEffectiveValue = { state.settings.paragraphSpacing ?: 0.0 }, @@ -293,7 +293,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val publisherStyles: Preference = + public val publisherStyles: Preference = PreferenceDelegate( getValue = { preferences.publisherStyles }, getEffectiveValue = { state.settings.publisherStyles }, @@ -306,7 +306,7 @@ class EpubPreferencesEditor internal constructor( * * This can be changed to influence directly the layout (e.g. LTR or RTL). */ - val readingProgression: EnumPreference = + public val readingProgression: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.readingProgression }, getEffectiveValue = { state.settings.readingProgression }, @@ -321,7 +321,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val scroll: Preference = + public val scroll: Preference = PreferenceDelegate( getValue = { preferences.scroll }, getEffectiveValue = { state.settings.scroll }, @@ -335,7 +335,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with fixed-layout publications. */ - val spread: EnumPreference = + public val spread: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.spread }, getEffectiveValue = { state.settings.spread }, @@ -352,7 +352,7 @@ class EpubPreferencesEditor internal constructor( * - [publisherStyles] is off * - the layout is LTR or RTL */ - val textAlign: EnumPreference = + public val textAlign: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.textAlign }, getEffectiveValue = { state.settings.textAlign }, @@ -367,7 +367,7 @@ class EpubPreferencesEditor internal constructor( * When unset, the current [theme] text color is effective. * Only effective with reflowable publications. */ - val textColor: Preference = + public val textColor: Preference = PreferenceDelegate( getValue = { preferences.textColor }, getEffectiveValue = { state.settings.textColor ?: Color((theme.value ?: theme.effectiveValue).contentColor) }, @@ -380,7 +380,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val textNormalization: Preference = + public val textNormalization: Preference = PreferenceDelegate( getValue = { preferences.textNormalization }, getEffectiveValue = { state.settings.textNormalization }, @@ -393,7 +393,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val theme: EnumPreference = + public val theme: EnumPreference = EnumPreferenceDelegate( getValue = { preferences.theme }, getEffectiveValue = { state.settings.theme }, @@ -409,7 +409,7 @@ class EpubPreferencesEditor internal constructor( * - the publication is reflowable * - [publisherStyles] is off */ - val typeScale: RangePreference = + public val typeScale: RangePreference = RangePreferenceDelegate( getValue = { preferences.typeScale }, getEffectiveValue = { state.settings.typeScale ?: 1.2 }, @@ -426,7 +426,7 @@ class EpubPreferencesEditor internal constructor( * * Only effective with reflowable publications. */ - val verticalText: Preference = + public val verticalText: Preference = PreferenceDelegate( getValue = { preferences.verticalText }, getEffectiveValue = { state.settings.verticalText }, @@ -441,7 +441,7 @@ class EpubPreferencesEditor internal constructor( * - the publication is reflowable * - the layout is LTR */ - val wordSpacing: RangePreference = + public val wordSpacing: RangePreference = RangePreferenceDelegate( getValue = { preferences.wordSpacing }, getEffectiveValue = { state.settings.wordSpacing ?: 0.0 }, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesFilters.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesFilters.kt index fe07a1b1e2..e97321aad5 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesFilters.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesFilters.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * Suggested filter to keep only shared [EpubPreferences]. */ @ExperimentalReadiumApi -object EpubSharedPreferencesFilter : PreferencesFilter { +public object EpubSharedPreferencesFilter : PreferencesFilter { override fun filter(preferences: EpubPreferences): EpubPreferences = preferences.copy( @@ -28,7 +28,7 @@ object EpubSharedPreferencesFilter : PreferencesFilter { * Suggested filter to keep only publication-specific [EpubPreferences]. */ @ExperimentalReadiumApi -object EpubPublicationPreferencesFilter : PreferencesFilter { +public object EpubPublicationPreferencesFilter : PreferencesFilter { override fun filter(preferences: EpubPreferences): EpubPreferences = EpubPreferences( diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesSerializer.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesSerializer.kt index a4a9fbd406..bd187265fd 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesSerializer.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubPreferencesSerializer.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * JSON serializer of [EpubPreferences]. */ @ExperimentalReadiumApi -class EpubPreferencesSerializer : PreferencesSerializer { +public class EpubPreferencesSerializer : PreferencesSerializer { override fun serialize(preferences: EpubPreferences): String = Json.encodeToString(EpubPreferences.serializer(), preferences) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubSettings.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubSettings.kt index f439ba1071..16ad5848de 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubSettings.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubSettings.kt @@ -36,7 +36,7 @@ import org.readium.r2.shared.util.Language * @see EpubPreferences */ @ExperimentalReadiumApi -data class EpubSettings( +public data class EpubSettings( val backgroundColor: Color?, val columnCount: ColumnCount, val fontFamily: FontFamily?, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/FontFamilyDeclaration.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/FontFamilyDeclaration.kt index f1fb492a07..af9c309a49 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/FontFamilyDeclaration.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/FontFamilyDeclaration.kt @@ -36,16 +36,6 @@ internal data class FontFamilyDeclaration( val fontFaces: List ) -/** - * Build a font face declaration for [fontFamily]. - */ -@ExperimentalReadiumApi -internal fun buildFontFaceDeclaration( - fontFamily: String, - builderAction: (MutableFontFaceDeclaration).() -> Unit -) = - MutableFontFaceDeclaration(fontFamily).apply(builderAction).toFontFaceDeclaration() - /** * An immutable font face declaration. */ @@ -107,13 +97,13 @@ internal data class FontFaceSource( * A mutable font family declaration. */ @ExperimentalReadiumApi -data class MutableFontFamilyDeclaration internal constructor( +public data class MutableFontFamilyDeclaration internal constructor( private val fontFamily: String, private val alternates: List, private val fontFaces: MutableList = mutableListOf() ) { - fun addFontFace(builderAction: MutableFontFaceDeclaration.() -> Unit) { + public fun addFontFace(builderAction: MutableFontFaceDeclaration.() -> Unit) { val fontFace = MutableFontFaceDeclaration(fontFamily).apply(builderAction) fontFaces.add(fontFace.toFontFaceDeclaration()) } @@ -128,7 +118,7 @@ data class MutableFontFamilyDeclaration internal constructor( * A mutable font face declaration. */ @ExperimentalReadiumApi -data class MutableFontFaceDeclaration internal constructor( +public data class MutableFontFaceDeclaration internal constructor( private val fontFamily: String, private val sources: MutableList = mutableListOf(), private var fontStyle: FontStyle? = null, @@ -141,28 +131,28 @@ data class MutableFontFaceDeclaration internal constructor( * @param preload Indicates whether this source will be declared for preloading in the HTML * using ``. */ - fun addSource(href: String, preload: Boolean = false) { + public fun addSource(href: String, preload: Boolean = false) { this.sources.add(FontFaceSource(href = href, preload = preload)) } /** * Set the font style of the font face. */ - fun setFontStyle(fontStyle: FontStyle) { + public fun setFontStyle(fontStyle: FontStyle) { this.fontStyle = fontStyle } /** * Set the font weight of the font face. */ - fun setFontWeight(fontWeight: FontWeight) { + public fun setFontWeight(fontWeight: FontWeight) { this.fontWeight = Either(fontWeight) } /** * Set the font weight range of a variable font face. */ - fun setFontWeight(range: ClosedRange) { + public fun setFontWeight(range: ClosedRange) { require(range.start >= 1) require(range.endInclusive <= 1000) this.fontWeight = Either(range) @@ -176,7 +166,7 @@ data class MutableFontFaceDeclaration internal constructor( * Styles that a font can be styled with. */ @ExperimentalReadiumApi -enum class FontStyle { +public enum class FontStyle { NORMAL, ITALIC; } @@ -187,7 +177,7 @@ enum class FontStyle { * See https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-weight#common_weight_name_mapping */ @ExperimentalReadiumApi -enum class FontWeight(val value: Int) { +public enum class FontWeight(public val value: Int) { THIN(100), EXTRA_LIGHT(200), LIGHT(300), diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/Properties.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/Properties.kt index 304ecac70b..14f94ca163 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/Properties.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/css/Properties.kt @@ -4,6 +4,8 @@ * available in the top-level LICENSE file of the project. */ +@file:OptIn(ExperimentalReadiumApi::class) + package org.readium.r2.navigator.epub.css import androidx.annotation.ColorInt @@ -16,8 +18,8 @@ import org.readium.r2.shared.util.Either * Holds a set of Readium CSS properties applied together. */ @ExperimentalReadiumApi -interface Properties : Cssable { - fun toCssProperties(): Map +public interface Properties : Cssable { + public fun toCssProperties(): Map override fun toCss(): String? { val props = toCssProperties() @@ -88,7 +90,7 @@ interface Properties : Cssable { * subscripts. Requires: fontOverride */ @ExperimentalReadiumApi -data class UserProperties( +public data class UserProperties( // View mode val view: View? = null, @@ -229,7 +231,7 @@ data class UserProperties( * The value can be another variable e.g. var(-RS__monospaceTf). */ @ExperimentalReadiumApi -data class RsProperties( +public data class RsProperties( // Pagination val colWidth: Length? = null, val colCount: ColCount? = null, @@ -345,7 +347,7 @@ data class RsProperties( /** User view. */ @ExperimentalReadiumApi -enum class View(private val css: String) : Cssable { +public enum class View(private val css: String) : Cssable { PAGED("readium-paged-on"), SCROLL("readium-scroll-on"); @@ -354,7 +356,7 @@ enum class View(private val css: String) : Cssable { /** Reading mode. */ @ExperimentalReadiumApi -enum class Appearance(private val css: String?) : Cssable { +public enum class Appearance(private val css: String?) : Cssable { NIGHT("readium-night-on"), SEPIA("readium-sepia-on"); @@ -363,9 +365,9 @@ enum class Appearance(private val css: String?) : Cssable { /** CSS color. */ @ExperimentalReadiumApi -interface Color : Cssable { +public interface Color : Cssable { - data class Rgb(val red: kotlin.Int, val green: kotlin.Int, val blue: kotlin.Int) : Color { + public data class Rgb(val red: kotlin.Int, val green: kotlin.Int, val blue: kotlin.Int) : Color { init { require(red in 0..255) require(green in 0..255) @@ -376,7 +378,7 @@ interface Color : Cssable { } @JvmInline - value class Hex(val color: String) : Color { + public value class Hex(public val color: String) : Color { init { require(Regex("^#(?:[0-9a-fA-F]{3}){1,2}$").matches(color)) } @@ -385,7 +387,7 @@ interface Color : Cssable { } @JvmInline - value class Int(@ColorInt val color: kotlin.Int) : Color { + public value class Int(@ColorInt public val color: kotlin.Int) : Color { override fun toCss(): String = String.format("#%06X", 0xFFFFFF and color) } @@ -393,102 +395,102 @@ interface Color : Cssable { /** CSS length dimension. */ @ExperimentalReadiumApi -interface Length : Cssable { +public interface Length : Cssable { /** Absolute CSS length. */ - interface Absolute : Length + public interface Absolute : Length /** Centimeters */ @JvmInline - value class Cm(val value: Double) : Absolute { + public value class Cm(public val value: Double) : Absolute { override fun toCss(): String = value.toCss("cm") } /** Millimeters */ @JvmInline - value class Mm(val value: Double) : Absolute { + public value class Mm(public val value: Double) : Absolute { override fun toCss(): String = value.toCss("mm") } /** Inches */ @JvmInline - value class In(val value: Double) : Absolute { + public value class In(public val value: Double) : Absolute { override fun toCss(): String = value.toCss("in") } /** Pixels */ @JvmInline - value class Px(val value: Double) : Absolute { + public value class Px(public val value: Double) : Absolute { override fun toCss(): String = value.toCss("px") } /** Points */ @JvmInline - value class Pt(val value: Double) : Absolute { + public value class Pt(public val value: Double) : Absolute { override fun toCss(): String = value.toCss("pt") } /** Picas */ @JvmInline - value class Pc(val value: Double) : Absolute { + public value class Pc(public val value: Double) : Absolute { override fun toCss(): String = value.toCss("pc") } /** Relative CSS length. */ - interface Relative : Length + public interface Relative : Length /** Relative to the font-size of the element. */ @JvmInline - value class Em(val value: Double) : Relative { + public value class Em(public val value: Double) : Relative { override fun toCss(): String = value.toCss("em") } /** Relative to the width of the "0" (zero). */ @JvmInline - value class Ch(val value: Double) : Relative { + public value class Ch(public val value: Double) : Relative { override fun toCss(): String = value.toCss("ch") } /** Relative to font-size of the root element. */ @JvmInline - value class Rem(val value: Double) : Relative { + public value class Rem(public val value: Double) : Relative { override fun toCss(): String = value.toCss("rem") } /** Relative to 1% of the width of the viewport. */ @JvmInline - value class Vw(val value: Double) : Relative { + public value class Vw(public val value: Double) : Relative { override fun toCss(): String = value.toCss("vw") } /** Relative to 1% of the height of the viewport. */ @JvmInline - value class Vh(val value: Double) : Relative { + public value class Vh(public val value: Double) : Relative { override fun toCss(): String = value.toCss("vh") } /** Relative to 1% of viewport's smaller dimension. */ @JvmInline - value class VMin(val value: Double) : Relative { + public value class VMin(public val value: Double) : Relative { override fun toCss(): String = value.toCss("vmin") } /** Relative to 1% of viewport's larger dimension. */ @JvmInline - value class VMax(val value: Double) : Relative { + public value class VMax(public val value: Double) : Relative { override fun toCss(): String = value.toCss("vmax") } /** Relative to the parent element. */ @JvmInline - value class Percent(val value: Double) : Relative { + public value class Percent(public val value: Double) : Relative { override fun toCss(): String = (value * 100).toCss("%") } } /** Number of CSS columns. */ @ExperimentalReadiumApi -enum class ColCount(private val css: String) : Cssable { +public enum class ColCount(private val css: String) : Cssable { AUTO("auto"), ONE("1"), TWO("2"); @@ -498,7 +500,7 @@ enum class ColCount(private val css: String) : Cssable { /** CSS text alignment. */ @ExperimentalReadiumApi -enum class TextAlign(private val css: String) : Cssable { +public enum class TextAlign(private val css: String) : Cssable { START("start"), LEFT("left"), RIGHT("right"), @@ -509,7 +511,7 @@ enum class TextAlign(private val css: String) : Cssable { /** CSS hyphenation. */ @ExperimentalReadiumApi -enum class Hyphens(private val css: String) : Cssable { +public enum class Hyphens(private val css: String) : Cssable { NONE("none"), AUTO("auto"); @@ -518,7 +520,7 @@ enum class Hyphens(private val css: String) : Cssable { /** CSS ligatures. */ @ExperimentalReadiumApi -enum class Ligatures(private val css: String) : Cssable { +public enum class Ligatures(private val css: String) : Cssable { NONE("none"), COMMON("common-ligatures"); @@ -527,7 +529,7 @@ enum class Ligatures(private val css: String) : Cssable { /** CSS box sizing. */ @ExperimentalReadiumApi -enum class BoxSizing(private val css: String) : Cssable { +public enum class BoxSizing(private val css: String) : Cssable { CONTENT_BOX("content-box"), BORDER_BOX("border-box"); @@ -535,8 +537,8 @@ enum class BoxSizing(private val css: String) : Cssable { } @ExperimentalReadiumApi -fun interface Cssable { - fun toCss(): String? +public fun interface Cssable { + public fun toCss(): String? } private fun MutableMap.putCss(name: String, value: Cssable?) { diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLLayout.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLLayout.kt index 48f1ed9c64..bd9e125de5 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLLayout.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLLayout.kt @@ -31,7 +31,7 @@ import kotlin.math.roundToInt import kotlin.math.roundToLong import org.readium.r2.shared.extensions.equalsDelta -class R2FXLLayout : FrameLayout { +internal class R2FXLLayout : FrameLayout { private var scaleDetector: ScaleGestureDetector? = null private var gestureDetector: GestureDetector? = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLOnDoubleTapListener.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLOnDoubleTapListener.kt index 6c033a2bbf..3b091ee2b4 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLOnDoubleTapListener.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLOnDoubleTapListener.kt @@ -9,7 +9,7 @@ package org.readium.r2.navigator.epub.fxl -class R2FXLOnDoubleTapListener(private var threeStep: Boolean) : R2FXLLayout.OnDoubleTapListener { +internal class R2FXLOnDoubleTapListener(private var threeStep: Boolean) : R2FXLLayout.OnDoubleTapListener { override fun onDoubleTap(view: R2FXLLayout, info: R2FXLLayout.TapInfo): Boolean { try { diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLScroller.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLScroller.kt index 333a860c73..18efad2d8a 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLScroller.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLScroller.kt @@ -12,7 +12,7 @@ package org.readium.r2.navigator.epub.fxl import android.content.Context import android.widget.OverScroller -abstract class R2FXLScroller { +internal abstract class R2FXLScroller { abstract val isFinished: Boolean abstract val currX: Int diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLUtils.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLUtils.kt index 8668ee20e0..a6c66ea5f1 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLUtils.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/fxl/R2FXLUtils.kt @@ -14,7 +14,7 @@ import android.graphics.RectF import kotlin.math.roundToInt import kotlin.math.roundToLong -object R2FXLUtils { +internal object R2FXLUtils { /** * Round and set the values on the rectangle diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Extensions.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Extensions.kt index 47591a77dc..233a2f12ee 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Extensions.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Extensions.kt @@ -13,11 +13,11 @@ import androidx.core.view.ViewCompat /** returns true if the resolved layout direction of the content view in this * activity is ViewCompat.LAYOUT_DIRECTION_RTL. Otherwise false. */ -fun Activity.layoutDirectionIsRTL(): Boolean { +internal fun Activity.layoutDirectionIsRTL(): Boolean { return ViewCompat.getLayoutDirection(findViewById(android.R.id.content)) == ViewCompat.LAYOUT_DIRECTION_RTL } @ColorInt -fun Context.color(@ColorRes id: Int): Int { +internal fun Context.color(@ColorRes id: Int): Int { return ContextCompat.getColor(this, id) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/JSON.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/JSON.kt index 6832ea10f3..97d2db0402 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/JSON.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/JSON.kt @@ -12,7 +12,7 @@ import org.json.JSONObject /** * Parses a [RectF] from its JSON representation. */ -fun JSONObject.optRectF(name: String): RectF? = +internal fun JSONObject.optRectF(name: String): RectF? = optJSONObject(name)?.let { json -> val left = json.optDouble("left").toFloat() val top = json.optDouble("top").toFloat() diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Locator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Locator.kt index 38c1d8928f..1dd5e51bf6 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Locator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Locator.kt @@ -12,8 +12,6 @@ package org.readium.r2.navigator.extensions import java.util.* import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.publication.Locator // FIXME: This should be in r2-shared once this public API is specified. @@ -23,8 +21,7 @@ import org.readium.r2.shared.publication.Locator /** * All named parameters found in the fragments, such as `p=5`. */ -@InternalReadiumApi -val Locator.Locations.fragmentParameters: Map get() = +internal val Locator.Locations.fragmentParameters: Map get() = fragments // Concatenates fragments together, after dropping any # .map { it.removePrefix("#") } @@ -68,7 +65,6 @@ internal val Locator.Locations.time: Duration? get() = /** * Computes the time position from the resource duration. */ -@OptIn(ExperimentalTime::class) internal fun Locator.Locations.timeWithDuration(duration: Duration?): Duration? = - let(duration, progression) { d, p -> (p * d.inSeconds).seconds } + let(duration, progression) { d, p -> (p * d.inWholeSeconds).seconds } ?: time diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Number.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Number.kt index f2a4bc4be1..52d0eeb2ad 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Number.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/extensions/Number.kt @@ -10,7 +10,7 @@ import java.text.NumberFormat import org.readium.r2.shared.InternalReadiumApi @InternalReadiumApi -fun Number.format(maximumFractionDigits: Int, percent: Boolean = false): String { +public fun Number.format(maximumFractionDigits: Int, percent: Boolean = false): String { val format = if (percent) NumberFormat.getPercentInstance() else NumberFormat.getNumberInstance() format.maximumFractionDigits = maximumFractionDigits return format.format(this) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/html/HtmlDecorationTemplate.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/html/HtmlDecorationTemplate.kt index eafd2084a0..6cc1286d96 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/html/HtmlDecorationTemplate.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/html/HtmlDecorationTemplate.kt @@ -37,7 +37,7 @@ import org.readium.r2.shared.JSONable * your app name. r2- and readium- are reserved by the Readium toolkit. */ @ExperimentalDecorator -data class HtmlDecorationTemplate( +public data class HtmlDecorationTemplate( val layout: Layout, val width: Width = Width.WRAP, val element: (Decoration) -> String = { "
" }, @@ -49,7 +49,7 @@ data class HtmlDecorationTemplate( * DOM range. */ @Parcelize - enum class Layout(val value: String) : Parcelable { + public enum class Layout(public val value: String) : Parcelable { /** A single HTML element covering the smallest region containing all CSS border boxes. */ BOUNDS("bounds"), /** One HTML element for each CSS border box (e.g. line of text). */ @@ -60,7 +60,7 @@ data class HtmlDecorationTemplate( * Indicates how the width of each created HTML element expands in the viewport. */ @Parcelize - enum class Width(val value: String) : Parcelable { + public enum class Width(public val value: String) : Parcelable { /** Smallest width fitting the CSS border box. */ WRAP("wrap"), /** Fills the bounds layout. */ @@ -78,20 +78,30 @@ data class HtmlDecorationTemplate( val bottom: Int = 0 ) - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("layout", layout.value) put("width", width.value) putOpt("stylesheet", stylesheet) } - companion object { + public companion object { /** Creates a new decoration template for the highlight style. */ - fun highlight(@ColorInt defaultTint: Int, lineWeight: Int, cornerRadius: Int, alpha: Double): HtmlDecorationTemplate = + public fun highlight( + @ColorInt defaultTint: Int, + lineWeight: Int, + cornerRadius: Int, + alpha: Double + ): HtmlDecorationTemplate = createTemplate(asHighlight = true, defaultTint = defaultTint, lineWeight = lineWeight, cornerRadius = cornerRadius, alpha = alpha) /** Creates a new decoration template for the underline style. */ - fun underline(@ColorInt defaultTint: Int, lineWeight: Int, cornerRadius: Int, alpha: Double): HtmlDecorationTemplate = + public fun underline( + @ColorInt defaultTint: Int, + lineWeight: Int, + cornerRadius: Int, + alpha: Double + ): HtmlDecorationTemplate = createTemplate(asHighlight = false, defaultTint = defaultTint, lineWeight = lineWeight, cornerRadius = cornerRadius, alpha = alpha) /** @@ -143,38 +153,38 @@ data class HtmlDecorationTemplate( } @ExperimentalDecorator -class HtmlDecorationTemplates private constructor( +public class HtmlDecorationTemplates private constructor( internal val styles: MutableMap, HtmlDecorationTemplate> = mutableMapOf() ) : JSONable { - operator fun get(style: KClass): HtmlDecorationTemplate? = + public operator fun get(style: KClass): HtmlDecorationTemplate? = styles[style] - operator fun set(style: KClass, template: HtmlDecorationTemplate) { + public operator fun set(style: KClass, template: HtmlDecorationTemplate) { styles[style] = template } - override fun toJSON() = JSONObject( + override fun toJSON(): JSONObject = JSONObject( styles.entries.associate { it.key.qualifiedName!! to it.value.toJSON() } ) - fun copy() = HtmlDecorationTemplates(styles.toMutableMap()) + public fun copy(): HtmlDecorationTemplates = HtmlDecorationTemplates(styles.toMutableMap()) - companion object { - operator fun invoke(build: HtmlDecorationTemplates.() -> Unit): HtmlDecorationTemplates = + public companion object { + public operator fun invoke(build: HtmlDecorationTemplates.() -> Unit): HtmlDecorationTemplates = HtmlDecorationTemplates().apply(build) /** * Creates the default list of decoration styles with associated HTML templates. */ - fun defaultTemplates( + public fun defaultTemplates( @ColorInt defaultTint: Int = Color.YELLOW, lineWeight: Int = 2, cornerRadius: Int = 3, alpha: Double = 0.3 - ) = HtmlDecorationTemplates { + ): HtmlDecorationTemplates = HtmlDecorationTemplates { set(Style.Highlight::class, HtmlDecorationTemplate.highlight(defaultTint = defaultTint, lineWeight = lineWeight, cornerRadius = cornerRadius, alpha = alpha)) set(Style.Underline::class, HtmlDecorationTemplate.underline(defaultTint = defaultTint, lineWeight = lineWeight, cornerRadius = cornerRadius, alpha = alpha)) } @@ -186,10 +196,10 @@ class HtmlDecorationTemplates private constructor( * * @param alpha When set, overrides the actual color alpha. */ -fun @receiver:ColorInt Int.toCss(alpha: Double? = null): String { +public fun @receiver:ColorInt Int.toCss(alpha: Double? = null): String { val r = Color.red(this) val g = Color.green(this) val b = Color.blue(this) - val a = alpha ?: Color.alpha(this).toDouble() / 255 + val a = alpha ?: (Color.alpha(this).toDouble() / 255) return "rgba($r, $g, $b, $a)" } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt index 16a2470287..00a25a4b8b 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt @@ -50,13 +50,13 @@ import org.readium.r2.shared.publication.services.positions * Navigator for bitmap-based publications, such as CBZ. */ @OptIn(ExperimentalReadiumApi::class) -class ImageNavigatorFragment private constructor( +public class ImageNavigatorFragment private constructor( override val publication: Publication, private val initialLocator: Locator? = null, internal val listener: Listener? = null ) : Fragment(), CoroutineScope by MainScope(), VisualNavigator { - interface Listener : VisualNavigator.Listener + public interface Listener : VisualNavigator.Listener init { require(!publication.isRestricted) { "The provided publication is restricted. Check that any DRM was properly unlocked using a Content Protection." } @@ -150,13 +150,13 @@ class ImageNavigatorFragment private constructor( @Deprecated("Use goForward instead", replaceWith = ReplaceWith("goForward()"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - fun nextResource(v: View?) { + public fun nextResource(v: View?) { goForward() } @Deprecated("Use goBackward instead", replaceWith = ReplaceWith("goBackward()"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - fun previousResource(v: View?) { + public fun previousResource(v: View?) { goBackward() } @@ -248,7 +248,7 @@ class ImageNavigatorFragment private constructor( inputListener.remove(listener) } - companion object { + public companion object { /** * Factory for [ImageNavigatorFragment]. @@ -258,7 +258,7 @@ class ImageNavigatorFragment private constructor( * publication. Can be used to restore the last reading location. * @param listener Optional listener to implement to observe events, such as user taps. */ - fun createFactory( + public fun createFactory( publication: Publication, initialLocator: Locator? = null, listener: Listener? = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/input/DragEvent.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/input/DragEvent.kt index ed2daff2d2..2b380db610 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/input/DragEvent.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/input/DragEvent.kt @@ -7,10 +7,10 @@ import android.graphics.PointF * * All the points are relative to the navigator view. */ -data class DragEvent( +public data class DragEvent( val type: Type, val start: PointF, val offset: PointF ) { - enum class Type { Start, Move, End } + public enum class Type { Start, Move, End } } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputListener.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputListener.kt index 79b8e24bad..52a0bcad5e 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputListener.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputListener.kt @@ -4,22 +4,22 @@ import org.readium.r2.navigator.VisualNavigator import org.readium.r2.shared.ExperimentalReadiumApi @ExperimentalReadiumApi -interface InputListener { +public interface InputListener { /** * Called when the user tapped the content, but nothing handled the event internally (eg. * by following an internal link). */ - fun onTap(navigator: VisualNavigator, event: TapEvent): Boolean = false + public fun onTap(navigator: VisualNavigator, event: TapEvent): Boolean = false /** * Called when the user dragged the content, but nothing handled the event internally. */ - fun onDrag(navigator: VisualNavigator, event: DragEvent): Boolean = false + public fun onDrag(navigator: VisualNavigator, event: DragEvent): Boolean = false /** * Called when the user pressed or released a key, but nothing handled the event internally. */ - fun onKey(navigator: VisualNavigator, event: KeyEvent): Boolean = false + public fun onKey(navigator: VisualNavigator, event: KeyEvent): Boolean = false } @OptIn(ExperimentalReadiumApi::class) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputModifier.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputModifier.kt index c70008d0c3..dd13e6530a 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputModifier.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/input/InputModifier.kt @@ -3,6 +3,6 @@ package org.readium.r2.navigator.input /** * Represents a key modifier for an input event. */ -enum class InputModifier { +public enum class InputModifier { Alt, Control, Meta, Shift } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/input/KeyEvent.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/input/KeyEvent.kt index aa6644b675..0aa4021c72 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/input/KeyEvent.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/input/KeyEvent.kt @@ -10,19 +10,19 @@ import android.view.KeyEvent as AndroidKeyEvent * @param modifiers Additional input modifiers for keyboard shortcuts. * @param characters Characters generated by the keypress, if any. */ -data class KeyEvent( +public data class KeyEvent( val type: Type, val key: Key, val modifiers: Set, val characters: String? ) { - enum class Type { + public enum class Type { Down, Up } - companion object { - operator fun invoke(type: Type, event: AndroidKeyEvent): KeyEvent? { + public companion object { + public operator fun invoke(type: Type, event: AndroidKeyEvent): KeyEvent? { return KeyEvent( type = type, key = Key(event) ?: return null, @@ -39,189 +39,189 @@ data class KeyEvent( * See https://w3c.github.io/uievents-code/ */ @JvmInline -value class Key(val code: String) { +public value class Key(public val code: String) { - companion object { + public companion object { // Alphanumeric section - val Backquote = Key("Backquote") - val Backslash = Key("Backslash") - val BracketLeft = Key("BracketLeft") - val BracketRight = Key("BracketRight") - val Comma = Key("Comma") - val Digit0 = Key("Digit0") - val Digit1 = Key("Digit1") - val Digit2 = Key("Digit2") - val Digit3 = Key("Digit3") - val Digit4 = Key("Digit4") - val Digit5 = Key("Digit5") - val Digit6 = Key("Digit6") - val Digit7 = Key("Digit7") - val Digit8 = Key("Digit8") - val Digit9 = Key("Digit9") - val Equal = Key("Equal") - val IntlBackslash = Key("IntlBackslash") - val IntlRo = Key("IntlRo") - val IntlYen = Key("IntlYen") - val KeyA = Key("KeyA") - val KeyB = Key("KeyB") - val KeyC = Key("KeyC") - val KeyD = Key("KeyD") - val KeyE = Key("KeyE") - val KeyF = Key("KeyF") - val KeyG = Key("KeyG") - val KeyH = Key("KeyH") - val KeyI = Key("KeyI") - val KeyJ = Key("KeyJ") - val KeyK = Key("KeyK") - val KeyL = Key("KeyL") - val KeyM = Key("KeyM") - val KeyN = Key("KeyN") - val KeyO = Key("KeyO") - val KeyP = Key("KeyP") - val KeyQ = Key("KeyQ") - val KeyR = Key("KeyR") - val KeyS = Key("KeyS") - val KeyT = Key("KeyT") - val KeyU = Key("KeyU") - val KeyV = Key("KeyV") - val KeyW = Key("KeyW") - val KeyX = Key("KeyX") - val KeyY = Key("KeyY") - val KeyZ = Key("KeyZ") - val Minus = Key("Minus") - val Period = Key("Period") - val Quote = Key("Quote") - val Semicolon = Key("Semicolon") - val Slash = Key("Slash") + public val Backquote: Key = Key("Backquote") + public val Backslash: Key = Key("Backslash") + public val BracketLeft: Key = Key("BracketLeft") + public val BracketRight: Key = Key("BracketRight") + public val Comma: Key = Key("Comma") + public val Digit0: Key = Key("Digit0") + public val Digit1: Key = Key("Digit1") + public val Digit2: Key = Key("Digit2") + public val Digit3: Key = Key("Digit3") + public val Digit4: Key = Key("Digit4") + public val Digit5: Key = Key("Digit5") + public val Digit6: Key = Key("Digit6") + public val Digit7: Key = Key("Digit7") + public val Digit8: Key = Key("Digit8") + public val Digit9: Key = Key("Digit9") + public val Equal: Key = Key("Equal") + public val IntlBackslash: Key = Key("IntlBackslash") + public val IntlRo: Key = Key("IntlRo") + public val IntlYen: Key = Key("IntlYen") + public val KeyA: Key = Key("KeyA") + public val KeyB: Key = Key("KeyB") + public val KeyC: Key = Key("KeyC") + public val KeyD: Key = Key("KeyD") + public val KeyE: Key = Key("KeyE") + public val KeyF: Key = Key("KeyF") + public val KeyG: Key = Key("KeyG") + public val KeyH: Key = Key("KeyH") + public val KeyI: Key = Key("KeyI") + public val KeyJ: Key = Key("KeyJ") + public val KeyK: Key = Key("KeyK") + public val KeyL: Key = Key("KeyL") + public val KeyM: Key = Key("KeyM") + public val KeyN: Key = Key("KeyN") + public val KeyO: Key = Key("KeyO") + public val KeyP: Key = Key("KeyP") + public val KeyQ: Key = Key("KeyQ") + public val KeyR: Key = Key("KeyR") + public val KeyS: Key = Key("KeyS") + public val KeyT: Key = Key("KeyT") + public val KeyU: Key = Key("KeyU") + public val KeyV: Key = Key("KeyV") + public val KeyW: Key = Key("KeyW") + public val KeyX: Key = Key("KeyX") + public val KeyY: Key = Key("KeyY") + public val KeyZ: Key = Key("KeyZ") + public val Minus: Key = Key("Minus") + public val Period: Key = Key("Period") + public val Quote: Key = Key("Quote") + public val Semicolon: Key = Key("Semicolon") + public val Slash: Key = Key("Slash") // Function keys - val AltLeft = Key("AltLeft") - val AltRight = Key("AltRight") - val Backspace = Key("Backspace") - val CapsLock = Key("CapsLock") - val ContextMenu = Key("ContextMenu") - val ControlLeft = Key("ControlLeft") - val ControlRight = Key("ControlRight") - val Enter = Key("Enter") - val MetaLeft = Key("MetaLeft") - val MetaRight = Key("MetaRight") - val ShiftLeft = Key("ShiftLeft") - val ShiftRight = Key("ShiftRight") - val Space = Key("Space") - val Tab = Key("Tab") + public val AltLeft: Key = Key("AltLeft") + public val AltRight: Key = Key("AltRight") + public val Backspace: Key = Key("Backspace") + public val CapsLock: Key = Key("CapsLock") + public val ContextMenu: Key = Key("ContextMenu") + public val ControlLeft: Key = Key("ControlLeft") + public val ControlRight: Key = Key("ControlRight") + public val Enter: Key = Key("Enter") + public val MetaLeft: Key = Key("MetaLeft") + public val MetaRight: Key = Key("MetaRight") + public val ShiftLeft: Key = Key("ShiftLeft") + public val ShiftRight: Key = Key("ShiftRight") + public val Space: Key = Key("Space") + public val Tab: Key = Key("Tab") // Function keys (Japanese and Korean keyboards) - val Convert = Key("Convert") - val KanaMode = Key("KanaMode") - val Lang1 = Key("Lang1") - val Lang2 = Key("Lang2") - val Lang3 = Key("Lang3") - val Lang4 = Key("Lang4") - val Lang5 = Key("Lang5") - val NonConvert = Key("NonConvert") + public val Convert: Key = Key("Convert") + public val KanaMode: Key = Key("KanaMode") + public val Lang1: Key = Key("Lang1") + public val Lang2: Key = Key("Lang2") + public val Lang3: Key = Key("Lang3") + public val Lang4: Key = Key("Lang4") + public val Lang5: Key = Key("Lang5") + public val NonConvert: Key = Key("NonConvert") // Control pad section - val Delete = Key("Delete") - val End = Key("End") - val Help = Key("Help") - val Home = Key("Home") - val Insert = Key("Insert") - val PageDown = Key("PageDown") - val PageUp = Key("PageUp") + public val Delete: Key = Key("Delete") + public val End: Key = Key("End") + public val Help: Key = Key("Help") + public val Home: Key = Key("Home") + public val Insert: Key = Key("Insert") + public val PageDown: Key = Key("PageDown") + public val PageUp: Key = Key("PageUp") // Arrow pad section - val ArrowDown = Key("ArrowDown") - val ArrowLeft = Key("ArrowLeft") - val ArrowRight = Key("ArrowRight") - val ArrowUp = Key("ArrowUp") + public val ArrowDown: Key = Key("ArrowDown") + public val ArrowLeft: Key = Key("ArrowLeft") + public val ArrowRight: Key = Key("ArrowRight") + public val ArrowUp: Key = Key("ArrowUp") // Numpad section - val NumLock = Key("NumLock") - val Numpad0 = Key("Numpad0") - val Numpad1 = Key("Numpad1") - val Numpad2 = Key("Numpad2") - val Numpad3 = Key("Numpad3") - val Numpad4 = Key("Numpad4") - val Numpad5 = Key("Numpad5") - val Numpad6 = Key("Numpad6") - val Numpad7 = Key("Numpad7") - val Numpad8 = Key("Numpad8") - val Numpad9 = Key("Numpad9") - val NumpadAdd = Key("NumpadAdd") - val NumpadBackspace = Key("NumpadBackspace") - val NumpadClear = Key("NumpadClear") - val NumpadClearEntry = Key("NumpadClearEntry") - val NumpadComma = Key("NumpadComma") - val NumpadDecimal = Key("NumpadDecimal") - val NumpadDivide = Key("NumpadDivide") - val NumpadEnter = Key("NumpadEnter") - val NumpadEqual = Key("NumpadEqual") - val NumpadHash = Key("NumpadHash") - val NumpadMemoryAdd = Key("NumpadMemoryAdd") - val NumpadMemoryClear = Key("NumpadMemoryClear") - val NumpadMemoryRecall = Key("NumpadMemoryRecall") - val NumpadMemoryStore = Key("NumpadMemoryStore") - val NumpadMemorySubtract = Key("NumpadMemorySubtract") - val NumpadMultiply = Key("NumpadMultiply") - val NumpadParenLeft = Key("NumpadParenLeft") - val NumpadParenRight = Key("NumpadParenRight") - val NumpadStar = Key("NumpadStar") - val NumpadSubtract = Key("NumpadSubtract") + public val NumLock: Key = Key("NumLock") + public val Numpad0: Key = Key("Numpad0") + public val Numpad1: Key = Key("Numpad1") + public val Numpad2: Key = Key("Numpad2") + public val Numpad3: Key = Key("Numpad3") + public val Numpad4: Key = Key("Numpad4") + public val Numpad5: Key = Key("Numpad5") + public val Numpad6: Key = Key("Numpad6") + public val Numpad7: Key = Key("Numpad7") + public val Numpad8: Key = Key("Numpad8") + public val Numpad9: Key = Key("Numpad9") + public val NumpadAdd: Key = Key("NumpadAdd") + public val NumpadBackspace: Key = Key("NumpadBackspace") + public val NumpadClear: Key = Key("NumpadClear") + public val NumpadClearEntry: Key = Key("NumpadClearEntry") + public val NumpadComma: Key = Key("NumpadComma") + public val NumpadDecimal: Key = Key("NumpadDecimal") + public val NumpadDivide: Key = Key("NumpadDivide") + public val NumpadEnter: Key = Key("NumpadEnter") + public val NumpadEqual: Key = Key("NumpadEqual") + public val NumpadHash: Key = Key("NumpadHash") + public val NumpadMemoryAdd: Key = Key("NumpadMemoryAdd") + public val NumpadMemoryClear: Key = Key("NumpadMemoryClear") + public val NumpadMemoryRecall: Key = Key("NumpadMemoryRecall") + public val NumpadMemoryStore: Key = Key("NumpadMemoryStore") + public val NumpadMemorySubtract: Key = Key("NumpadMemorySubtract") + public val NumpadMultiply: Key = Key("NumpadMultiply") + public val NumpadParenLeft: Key = Key("NumpadParenLeft") + public val NumpadParenRight: Key = Key("NumpadParenRight") + public val NumpadStar: Key = Key("NumpadStar") + public val NumpadSubtract: Key = Key("NumpadSubtract") // Function section - val Escape = Key("Escape") - val F1 = Key("F1") - val F2 = Key("F2") - val F3 = Key("F3") - val F4 = Key("F4") - val F5 = Key("F5") - val F6 = Key("F6") - val F7 = Key("F7") - val F8 = Key("F8") - val F9 = Key("F9") - val F10 = Key("F10") - val F11 = Key("F11") - val F12 = Key("F12") - val Fn = Key("Fn") - val FnLock = Key("FnLock") - val PrintScreen = Key("PrintScreen") - val ScrollLock = Key("ScrollLock") - val Pause = Key("Pause") + public val Escape: Key = Key("Escape") + public val F1: Key = Key("F1") + public val F2: Key = Key("F2") + public val F3: Key = Key("F3") + public val F4: Key = Key("F4") + public val F5: Key = Key("F5") + public val F6: Key = Key("F6") + public val F7: Key = Key("F7") + public val F8: Key = Key("F8") + public val F9: Key = Key("F9") + public val F10: Key = Key("F10") + public val F11: Key = Key("F11") + public val F12: Key = Key("F12") + public val Fn: Key = Key("Fn") + public val FnLock: Key = Key("FnLock") + public val PrintScreen: Key = Key("PrintScreen") + public val ScrollLock: Key = Key("ScrollLock") + public val Pause: Key = Key("Pause") // Media keys - val BrowserBack = Key("BrowserBack") - val BrowserFavorites = Key("BrowserFavorites") - val BrowserForward = Key("BrowserForward") - val BrowserHome = Key("BrowserHome") - val BrowserRefresh = Key("BrowserRefresh") - val BrowserSearch = Key("BrowserSearch") - val BrowserStop = Key("BrowserStop") - val Eject = Key("Eject") - val LaunchApp1 = Key("LaunchApp1") - val LaunchApp2 = Key("LaunchApp2") - val LaunchMail = Key("LaunchMail") - val MediaPlayPause = Key("MediaPlayPause") - val MediaSelect = Key("MediaSelect") - val MediaStop = Key("MediaStop") - val MediaTrackNext = Key("MediaTrackNext") - val MediaTrackPrevious = Key("MediaTrackPrevious") - val Power = Key("Power") - val Sleep = Key("Sleep") - val AudioVolumeDown = Key("AudioVolumeDown") - val AudioVolumeMute = Key("AudioVolumeMute") - val AudioVolumeUp = Key("AudioVolumeUp") - val WakeUp = Key("WakeUp") - - operator fun invoke(event: AndroidKeyEvent): Key? = + public val BrowserBack: Key = Key("BrowserBack") + public val BrowserFavorites: Key = Key("BrowserFavorites") + public val BrowserForward: Key = Key("BrowserForward") + public val BrowserHome: Key = Key("BrowserHome") + public val BrowserRefresh: Key = Key("BrowserRefresh") + public val BrowserSearch: Key = Key("BrowserSearch") + public val BrowserStop: Key = Key("BrowserStop") + public val Eject: Key = Key("Eject") + public val LaunchApp1: Key = Key("LaunchApp1") + public val LaunchApp2: Key = Key("LaunchApp2") + public val LaunchMail: Key = Key("LaunchMail") + public val MediaPlayPause: Key = Key("MediaPlayPause") + public val MediaSelect: Key = Key("MediaSelect") + public val MediaStop: Key = Key("MediaStop") + public val MediaTrackNext: Key = Key("MediaTrackNext") + public val MediaTrackPrevious: Key = Key("MediaTrackPrevious") + public val Power: Key = Key("Power") + public val Sleep: Key = Key("Sleep") + public val AudioVolumeDown: Key = Key("AudioVolumeDown") + public val AudioVolumeMute: Key = Key("AudioVolumeMute") + public val AudioVolumeUp: Key = Key("AudioVolumeUp") + public val WakeUp: Key = Key("WakeUp") + + public operator fun invoke(event: AndroidKeyEvent): Key? = when (event.keyCode) { AndroidKeyEvent.KEYCODE_DEL -> Backspace AndroidKeyEvent.KEYCODE_ENTER -> Enter diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/input/TapEvent.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/input/TapEvent.kt index b3d4c94792..8a3adf1928 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/input/TapEvent.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/input/TapEvent.kt @@ -7,6 +7,6 @@ import android.graphics.PointF * * All the points are relative to the navigator view. */ -data class TapEvent( +public data class TapEvent( val point: PointF ) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media/ExoMediaPlayer.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media/ExoMediaPlayer.kt index 223ecc2486..c14447bab7 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media/ExoMediaPlayer.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media/ExoMediaPlayer.kt @@ -35,7 +35,6 @@ import com.google.android.exoplayer2.upstream.cache.Cache import com.google.android.exoplayer2.upstream.cache.CacheDataSource import java.net.UnknownHostException import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.MainScope @@ -59,8 +58,7 @@ import timber.log.Timber * An implementation of [MediaPlayer] using ExoPlayer. */ @ExperimentalAudiobook -@OptIn(ExperimentalTime::class) -class ExoMediaPlayer( +public class ExoMediaPlayer( context: Context, mediaSession: MediaSessionCompat, media: PendingMedia, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayback.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayback.kt index c02d7e08df..d242310e91 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayback.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayback.kt @@ -7,7 +7,6 @@ package org.readium.r2.navigator.media import kotlin.time.Duration -import kotlin.time.ExperimentalTime import org.readium.r2.navigator.ExperimentalAudiobook /** @@ -17,18 +16,17 @@ import org.readium.r2.navigator.ExperimentalAudiobook * @param rate Speed of the playback, defaults to 1.0. * @param timeline Position and duration of the current resource. */ -@OptIn(ExperimentalTime::class) @ExperimentalAudiobook -data class MediaPlayback(val state: State, val rate: Double, val timeline: Timeline) { +public data class MediaPlayback(val state: State, val rate: Double, val timeline: Timeline) { - enum class State { + public enum class State { Idle, Loading, Playing, Paused; - val isPlaying: Boolean get() = + public val isPlaying: Boolean get() = (this == Playing || this == Loading) } - data class Timeline( + public data class Timeline( val position: Duration, val duration: Duration?, val buffered: Duration? diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayer.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayer.kt index e1eb17c5b6..bc18fab597 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayer.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaPlayer.kt @@ -26,44 +26,47 @@ import org.readium.r2.shared.resource.Resource * `publicationId#resourceHref` with a [Locator] as a `locator` extra field. */ @ExperimentalAudiobook -interface MediaPlayer { +public interface MediaPlayer { - data class NotificationMetadata( + public data class NotificationMetadata( val publicationTitle: String?, val trackTitle: String?, val authors: String? ) { - constructor(publication: Publication, link: Link) : this( + public constructor(publication: Publication, link: Link) : this( publicationTitle = publication.metadata.title, trackTitle = link.title, authors = publication.metadata.authors.joinToString(", ") { it.name }.takeIf { it.isNotBlank() } ) } - interface Listener { + public interface Listener { - fun locatorFromMediaId(mediaId: String, extras: Bundle?): Locator? + public fun locatorFromMediaId(mediaId: String, extras: Bundle?): Locator? - suspend fun coverOfPublication(publication: Publication, publicationId: PublicationId): Bitmap? + public suspend fun coverOfPublication( + publication: Publication, + publicationId: PublicationId + ): Bitmap? - fun onNotificationPosted(notificationId: Int, notification: Notification) - fun onNotificationCancelled(notificationId: Int) - fun onCommand(command: String, args: Bundle?, cb: ResultReceiver?): Boolean + public fun onNotificationPosted(notificationId: Int, notification: Notification) + public fun onNotificationCancelled(notificationId: Int) + public fun onCommand(command: String, args: Bundle?, cb: ResultReceiver?): Boolean - fun onPlayerStopped() + public fun onPlayerStopped() /** * Called when a resource failed to be loaded, for example because the Internet connection * is offline and the resource is streamed. */ - fun onResourceLoadFailed(link: Link, error: Resource.Exception) + public fun onResourceLoadFailed(link: Link, error: Resource.Exception) /** * Creates the [NotificationMetadata] for the given resource [link]. * * The metadata will be used for the media-style notification. */ - fun onCreateNotificationMetadata( + public fun onCreateNotificationMetadata( publication: Publication, publicationId: PublicationId, link: Link @@ -71,9 +74,9 @@ interface MediaPlayer { } // FIXME: ExoPlayer's media session connector doesn't handle the playback speed yet, so I used a custom solution until we create our own connector - var playbackRate: Double + public var playbackRate: Double - var listener: Listener? + public var listener: Listener? - fun onDestroy() + public fun onDestroy() } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaService.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaService.kt index 9f43bb3c2c..f2293743dd 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaService.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaService.kt @@ -45,26 +45,26 @@ import timber.log.Timber */ @ExperimentalAudiobook @OptIn(ExperimentalCoroutinesApi::class) -open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainScope() { +public open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainScope() { /** * Creates the instance of [MediaPlayer] which will be used for playing the given [media]. * * The default implementation uses ExoPlayer. */ - open fun onCreatePlayer(mediaSession: MediaSessionCompat, media: PendingMedia): MediaPlayer = + public open fun onCreatePlayer(mediaSession: MediaSessionCompat, media: PendingMedia): MediaPlayer = ExoMediaPlayer(this, mediaSession, media) /** * Called when the underlying [MediaPlayer] was stopped. */ - open fun onPlayerStopped() {} + public open fun onPlayerStopped() {} /** * Creates the [PendingIntent] which will be used to start the media activity when the user * activates the media notification. */ - open suspend fun onCreateNotificationIntent( + public open suspend fun onCreateNotificationIntent( publicationId: PublicationId, publication: Publication ): PendingIntent? = null @@ -74,7 +74,7 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco * * The metadata will be used for the media-style notification. */ - open fun onCreateNotificationMetadata( + public open fun onCreateNotificationMetadata( publicationId: PublicationId, publication: Publication, link: Link @@ -84,7 +84,10 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco /** * Returns the cover for the given [publication] which should be used in media notifications. */ - open suspend fun coverOfPublication(publicationId: PublicationId, publication: Publication): Bitmap? = + public open suspend fun coverOfPublication( + publicationId: PublicationId, + publication: Publication + ): Bitmap? = publication.cover() /** @@ -92,7 +95,7 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco * * @return Whether the custom command was handled. */ - open fun onCommand(command: String, args: Bundle?, cb: ResultReceiver?): Boolean = false + public open fun onCommand(command: String, args: Bundle?, cb: ResultReceiver?): Boolean = false /** * Called when a resource failed to be loaded, for example because the Internet connection @@ -100,7 +103,7 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco * * You should present the exception to the user. */ - open fun onResourceLoadFailed(link: Link, error: Resource.Exception) { + public open fun onResourceLoadFailed(link: Link, error: Resource.Exception) { Toast.makeText(this, error.getUserMessage(this), Toast.LENGTH_LONG).show() } @@ -111,7 +114,7 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco * @param packageName The package name of the application which is requesting access. * @param uid The UID of the application which is requesting access. */ - open fun isClientAuthorized(packageName: String, uid: Int): Boolean = + public open fun isClientAuthorized(packageName: String, uid: Int): Boolean = (uid == Process.myUid()) protected val mediaSession: MediaSessionCompat get() = getMediaSession(this, javaClass) @@ -278,7 +281,7 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco result.sendResult(mutableListOf()) } - companion object { + public companion object { internal const val EVENT_PUBLICATION_CHANGED = "org.readium.r2.navigator.EVENT_PUBLICATION_CHANGED" internal const val EXTRA_PUBLICATION_ID = "org.readium.r2.navigator.EXTRA_PUBLICATION_ID" @@ -289,9 +292,9 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco private val currentNavigator = MutableStateFlow(null) private val pendingNavigator = Channel(Channel.CONFLATED) - val navigator = currentNavigator.asStateFlow() + public val navigator: StateFlow = currentNavigator.asStateFlow() - fun connect(serviceClass: Class<*> = MediaService::class.java): Connection = + public fun connect(serviceClass: Class<*> = MediaService::class.java): Connection = createIfNull(this::connection, this) { Connection(serviceClass) } @@ -316,11 +319,11 @@ open class MediaService : MediaBrowserServiceCompat(), CoroutineScope by MainSco * Use a [Connection] to get a [MediaSessionNavigator] from a [Publication]. * It will start the service if needed. */ - class Connection internal constructor(private val serviceClass: Class<*>) { + public class Connection internal constructor(private val serviceClass: Class<*>) { - val currentNavigator: StateFlow get() = navigator + public val currentNavigator: StateFlow get() = navigator - fun getNavigator( + public fun getNavigator( context: Context, publication: Publication, publicationId: PublicationId, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaSessionNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaSessionNavigator.kt index 03d371d734..193e7eef0b 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaSessionNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media/MediaSessionNavigator.kt @@ -35,24 +35,22 @@ import timber.log.Timber */ private const val playbackPositionRefreshRate: Double = 2.0 // Hz -@OptIn(ExperimentalTime::class) private val skipForwardInterval: Duration = 30.seconds -@OptIn(ExperimentalTime::class) private val skipBackwardInterval: Duration = 30.seconds /** * An implementation of [MediaNavigator] using an Android's MediaSession compatible media player. */ @ExperimentalAudiobook -@OptIn(ExperimentalCoroutinesApi::class, ExperimentalTime::class) -class MediaSessionNavigator( +@OptIn(ExperimentalTime::class) +public class MediaSessionNavigator( override val publication: Publication, - val publicationId: PublicationId, - val controller: MediaControllerCompat, - var listener: Listener? = null + internal val publicationId: PublicationId, + private val controller: MediaControllerCompat, + public var listener: Listener? = null ) : MediaNavigator, CoroutineScope by MainScope() { - interface Listener : MediaNavigator.Listener + public interface Listener : MediaNavigator.Listener /** * Indicates whether the media session is loaded with a resource from this [publication]. This diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media/PendingMedia.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media/PendingMedia.kt index 52987ab2fd..da036017d2 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media/PendingMedia.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media/PendingMedia.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.publication.PublicationId * Holds information about a media-based [publication] waiting to be rendered by a [MediaPlayer]. */ @ExperimentalAudiobook -data class PendingMedia( +public data class PendingMedia( val publication: Publication, val publicationId: PublicationId, val locator: Locator diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/DefaultMediaMetadataProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/DefaultMediaMetadataProvider.kt index 447426b46c..18edb295d8 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/DefaultMediaMetadataProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/DefaultMediaMetadataProvider.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.publication.Publication * Builds a [MediaMetadataFactory] which will use the given title, author and cover, * and fall back on what is in the publication. */ -class DefaultMediaMetadataProvider( +public class DefaultMediaMetadataProvider( private val title: String? = null, private val author: String? = null, private val cover: Uri? = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/Media3Adapter.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/Media3Adapter.kt index b5822a9b22..ab58358659 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/Media3Adapter.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/Media3Adapter.kt @@ -7,6 +7,6 @@ import org.readium.r2.shared.ExperimentalReadiumApi * An object able to pass as a Jetpack media3 [Player]. */ @ExperimentalReadiumApi -interface Media3Adapter { - fun asMedia3Player(): Player +public interface Media3Adapter { + public fun asMedia3Player(): Player } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataFactory.kt index 0e705f354b..bdeb211e4d 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataFactory.kt @@ -13,15 +13,15 @@ import androidx.media3.common.MediaMetadata * * The metadata are used for example in the media-style Android notification. */ -interface MediaMetadataFactory { +public interface MediaMetadataFactory { /** * Creates the [MediaMetadata] for the whole publication. */ - suspend fun publicationMetadata(): MediaMetadata + public suspend fun publicationMetadata(): MediaMetadata /** * Creates the [MediaMetadata] for the reading order resource at the given [index]. */ - suspend fun resourceMetadata(index: Int): MediaMetadata + public suspend fun resourceMetadata(index: Int): MediaMetadata } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataProvider.kt index fb1a45d8d1..706932e049 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaMetadataProvider.kt @@ -11,7 +11,7 @@ import org.readium.r2.shared.publication.Publication /** * To be implemented to use a custom [MediaMetadataFactory]. */ -fun interface MediaMetadataProvider { +public fun interface MediaMetadataProvider { - fun createMetadataFactory(publication: Publication): MediaMetadataFactory + public fun createMetadataFactory(publication: Publication): MediaMetadataFactory } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaNavigator.kt index 4a489354b2..f96be5648d 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/MediaNavigator.kt @@ -16,7 +16,7 @@ import org.readium.r2.shared.util.Href * A [Navigator] which can play multimedia content. */ @ExperimentalReadiumApi -interface MediaNavigator< +public interface MediaNavigator< L : MediaNavigator.Location, P : MediaNavigator.Playback, R : MediaNavigator.ReadingOrder @@ -25,96 +25,96 @@ interface MediaNavigator< /** * Location of the navigator. */ - interface Location { + public interface Location { - val href: Href + public val href: Href } /** * State of the player. */ - sealed interface State { + public sealed interface State { /** * The navigator is ready to play. */ - interface Ready : State + public interface Ready : State /** * The end of the media has been reached. */ - interface Ended : State + public interface Ended : State /** * The navigator cannot play because the buffer is starved. */ - interface Buffering : State + public interface Buffering : State /** * The navigator cannot play because an error occurred. */ - interface Error : State + public interface Error : State } /** * State of the playback. */ - interface Playback { + public interface Playback { /** * The current state. */ - val state: State + public val state: State /** * Indicates if the navigator should play as soon as the state is Ready. */ - val playWhenReady: Boolean + public val playWhenReady: Boolean /** * Index of the reading order item currently being played. */ - val index: Int + public val index: Int } /** * Data about the content to play. */ - interface ReadingOrder { + public interface ReadingOrder { /** * List of items to play. */ - val items: List + public val items: List /** * A piece of the content to play. */ - interface Item + public interface Item } /** * Current state of the playback. */ - val playback: StateFlow

+ public val playback: StateFlow

/** * Current location of the navigator. */ - val location: StateFlow + public val location: StateFlow /** * Reading order being read by this navigator. */ - val readingOrder: R + public val readingOrder: R /** * Resumes the playback at the current location. */ - fun play() + public fun play() /** * Pauses the playback. */ - fun pause() + public fun pause() } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TextAwareMediaNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TextAwareMediaNavigator.kt index b095743d7c..977fe07aa7 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TextAwareMediaNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TextAwareMediaNavigator.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.publication.Locator * A [MediaNavigator] aware of the utterances being read aloud. */ @ExperimentalReadiumApi -interface TextAwareMediaNavigator< +public interface TextAwareMediaNavigator< L : TextAwareMediaNavigator.Location, P : TextAwareMediaNavigator.Playback, R : TextAwareMediaNavigator.ReadingOrder @@ -23,59 +23,59 @@ interface TextAwareMediaNavigator< /** * Location of the navigator. */ - interface Location : MediaNavigator.Location { + public interface Location : MediaNavigator.Location { /** * The utterance being played. */ - val utterance: String + public val utterance: String /** * The text right before the utterance being played, if any in the current item. */ - val textBefore: String? + public val textBefore: String? /** * The text right after the utterance being played, if any in the current item. */ - val textAfter: String? + public val textAfter: String? /** * The range of [utterance] being played, if known. */ - val range: IntRange? + public val range: IntRange? /** * A locator pointing to the current utterance. */ - val utteranceLocator: Locator + public val utteranceLocator: Locator /** * A locator pointing to the current token, if known. */ - val tokenLocator: Locator? + public val tokenLocator: Locator? } /** * State of the playback. */ - interface Playback : MediaNavigator.Playback { + public interface Playback : MediaNavigator.Playback { /** * The utterance being played. */ - val utterance: String + public val utterance: String /** * The range of [utterance] being played. */ - val range: IntRange? + public val range: IntRange? } /** * Data about the content to play. */ - interface ReadingOrder : MediaNavigator.ReadingOrder { + public interface ReadingOrder : MediaNavigator.ReadingOrder { /** * List of items to play. @@ -85,7 +85,7 @@ interface TextAwareMediaNavigator< /** * A piece of the content to play.. */ - interface Item : MediaNavigator.ReadingOrder.Item + public interface Item : MediaNavigator.ReadingOrder.Item } /** @@ -108,22 +108,22 @@ interface TextAwareMediaNavigator< * * Does nothing if the current utterance is the first one. */ - fun goToPreviousUtterance() + public fun goToPreviousUtterance() /** * Jumps to the next utterance. * * Does nothing if the current utterance is the last one. */ - fun goToNextUtterance() + public fun goToNextUtterance() /** * Whether the current utterance has a previous one or is the first one. */ - fun hasPreviousUtterance(): Boolean + public fun hasPreviousUtterance(): Boolean /** * Whether the current utterance has a next utterance or is the last one. */ - fun hasNextUtterance(): Boolean + public fun hasNextUtterance(): Boolean } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TimeBasedMediaNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TimeBasedMediaNavigator.kt index 8c5d89e5e7..adc1cdfc27 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TimeBasedMediaNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/api/TimeBasedMediaNavigator.kt @@ -14,45 +14,45 @@ import org.readium.r2.shared.ExperimentalReadiumApi * A [MediaNavigator] whose locations provide time offsets. */ @ExperimentalReadiumApi -interface TimeBasedMediaNavigator : MediaNavigator { /** * Location of the navigator. */ - interface Location : MediaNavigator.Location { + public interface Location : MediaNavigator.Location { /** * The duration offset in the resource. */ - val offset: Duration + public val offset: Duration } /** * State of the playback. */ - interface Playback : MediaNavigator.Playback { + public interface Playback : MediaNavigator.Playback { /** * Position of the playback in the current item. */ - val offset: Duration + public val offset: Duration /** * Position in the current item until which the content is buffered. */ - val buffered: Duration? + public val buffered: Duration? } /** * Data about the content to play. */ - interface ReadingOrder : MediaNavigator.ReadingOrder { + public interface ReadingOrder : MediaNavigator.ReadingOrder { /** * Total duration of the content to play. */ - val duration: Duration? + public val duration: Duration? /** * List of items to play. @@ -62,12 +62,12 @@ interface TimeBasedMediaNavigator> : +public interface AudioEngine> : Configurable { /** * Marker interface for the errors that the [AudioEngine] returns. */ - interface Error + public interface Error /** * State of the player. */ - sealed class State { + public sealed class State { /** * The player is ready to play. */ - object Ready : State() + public object Ready : State() /** * The end of the content has been reached. */ - object Ended : State() + public object Ended : State() /** * The engine cannot play because the buffer is starved. */ - object Buffering : State() + public object Buffering : State() /** * The engine cannot play because an error occurred. */ - data class Error(val error: AudioEngine.Error) : State() + public data class Error(val error: AudioEngine.Error) : State() } /** @@ -59,7 +59,7 @@ interface AudioEngine * @param offset Position of the playback in the current item. * @param buffered Position in the current item until which the content is buffered. */ - data class Playback( + public data class Playback( val state: State, val playWhenReady: Boolean, val index: Int, @@ -70,45 +70,45 @@ interface AudioEngine /** * Current state of the playback. */ - val playback: StateFlow + public val playback: StateFlow /** * Resumes the playback at the current location. */ - fun play() + public fun play() /** * Pauses the playback. */ - fun pause() + public fun pause() /** * Seeks to [position] in the item at [index]. */ - fun seek(index: Int, position: Duration) + public fun seek(index: Int, position: Duration) /** * Seeks by [offset] either forward or backward if [offset] is negative. */ - fun seekBy(offset: Duration) + public fun seekBy(offset: Duration) /** * Seeks by a small increment forward. */ - fun seekForward() + public fun seekForward() /** * Seeks by a small increment backward. */ - fun seekBackward() + public fun seekBackward() /** * Closes the player. */ - fun close() + public fun close() /** * Adapts this engine to the media3 [Player] interface. */ - fun asPlayer(): Player + public fun asPlayer(): Player } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioEngineProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioEngineProvider.kt index 21ea7681a6..97d24bc6de 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioEngineProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioEngineProvider.kt @@ -10,34 +10,28 @@ import org.readium.r2.navigator.preferences.Configurable import org.readium.r2.navigator.preferences.PreferencesEditor import org.readium.r2.shared.ExperimentalReadiumApi import org.readium.r2.shared.publication.Locator -import org.readium.r2.shared.publication.Metadata import org.readium.r2.shared.publication.Publication /** * To be implemented by adapters for third-party audio engines which can be used with [AudioNavigator]. */ @ExperimentalReadiumApi -interface AudioEngineProvider, +public interface AudioEngineProvider, E : PreferencesEditor

> { - suspend fun createEngine( + public suspend fun createEngine( publication: Publication, initialLocator: Locator, initialPreferences: P ): AudioEngine? - /** - * Creates settings for [metadata] and [preferences]. - */ - fun computeSettings(metadata: Metadata, preferences: P): S - /** * Creates a preferences editor for [publication] and [initialPreferences]. */ - fun createPreferenceEditor(publication: Publication, initialPreferences: P): E + public fun createPreferenceEditor(publication: Publication, initialPreferences: P): E /** * Creates an empty set of preferences of this TTS engine provider. */ - fun createEmptyPreferences(): P + public fun createEmptyPreferences(): P } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigator.kt index c2ab1c5459..f44c2c91bb 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigator.kt @@ -30,7 +30,7 @@ import timber.log.Timber @ExperimentalReadiumApi @OptIn(ExperimentalTime::class) -class AudioNavigator> private constructor( +public class AudioNavigator> private constructor( override val publication: Publication, private val audioEngine: AudioEngine, override val readingOrder: ReadingOrder, @@ -40,9 +40,9 @@ class AudioNavigator> Media3Adapter, Configurable by audioEngine { - companion object { + public companion object { - suspend operator fun > invoke( + public suspend operator fun > invoke( publication: Publication, audioEngineProvider: AudioEngineProvider, readingOrder: List = publication.readingOrder, @@ -89,23 +89,23 @@ class AudioNavigator> } } - data class Location( + public data class Location( override val href: Href, override val offset: Duration, ) : TimeBasedMediaNavigator.Location - data class ReadingOrder( + public data class ReadingOrder( override val duration: Duration?, override val items: List ) : TimeBasedMediaNavigator.ReadingOrder { - data class Item( + public data class Item( val href: Href, override val duration: Duration? ) : TimeBasedMediaNavigator.ReadingOrder.Item } - data class Playback( + public data class Playback( override val state: MediaNavigator.State, override val playWhenReady: Boolean, override val index: Int, @@ -113,15 +113,15 @@ class AudioNavigator> override val buffered: Duration?, ) : TimeBasedMediaNavigator.Playback - sealed class State { + public sealed class State { - object Ready : MediaNavigator.State.Ready + public object Ready : MediaNavigator.State.Ready - object Ended : MediaNavigator.State.Ended + public object Ended : MediaNavigator.State.Ended - object Buffering : MediaNavigator.State.Buffering + public object Buffering : MediaNavigator.State.Buffering - data class Error (val error: E) : MediaNavigator.State.Error + public data class Error (val error: E) : MediaNavigator.State.Error } private val coroutineScope: CoroutineScope = @@ -178,15 +178,15 @@ class AudioNavigator> audioEngine.seek(index, offset) } - fun seekForward() { + public fun seekForward() { audioEngine.seekForward() } - fun seekBackward() { + public fun seekBackward() { audioEngine.seekBackward() } - fun seekBy(offset: Duration) { + public fun seekBy(offset: Duration) { audioEngine.seekBy(offset) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigatorFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigatorFactory.kt index a4b21cfb89..e0a2f9a7b0 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigatorFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/audio/AudioNavigatorFactory.kt @@ -13,16 +13,16 @@ import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication @ExperimentalReadiumApi -class AudioNavigatorFactory, +public class AudioNavigatorFactory, E : PreferencesEditor

> private constructor( private val publication: Publication, private val audioEngineProvider: AudioEngineProvider, ) { - companion object { + public companion object { @Suppress("RedundantSuspendModifier") - suspend operator fun , + public suspend operator fun , E : PreferencesEditor

> invoke( publication: Publication, audioEngineProvider: AudioEngineProvider, @@ -41,7 +41,7 @@ class AudioNavigatorFactory? { @@ -53,7 +53,7 @@ class AudioNavigatorFactory +public typealias ExoPlayerNavigatorFactory = AudioNavigatorFactory @OptIn(ExperimentalReadiumApi::class) -typealias ExoPlayerNavigator = AudioNavigator +public typealias ExoPlayerNavigator = AudioNavigator diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDataSource.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDataSource.kt index 51ad447912..da366df023 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDataSource.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDataSource.kt @@ -21,10 +21,10 @@ import org.readium.r2.shared.fetcher.buffered import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.resource.Resource -sealed class ExoPlayerDataSourceException(message: String, cause: Throwable?) : IOException(message, cause) { - class NotOpened(message: String) : ExoPlayerDataSourceException(message, null) - class NotFound(message: String) : ExoPlayerDataSourceException(message, null) - class ReadFailed(uri: Uri, offset: Int, readLength: Int, cause: Throwable) : ExoPlayerDataSourceException("Failed to read $readLength bytes of URI $uri at offset $offset.", cause) +public sealed class ExoPlayerDataSourceException(message: String, cause: Throwable?) : IOException(message, cause) { + public class NotOpened(message: String) : ExoPlayerDataSourceException(message, null) + public class NotFound(message: String) : ExoPlayerDataSourceException(message, null) + public class ReadFailed(uri: Uri, offset: Int, readLength: Int, cause: Throwable) : ExoPlayerDataSourceException("Failed to read $readLength bytes of URI $uri at offset $offset.", cause) } /** diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDefaults.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDefaults.kt index dd3f84b175..b987c214c9 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDefaults.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerDefaults.kt @@ -17,7 +17,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @see ExoPlayerPreferences */ @ExperimentalReadiumApi -data class ExoPlayerDefaults( +public data class ExoPlayerDefaults( val pitch: Double? = null, val speed: Double? = null ) { diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngine.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngine.kt index a80e16055e..c2e6344f14 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngine.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngine.kt @@ -30,16 +30,16 @@ import org.readium.r2.shared.units.hz @ExperimentalReadiumApi @OptIn(ExperimentalCoroutinesApi::class) @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) -class ExoPlayerEngine private constructor( +public class ExoPlayerEngine private constructor( private val exoPlayer: ExoAudiobookPlayer, private val settingsResolver: SettingsResolver, private val configuration: Configuration, initialPreferences: ExoPlayerPreferences ) : AudioEngine { - companion object { + public companion object { - suspend operator fun invoke( + public suspend operator fun invoke( application: Application, settingsResolver: SettingsResolver, dataSourceFactory: DataSource.Factory, @@ -120,30 +120,30 @@ class ExoPlayerEngine private constructor( } } - data class Configuration( + public data class Configuration( val positionRefreshRate: Hz = 2.0.hz, val seekBackwardIncrement: Duration = 15.seconds, val seekForwardIncrement: Duration = 30.seconds ) - data class Playlist( + public data class Playlist( val mediaMetadata: MediaMetadata, val duration: Duration?, val items: List ) { - data class Item( + public data class Item( val uri: String, val mediaMetadata: MediaMetadata, val duration: Duration? ) } - fun interface SettingsResolver { + public fun interface SettingsResolver { /** * Computes a set of engine settings from the engine preferences. */ - fun settings(preferences: ExoPlayerPreferences): ExoPlayerSettings + public fun settings(preferences: ExoPlayerPreferences): ExoPlayerSettings } private inner class Listener : Player.Listener { @@ -162,7 +162,7 @@ class ExoPlayerEngine private constructor( } } - data class Error(val error: ExoPlaybackException) : AudioEngine.Error + public data class Error(val error: ExoPlaybackException) : AudioEngine.Error private val coroutineScope: CoroutineScope = MainScope() diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngineProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngineProvider.kt index c3b3aaba60..4c4d0c0fa2 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngineProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerEngineProvider.kt @@ -16,7 +16,6 @@ import org.readium.r2.navigator.media3.api.MediaMetadataProvider import org.readium.r2.navigator.media3.audio.AudioEngineProvider import org.readium.r2.shared.ExperimentalReadiumApi import org.readium.r2.shared.publication.Locator -import org.readium.r2.shared.publication.Metadata import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.indexOfFirstWithHref @@ -28,7 +27,7 @@ import org.readium.r2.shared.publication.indexOfFirstWithHref */ @ExperimentalReadiumApi @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) -class ExoPlayerEngineProvider( +public class ExoPlayerEngineProvider( private val application: Application, private val metadataProvider: MediaMetadataProvider = DefaultMediaMetadataProvider(), private val defaults: ExoPlayerDefaults = ExoPlayerDefaults(), @@ -69,12 +68,6 @@ class ExoPlayerEngineProvider( ) } - override fun computeSettings( - metadata: Metadata, - preferences: ExoPlayerPreferences - ): ExoPlayerSettings = - ExoPlayerSettingsResolver(defaults).settings(preferences) - override fun createPreferenceEditor( publication: Publication, initialPreferences: ExoPlayerPreferences diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferences.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferences.kt index ce048b2a50..dd01b76aa5 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferences.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferences.kt @@ -17,7 +17,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi */ @ExperimentalReadiumApi @kotlinx.serialization.Serializable -data class ExoPlayerPreferences( +public data class ExoPlayerPreferences( val pitch: Double? = null, val speed: Double? = null, ) : Configurable.Preferences { diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesEditor.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesEditor.kt index ffe9d8f799..00727b833a 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesEditor.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesEditor.kt @@ -22,7 +22,7 @@ import org.readium.r2.shared.publication.Metadata * or ranges. */ @ExperimentalReadiumApi -class ExoPlayerPreferencesEditor( +public class ExoPlayerPreferencesEditor( initialPreferences: ExoPlayerPreferences, @Suppress("UNUSED_PARAMETER") publicationMetadata: Metadata, defaults: ExoPlayerDefaults, @@ -46,7 +46,7 @@ class ExoPlayerPreferencesEditor( updateValues { ExoPlayerPreferences() } } - val pitch: RangePreference = + public val pitch: RangePreference = RangePreferenceDelegate( getValue = { preferences.pitch }, getEffectiveValue = { state.settings.pitch }, @@ -57,7 +57,7 @@ class ExoPlayerPreferencesEditor( valueFormatter = { "${it.format(2)}x" }, ) - val speed: RangePreference = + public val speed: RangePreference = RangePreferenceDelegate( getValue = { preferences.speed }, getEffectiveValue = { state.settings.speed }, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesSerializer.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesSerializer.kt index aada34c11e..f4a46e0f96 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesSerializer.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerPreferencesSerializer.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * JSON serializer of [ExoPlayerPreferences]. */ @ExperimentalReadiumApi -class ExoPlayerPreferencesSerializer : PreferencesSerializer { +public class ExoPlayerPreferencesSerializer : PreferencesSerializer { override fun serialize(preferences: ExoPlayerPreferences): String = Json.encodeToString(ExoPlayerPreferences.serializer(), preferences) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerSettings.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerSettings.kt index e43425842d..ff57ca358b 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerSettings.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/exoplayer/ExoPlayerSettings.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @see ExoPlayerPreferences */ @ExperimentalReadiumApi -data class ExoPlayerSettings( +public data class ExoPlayerSettings( val pitch: Double, val speed: Double ) : Configurable.Settings diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/syncmedia/GuidedMediaNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/syncmedia/GuidedMediaNavigator.kt index 1c01c0c68b..7d02baf5c7 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/syncmedia/GuidedMediaNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/syncmedia/GuidedMediaNavigator.kt @@ -22,7 +22,7 @@ import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.util.Href @ExperimentalReadiumApi -class GuidedMediaNavigator>( +public class GuidedMediaNavigator>( private val audioNavigator: AudioNavigator, ) : MediaNavigator, @@ -31,7 +31,7 @@ class GuidedMediaNavigator { - data class Location( + public data class Location( override val href: Href, override val offset: Duration, val fragment: String, @@ -44,7 +44,7 @@ class GuidedMediaNavigator ) : TimeBasedMediaNavigator.ReadingOrder, TextAwareMediaNavigator.ReadingOrder { - data class Item( + public data class Item( val href: Href, override val duration: Duration? ) : TimeBasedMediaNavigator.ReadingOrder.Item, TextAwareMediaNavigator.ReadingOrder.Item diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsAliases.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsAliases.kt index 717a2e74c0..2aeacd1c2f 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsAliases.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsAliases.kt @@ -13,7 +13,7 @@ import org.readium.r2.navigator.media3.tts.android.AndroidTtsSettings import org.readium.r2.shared.ExperimentalReadiumApi @OptIn(ExperimentalReadiumApi::class) -typealias AndroidTtsNavigatorFactory = TtsNavigatorFactory +public typealias AndroidTtsNavigatorFactory = TtsNavigatorFactory @OptIn(ExperimentalReadiumApi::class) -typealias AndroidTtsNavigator = TtsNavigator +public typealias AndroidTtsNavigator = TtsNavigator diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngine.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngine.kt index b9124d1731..b866dd60ae 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngine.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngine.kt @@ -15,58 +15,58 @@ import org.readium.r2.shared.util.Language * A text-to-speech engine synthesizes text utterances (e.g. sentence). */ @ExperimentalReadiumApi -interface TtsEngine, +public interface TtsEngine, E : TtsEngine.Error, V : TtsEngine.Voice> : Configurable, Closeable { - interface Preferences

> : Configurable.Preferences

{ + public interface Preferences

> : Configurable.Preferences

{ /** * The default language to use when no language information is passed to [speak]. */ - val language: Language? + public val language: Language? } - interface Settings : Configurable.Settings { + public interface Settings : Configurable.Settings { /** * The default language to use when no language information is passed to [speak]. */ - val language: Language? + public val language: Language? /** * Whether language information in content should be superseded by [language]. */ - val overrideContentLanguage: Boolean + public val overrideContentLanguage: Boolean } - interface Voice { + public interface Voice { /** * The voice's language. */ - val language: Language + public val language: Language } /** * Marker interface for the errors that the [TtsEngine] returns. */ - interface Error + public interface Error /** * An id to identify a request to speak. */ @JvmInline - value class RequestId(val value: String) + public value class RequestId(public val value: String) /** * TTS engine callbacks. */ - interface Listener { + public interface Listener { /** * Called when the utterance with the given id starts as perceived by the caller. */ - fun onStart(requestId: RequestId) + public fun onStart(requestId: RequestId) /** * Called when the [TtsEngine] is about to speak the specified [range] of the utterance with @@ -74,48 +74,48 @@ interface TtsEngine, * * This callback may not be called if the [TtsEngine] does not provide range information. */ - fun onRange(requestId: RequestId, range: IntRange) + public fun onRange(requestId: RequestId, range: IntRange) /** * Called if the utterance with the given id has been stopped while in progress * by a call to [stop]. */ - fun onInterrupted(requestId: RequestId) + public fun onInterrupted(requestId: RequestId) /** * Called when the utterance with the given id has been flushed from the synthesis queue * by a call to [stop]. */ - fun onFlushed(requestId: RequestId) + public fun onFlushed(requestId: RequestId) /** * Called when the utterance with the given id has successfully completed processing. */ - fun onDone(requestId: RequestId) + public fun onDone(requestId: RequestId) /** * Called when an error has occurred during processing of the utterance with the given id. */ - fun onError(requestId: RequestId, error: E) + public fun onError(requestId: RequestId, error: E) } /** * Sets of voices available with this [TtsEngine]. */ - val voices: Set + public val voices: Set /** * Enqueues a new speak request. */ - fun speak(requestId: RequestId, text: String, language: Language?) + public fun speak(requestId: RequestId, text: String, language: Language?) /** * Stops the [TtsEngine]. */ - fun stop() + public fun stop() /** * Sets a new listener or removes the current one. */ - fun setListener(listener: Listener?) + public fun setListener(listener: Listener?) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngineProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngineProvider.kt index 5e1d26e580..e13059035a 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngineProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsEngineProvider.kt @@ -16,36 +16,39 @@ import org.readium.r2.shared.publication.Publication * To be implemented by adapters for third-party TTS engines which can be used with [TtsNavigator]. */ @ExperimentalReadiumApi -interface TtsEngineProvider, E : PreferencesEditor

, +public interface TtsEngineProvider, E : PreferencesEditor

, F : TtsEngine.Error, V : TtsEngine.Voice> { /** * Creates a [TtsEngine] for [publication] and [initialPreferences]. */ - suspend fun createEngine(publication: Publication, initialPreferences: P): TtsEngine? + public suspend fun createEngine(publication: Publication, initialPreferences: P): TtsEngine? /** * Creates a preferences editor for [publication] and [initialPreferences]. */ - fun createPreferencesEditor(publication: Publication, initialPreferences: P): E + public fun createPreferencesEditor(publication: Publication, initialPreferences: P): E /** * Creates an empty set of preferences of this TTS engine provider. */ - fun createEmptyPreferences(): P + public fun createEmptyPreferences(): P /** * Computes Media3 [PlaybackParameters] from the given [settings]. */ - fun getPlaybackParameters(settings: S): PlaybackParameters + public fun getPlaybackParameters(settings: S): PlaybackParameters /** * Updates [previousPreferences] to honor the given Media3 [playbackParameters]. */ - fun updatePlaybackParameters(previousPreferences: P, playbackParameters: PlaybackParameters): P + public fun updatePlaybackParameters( + previousPreferences: P, + playbackParameters: PlaybackParameters + ): P /** * Maps an engine-specific error to Media3 [PlaybackException]. */ - fun mapEngineError(error: F): PlaybackException + public fun mapEngineError(error: F): PlaybackException } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt index 0c0dc5264d..257149fff0 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigator.kt @@ -34,7 +34,7 @@ import org.readium.r2.shared.util.tokenizer.TextTokenizer * A navigator to read aloud a [Publication] with a TTS engine. */ @ExperimentalReadiumApi -class TtsNavigator, +public class TtsNavigator, E : TtsEngine.Error, V : TtsEngine.Voice> private constructor( coroutineScope: CoroutineScope, override val publication: Publication, @@ -46,9 +46,9 @@ class TtsNavigator, Media3Adapter, Configurable { - companion object { + public companion object { - suspend operator fun , + public suspend operator fun , E : TtsEngine.Error, V : TtsEngine.Voice> invoke( application: Application, publication: Publication, @@ -125,12 +125,12 @@ class TtsNavigator, } } - interface Listener { + public interface Listener { - fun onStopRequested() + public fun onStopRequested() } - data class Location( + public data class Location( override val href: Href, override val utterance: String, override val range: IntRange?, @@ -140,7 +140,7 @@ class TtsNavigator, override val tokenLocator: Locator?, ) : TextAwareMediaNavigator.Location - data class Playback( + public data class Playback( override val state: MediaNavigator.State, override val playWhenReady: Boolean, override val index: Int, @@ -148,30 +148,30 @@ class TtsNavigator, override val range: IntRange?, ) : TextAwareMediaNavigator.Playback - data class ReadingOrder( + public data class ReadingOrder( override val items: List ) : TextAwareMediaNavigator.ReadingOrder { - data class Item( + public data class Item( val href: Href ) : TextAwareMediaNavigator.ReadingOrder.Item } - sealed class State { + public sealed class State { - object Ready : MediaNavigator.State.Ready + public object Ready : MediaNavigator.State.Ready - object Ended : MediaNavigator.State.Ended + public object Ended : MediaNavigator.State.Ended - sealed class Error : MediaNavigator.State.Error { + public sealed class Error : MediaNavigator.State.Error { - data class EngineError (val error: E) : Error() + public data class EngineError (val error: E) : Error() - data class ContentError(val exception: Exception) : Error() + public data class ContentError(val exception: Exception) : Error() } } - val voices: Set get() = + public val voices: Set get() = player.voices override val readingOrder: ReadingOrder = @@ -197,7 +197,7 @@ class TtsNavigator, player.pause() } - fun go(locator: Locator) { + public fun go(locator: Locator) { player.go(locator) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigatorFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigatorFactory.kt index 7005a748fe..879bea99ba 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigatorFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/TtsNavigatorFactory.kt @@ -24,7 +24,7 @@ import org.readium.r2.shared.util.tokenizer.TextTokenizer import org.readium.r2.shared.util.tokenizer.TextUnit @ExperimentalReadiumApi -class TtsNavigatorFactory, E : PreferencesEditor

, +public class TtsNavigatorFactory, E : PreferencesEditor

, F : TtsEngine.Error, V : TtsEngine.Voice> private constructor( private val application: Application, private val publication: Publication, @@ -32,9 +32,9 @@ class TtsNavigatorFactory, private val tokenizerFactory: (language: Language?) -> TextTokenizer, private val metadataProvider: MediaMetadataProvider ) { - companion object { + public companion object { - suspend operator fun invoke( + public suspend operator fun invoke( application: Application, publication: Publication, tokenizerFactory: (language: Language?) -> TextTokenizer = defaultTokenizerFactory, @@ -58,7 +58,7 @@ class TtsNavigatorFactory, ) } - suspend operator fun , E : PreferencesEditor

, + public suspend operator fun , E : PreferencesEditor

, F : TtsEngine.Error, V : TtsEngine.Voice> invoke( application: Application, publication: Publication, @@ -113,7 +113,7 @@ class TtsNavigatorFactory, { _, _ -> null } } - suspend fun createNavigator( + public suspend fun createNavigator( listener: TtsNavigator.Listener, initialLocator: Locator? = null, initialPreferences: P? = null, @@ -130,6 +130,6 @@ class TtsNavigatorFactory, ) } - fun createPreferencesEditor(preferences: P): E = + public fun createPreferencesEditor(preferences: P): E = ttsEngineProvider.createPreferencesEditor(publication, preferences) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsDefaults.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsDefaults.kt index a46e75eb7b..abdfa3b7db 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsDefaults.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsDefaults.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.util.Language * @see AndroidTtsPreferences */ @ExperimentalReadiumApi -data class AndroidTtsDefaults( +public data class AndroidTtsDefaults( val language: Language? = null, val pitch: Double? = null, val speed: Double? = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngine.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngine.kt index f909547422..45207578be 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngine.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngine.kt @@ -36,7 +36,7 @@ import org.readium.r2.shared.util.Language * Default [TtsEngine] implementation using Android's native text to speech engine. */ @ExperimentalReadiumApi -class AndroidTtsEngine private constructor( +public class AndroidTtsEngine private constructor( private val context: Context, engine: TextToSpeech, private val settingsResolver: SettingsResolver, @@ -46,9 +46,9 @@ class AndroidTtsEngine private constructor( ) : TtsEngine { - companion object { + public companion object { - suspend operator fun invoke( + public suspend operator fun invoke( context: Context, settingsResolver: SettingsResolver, voiceSelector: VoiceSelector, @@ -88,7 +88,7 @@ class AndroidTtsEngine private constructor( * Starts the activity to install additional voice data. */ @SuppressLint("QueryPermissionsNeeded") - fun requestInstallVoice(context: Context) { + public fun requestInstallVoice(context: Context) { val intent = Intent() .setAction(Engine.ACTION_INSTALL_TTS_DATA) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) @@ -125,47 +125,47 @@ class AndroidTtsEngine private constructor( ) } - fun interface SettingsResolver { + public fun interface SettingsResolver { /** * Computes a set of engine settings from the engine preferences. */ - fun settings(preferences: AndroidTtsPreferences): AndroidTtsSettings + public fun settings(preferences: AndroidTtsPreferences): AndroidTtsSettings } - fun interface VoiceSelector { + public fun interface VoiceSelector { /** * Selects a voice for the given [language]. */ - fun voice(language: Language?, availableVoices: Set): Voice? + public fun voice(language: Language?, availableVoices: Set): Voice? } - sealed class Error : TtsEngine.Error { + public sealed class Error : TtsEngine.Error { /** Denotes a generic operation failure. */ - object Unknown : Error() + public object Unknown : Error() /** Denotes a failure caused by an invalid request. */ - object InvalidRequest : Error() + public object InvalidRequest : Error() /** Denotes a failure caused by a network connectivity problems. */ - object Network : Error() + public object Network : Error() /** Denotes a failure caused by network timeout. */ - object NetworkTimeout : Error() + public object NetworkTimeout : Error() /** Denotes a failure caused by an unfinished download of the voice data. */ - object NotInstalledYet : Error() + public object NotInstalledYet : Error() /** Denotes a failure related to the output (audio device or a file). */ - object Output : Error() + public object Output : Error() /** Denotes a failure of a TTS service. */ - object Service : Error() + public object Service : Error() /** Denotes a failure of a TTS engine to synthesize the given input. */ - object Synthesis : Error() + public object Synthesis : Error() /** * Denotes the language data is missing. @@ -173,13 +173,13 @@ class AndroidTtsEngine private constructor( * You can open the Android settings to install the missing data with: * AndroidTtsEngine.requestInstallVoice(context) */ - data class LanguageMissingData(val language: Language) : Error() + public data class LanguageMissingData(val language: Language) : Error() /** * Android's TTS error code. * See https://developer.android.com/reference/android/speech/tts/TextToSpeech#ERROR */ - companion object { + public companion object { internal fun fromNativeError(code: Int): Error = when (code) { ERROR_INVALID_REQUEST -> InvalidRequest @@ -202,7 +202,7 @@ class AndroidTtsEngine private constructor( * @param quality Voice quality. * @param requiresNetwork Indicates whether using this voice requires an Internet connection. */ - data class Voice( + public data class Voice( val id: Id, override val language: Language, val quality: Quality = Quality.Normal, @@ -211,9 +211,9 @@ class AndroidTtsEngine private constructor( @kotlinx.serialization.Serializable @JvmInline - value class Id(val value: String) + public value class Id(public val value: String) - enum class Quality { + public enum class Quality { Lowest, Low, Normal, High, Highest } } @@ -467,7 +467,7 @@ class AndroidTtsEngine private constructor( listener?.onDone(TtsEngine.RequestId(utteranceId)) } - @Deprecated("Deprecated in the interface", ReplaceWith("onError(utteranceId, -1)")) + @Deprecated("Deprecated in the interface", ReplaceWith("onError(utteranceId, -1)"), level = DeprecationLevel.ERROR) override fun onError(utteranceId: String) { onError(utteranceId, -1) } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngineProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngineProvider.kt index cc01c650e6..5bf0114bed 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngineProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsEngineProvider.kt @@ -12,12 +12,11 @@ import androidx.media3.common.PlaybackException.* import androidx.media3.common.PlaybackParameters import org.readium.r2.navigator.media3.tts.TtsEngineProvider import org.readium.r2.shared.ExperimentalReadiumApi -import org.readium.r2.shared.publication.Metadata import org.readium.r2.shared.publication.Publication @ExperimentalReadiumApi @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) -class AndroidTtsEngineProvider( +public class AndroidTtsEngineProvider( private val context: Context, private val defaults: AndroidTtsDefaults = AndroidTtsDefaults(), private val voiceSelector: AndroidTtsEngine.VoiceSelector = AndroidTtsEngine.VoiceSelector { _, _ -> null } @@ -39,12 +38,6 @@ class AndroidTtsEngineProvider( ) } - fun computeSettings( - metadata: Metadata, - preferences: AndroidTtsPreferences - ): AndroidTtsSettings = - AndroidTtsSettingsResolver(metadata, defaults).settings(preferences) - override fun createPreferencesEditor( publication: Publication, initialPreferences: AndroidTtsPreferences diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferences.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferences.kt index b397d3712c..8fc062db7d 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferences.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferences.kt @@ -21,7 +21,7 @@ import org.readium.r2.shared.util.Language */ @ExperimentalReadiumApi @Serializable -data class AndroidTtsPreferences( +public data class AndroidTtsPreferences( override val language: Language? = null, val pitch: Double? = null, val speed: Double? = null, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesEditor.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesEditor.kt index b8a47e159e..1c80f75a50 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesEditor.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesEditor.kt @@ -20,7 +20,7 @@ import org.readium.r2.shared.util.Language * or ranges. */ @ExperimentalReadiumApi -class AndroidTtsPreferencesEditor( +public class AndroidTtsPreferencesEditor( initialPreferences: AndroidTtsPreferences, publicationMetadata: Metadata, defaults: AndroidTtsDefaults, @@ -44,7 +44,7 @@ class AndroidTtsPreferencesEditor( updateValues { AndroidTtsPreferences() } } - val language: Preference = + public val language: Preference = PreferenceDelegate( getValue = { preferences.language }, getEffectiveValue = { state.settings.language }, @@ -52,7 +52,7 @@ class AndroidTtsPreferencesEditor( updateValue = { value -> updateValues { it.copy(language = value) } }, ) - val pitch: RangePreference = + public val pitch: RangePreference = RangePreferenceDelegate( getValue = { preferences.pitch }, getEffectiveValue = { state.settings.pitch }, @@ -63,7 +63,7 @@ class AndroidTtsPreferencesEditor( valueFormatter = { "${it.format(2)}x" }, ) - val speed: RangePreference = + public val speed: RangePreference = RangePreferenceDelegate( getValue = { preferences.speed }, getEffectiveValue = { state.settings.speed }, @@ -74,7 +74,7 @@ class AndroidTtsPreferencesEditor( valueFormatter = { "${it.format(2)}x" }, ) - val voices: Preference> = + public val voices: Preference> = PreferenceDelegate( getValue = { preferences.voices }, getEffectiveValue = { state.settings.voices }, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesFilters.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesFilters.kt index 971bcd6f52..fa70124637 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesFilters.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesFilters.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * Suggested filter to keep only shared [AndroidTtsPreferences]. */ @ExperimentalReadiumApi -object AndroidTtsSharedPreferencesFilter : PreferencesFilter { +public object AndroidTtsSharedPreferencesFilter : PreferencesFilter { override fun filter(preferences: AndroidTtsPreferences): AndroidTtsPreferences = preferences.copy( @@ -25,7 +25,7 @@ object AndroidTtsSharedPreferencesFilter : PreferencesFilter { +public object AndroidTtsPublicationPreferencesFilter : PreferencesFilter { override fun filter(preferences: AndroidTtsPreferences): AndroidTtsPreferences = AndroidTtsPreferences( diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesSerializer.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesSerializer.kt index e6e0b948b2..3e8df9c750 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesSerializer.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsPreferencesSerializer.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * JSON serializer of [AndroidTtsPreferences]. */ @ExperimentalReadiumApi -class AndroidTtsPreferencesSerializer : PreferencesSerializer { +public class AndroidTtsPreferencesSerializer : PreferencesSerializer { override fun serialize(preferences: AndroidTtsPreferences): String = Json.encodeToString(AndroidTtsPreferences.serializer(), preferences) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsSettings.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsSettings.kt index 4f0542fd04..b39ec92288 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsSettings.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/media3/tts/android/AndroidTtsSettings.kt @@ -16,7 +16,7 @@ import org.readium.r2.shared.util.Language * @see AndroidTtsPreferences */ @ExperimentalReadiumApi -data class AndroidTtsSettings( +public data class AndroidTtsSettings( override val language: Language, override val overrideContentLanguage: Boolean, val pitch: Double, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/DelegatingPagerAdapter.java b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/DelegatingPagerAdapter.java index ef34b16c21..32f0d17e35 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/DelegatingPagerAdapter.java +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/DelegatingPagerAdapter.java @@ -24,7 +24,7 @@ import androidx.annotation.NonNull; import androidx.viewpager.widget.PagerAdapter; -public class DelegatingPagerAdapter extends PagerAdapter { +class DelegatingPagerAdapter extends PagerAdapter { private final PagerAdapter mDelegate; diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2CbzPageFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2CbzPageFragment.kt index e1528268f8..0665502f03 100755 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2CbzPageFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2CbzPageFragment.kt @@ -26,7 +26,7 @@ import org.readium.r2.navigator.databinding.ReadiumNavigatorViewpagerFragmentCbz import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Publication -class R2CbzPageFragment( +internal class R2CbzPageFragment( private val publication: Publication, private val onTapListener: (Float, Float) -> Unit ) : diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt index f348581219..898c03cb91 100755 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt @@ -42,7 +42,7 @@ import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Locator @OptIn(ExperimentalReadiumApi::class) -class R2EpubPageFragment : Fragment() { +internal class R2EpubPageFragment : Fragment() { private val resourceUrl: String? get() = requireArguments().getString("url") diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FXLPageFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FXLPageFragment.kt index 48843a275d..ae015c2e30 100755 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FXLPageFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FXLPageFragment.kt @@ -29,7 +29,7 @@ import org.readium.r2.navigator.epub.EpubNavigatorViewModel import org.readium.r2.navigator.epub.fxl.R2FXLLayout import org.readium.r2.navigator.epub.fxl.R2FXLOnDoubleTapListener -class R2FXLPageFragment : Fragment() { +internal class R2FXLPageFragment : Fragment() { private val firstResourceUrl: String? get() = requireArguments().getString("firstUrl") diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FragmentPagerAdapter.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FragmentPagerAdapter.kt index e213b8a055..f58f52fb89 100755 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FragmentPagerAdapter.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FragmentPagerAdapter.kt @@ -20,7 +20,7 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentTransaction import androidx.viewpager.widget.PagerAdapter -abstract class R2FragmentPagerAdapter(private val mFragmentManager: FragmentManager) : androidx.fragment.app.FragmentStatePagerAdapter(mFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { +internal abstract class R2FragmentPagerAdapter(private val mFragmentManager: FragmentManager) : androidx.fragment.app.FragmentStatePagerAdapter(mFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { val mFragments = LongSparseArray() private val mSavedStates = LongSparseArray() diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2PagerAdapter.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2PagerAdapter.kt index 0e5b7934a4..37836c1ebb 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2PagerAdapter.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2PagerAdapter.kt @@ -19,7 +19,7 @@ import androidx.fragment.app.FragmentManager import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Locator -class R2PagerAdapter internal constructor( +internal class R2PagerAdapter internal constructor( val fm: FragmentManager, private val resources: List ) : R2FragmentPagerAdapter(fm) { diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2RTLViewPager.java b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2RTLViewPager.java index cb0f7a91db..6c2b00e143 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2RTLViewPager.java +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2RTLViewPager.java @@ -35,7 +35,7 @@ import java.util.HashMap; - /** +/** * RtlViewPager is an API-compatible implementation of ViewPager which * orders paged views according to the layout direction of the view. In left to right mode, the * first view is at the left side of the carousel, and in right to left mode it is at the right @@ -45,8 +45,7 @@ * OnPageChangeListeners so that clients can be agnostic to layout direction and * modifications are kept internal to RtlViewPager. */ -@ExperimentalReadiumApi -public class R2RTLViewPager extends ViewPager { +class R2RTLViewPager extends ViewPager { public ReadingProgression direction = ReadingProgression.LTR; private int mLayoutDirection = ViewCompat.LAYOUT_DIRECTION_LTR; private HashMap mPageChangeListeners = new HashMap<>(); diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2ViewPager.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2ViewPager.kt index d380f20550..571160e495 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2ViewPager.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2ViewPager.kt @@ -13,10 +13,9 @@ import android.content.Context import android.util.AttributeSet import android.view.MotionEvent import org.readium.r2.navigator.BuildConfig.DEBUG -import org.readium.r2.shared.publication.Publication import timber.log.Timber -class R2ViewPager : R2RTLViewPager { +internal class R2ViewPager : R2RTLViewPager { internal enum class PublicationType { EPUB, CBZ, FXL, WEBPUB, AUDIO, DiViNa @@ -25,7 +24,7 @@ class R2ViewPager : R2RTLViewPager { internal lateinit var publicationType: PublicationType @Deprecated(message = "You shouldn't be using these internals.", level = DeprecationLevel.ERROR) - lateinit var type: Publication.TYPE + val type = Unit constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet) : super(context, attrs) diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/RtlViewPager.java b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/RtlViewPager.java index d18dc86228..30fd3b6f85 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/RtlViewPager.java +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/RtlViewPager.java @@ -40,7 +40,7 @@ * OnPageChangeListeners so that clients can be agnostic to layout direction and * modifications are kept internal to RtlViewPager. */ -public class RtlViewPager extends ViewPager { +class RtlViewPager extends ViewPager { private final HashMap mPageChangeListeners = new HashMap<>(); private int mLayoutDirection = ViewCompat.LAYOUT_DIRECTION_LTR; diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/Deprecated.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/Deprecated.kt index f54bf22927..6808d89a24 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/Deprecated.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/Deprecated.kt @@ -12,7 +12,7 @@ package org.readium.r2.navigator.pdf import androidx.appcompat.app.AppCompatActivity @Deprecated("Use `PdfNavigatorFragment` in your own activity instead", level = DeprecationLevel.ERROR) -abstract class R2PdfActivity : AppCompatActivity() +public abstract class R2PdfActivity : AppCompatActivity() // This is for lint to pass. private val fake = null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfEngineProvider.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfEngineProvider.kt index addb6e00a7..44eacce190 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfEngineProvider.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfEngineProvider.kt @@ -21,64 +21,64 @@ import org.readium.r2.shared.resource.Resource * To be implemented by adapters for third-party PDF engines which can be used with [PdfNavigatorFragment]. */ @ExperimentalReadiumApi -interface PdfEngineProvider, E : PreferencesEditor

> { +public interface PdfEngineProvider, E : PreferencesEditor

> { /** * Creates a [PdfDocumentFragment] for [input]. */ - suspend fun createDocumentFragment(input: PdfDocumentFragmentInput): PdfDocumentFragment + public suspend fun createDocumentFragment(input: PdfDocumentFragmentInput): PdfDocumentFragment /** * Creates settings for [metadata] and [preferences]. */ - fun computeSettings(metadata: Metadata, preferences: P): S + public fun computeSettings(metadata: Metadata, preferences: P): S /** * Infers a [VisualNavigator.Presentation] from settings. */ - fun computePresentation(settings: S): VisualNavigator.Presentation + public fun computePresentation(settings: S): VisualNavigator.Presentation /** * Creates a preferences editor for [publication] and [initialPreferences]. */ - fun createPreferenceEditor(publication: Publication, initialPreferences: P): E + public fun createPreferenceEditor(publication: Publication, initialPreferences: P): E /** * Creates an empty set of preferences of this PDF engine provider. */ - fun createEmptyPreferences(): P + public fun createEmptyPreferences(): P } @ExperimentalReadiumApi -typealias PdfDocumentFragmentFactory = suspend (PdfDocumentFragmentInput) -> PdfDocumentFragment +public typealias PdfDocumentFragmentFactory = suspend (PdfDocumentFragmentInput) -> PdfDocumentFragment /** * A [PdfDocumentFragment] renders a single PDF resource. */ @ExperimentalReadiumApi -abstract class PdfDocumentFragment : Fragment() { +public abstract class PdfDocumentFragment : Fragment() { - interface Listener { + public interface Listener { /** * Called when the fragment navigates to a different page. */ - fun onPageChanged(pageIndex: Int) + public fun onPageChanged(pageIndex: Int) /** * Called when the user triggers a tap on the document. */ - fun onTap(point: PointF): Boolean + public fun onTap(point: PointF): Boolean /** * Called when the PDF engine fails to load the PDF document. */ - fun onResourceLoadFailed(link: Link, error: Resource.Exception) + public fun onResourceLoadFailed(link: Link, error: Resource.Exception) } /** * Returns the current page index in the document, from 0. */ - abstract val pageIndex: Int + public abstract val pageIndex: Int /** * Jumps to the given page [index]. @@ -86,16 +86,16 @@ abstract class PdfDocumentFragment : Fragment() { * @param animated Indicates if the transition should be animated. * @return Whether the jump is valid. */ - abstract fun goToPageIndex(index: Int, animated: Boolean): Boolean + public abstract fun goToPageIndex(index: Int, animated: Boolean): Boolean /** * Current settings for the PDF document. */ - abstract var settings: S + public abstract var settings: S } @ExperimentalReadiumApi -data class PdfDocumentFragmentInput( +public data class PdfDocumentFragmentInput( val publication: Publication, val link: Link, val initialPageIndex: Int, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFactory.kt index 6522ff8825..d195bac703 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorFactory.kt @@ -21,7 +21,7 @@ import org.readium.r2.shared.publication.Publication * @param pdfEngineProvider provider for third-party PDF engine adapter. */ @ExperimentalReadiumApi -class PdfNavigatorFactory, E : PreferencesEditor

>( +public class PdfNavigatorFactory, E : PreferencesEditor

>( private val publication: Publication, private val pdfEngineProvider: PdfEngineProvider ) { @@ -35,7 +35,7 @@ class PdfNavigatorFactory> internal constructor( +public class PdfNavigatorFragment> internal constructor( override val publication: Publication, initialLocator: Locator? = null, initialPreferences: P, @@ -68,15 +68,15 @@ class PdfNavigatorFragment ) : Fragment(), VisualNavigator, Configurable { - interface Listener : VisualNavigator.Listener { + public interface Listener : VisualNavigator.Listener { /** * Called when a PDF resource failed to be loaded, for example because of an [OutOfMemoryError]. */ - fun onResourceLoadFailed(link: Link, error: Resource.Exception) {} + public fun onResourceLoadFailed(link: Link, error: Resource.Exception) {} } - companion object { + public companion object { /** * Creates a factory for [PdfNavigatorFragment]. @@ -89,7 +89,7 @@ class PdfNavigatorFragment, E : PreferencesEditor

> createFactory( + public fun , E : PreferencesEditor

> createFactory( publication: Publication, initialLocator: Locator? = null, preferences: P? = null, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Configurable.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Configurable.kt index 62f1ffb176..6006b1a372 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Configurable.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Configurable.kt @@ -15,30 +15,30 @@ import org.readium.r2.shared.ExperimentalReadiumApi * A [Configurable] is a component with a set of configurable [Settings]. */ @ExperimentalReadiumApi -interface Configurable> { +public interface Configurable> { /** * Marker interface for the [Settings] properties holder. */ - interface Settings + public interface Settings /** * Marker interface for the [Preferences] properties holder. */ - interface Preferences

> { + public interface Preferences

> { /** * Creates a new instance of [P] after merging the values of [other]. * * In case of conflict, [other] takes precedence. */ - operator fun plus(other: P): P + public operator fun plus(other: P): P } /** * Current [Settings] values. */ - val settings: StateFlow + public val settings: StateFlow /** * Submits a new set of [Preferences] to update the current [Settings]. @@ -46,24 +46,24 @@ interface Configurable> { * Note that the [Configurable] might not update its [settings] right away, or might even ignore * some of the provided preferences. They are only used as hints to compute the new settings. */ - fun submitPreferences(preferences: P) + public fun submitPreferences(preferences: P) } /** * JSON serializer of [P]. */ @ExperimentalReadiumApi -interface PreferencesSerializer

> { +public interface PreferencesSerializer

> { /** * Serialize [P] into a JSON string. */ - fun serialize(preferences: P): String + public fun serialize(preferences: P): String /** * Deserialize [P] from a JSON string. */ - fun deserialize(preferences: String): P + public fun deserialize(preferences: String): P } /** @@ -72,30 +72,30 @@ interface PreferencesSerializer

> { * This can be used as a helper for a user preferences screen. */ @ExperimentalReadiumApi -interface PreferencesEditor

> { +public interface PreferencesEditor

> { /** * The current preferences. */ - val preferences: P + public val preferences: P /** * Unset all preferences. */ - fun clear() + public fun clear() } /** * A filter to keep only some preferences and filter out some others. */ @ExperimentalReadiumApi -fun interface PreferencesFilter

> { +public fun interface PreferencesFilter

> { - fun filter(preferences: P): P + public fun filter(preferences: P): P } @ExperimentalReadiumApi -operator fun

> PreferencesFilter

.plus(other: PreferencesFilter

): PreferencesFilter

= +public operator fun

> PreferencesFilter

.plus(other: PreferencesFilter

): PreferencesFilter

= CombinedPreferencesFilter(this, other) @ExperimentalReadiumApi diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/MappedPreference.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/MappedPreference.kt index 163855a102..a1dd3a976e 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/MappedPreference.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/MappedPreference.kt @@ -7,21 +7,21 @@ import org.readium.r2.shared.ExperimentalReadiumApi * the target type [V]. */ @ExperimentalReadiumApi -fun Preference.map(from: (T) -> V, to: (V) -> T): Preference = +public fun Preference.map(from: (T) -> V, to: (V) -> T): Preference = MappedPreference(this, from, to) /** * Creates a new [EnumPreference] object wrapping the receiver with the provided [supportedValues]. */ @ExperimentalReadiumApi -fun Preference.withSupportedValues(vararg supportedValues: T): EnumPreference = +public fun Preference.withSupportedValues(vararg supportedValues: T): EnumPreference = withSupportedValues(supportedValues.toList()) /** * Creates a new [EnumPreference] object wrapping the receiver with the provided [supportedValues]. */ @ExperimentalReadiumApi -fun Preference.withSupportedValues(supportedValues: List): EnumPreference = +public fun Preference.withSupportedValues(supportedValues: List): EnumPreference = PreferenceWithSupportedValues(this, supportedValues) /** @@ -29,7 +29,7 @@ fun Preference.withSupportedValues(supportedValues: List): EnumPrefere * [supportedValues], [from] and [to] the target type [V]. */ @ExperimentalReadiumApi -fun EnumPreference.map( +public fun EnumPreference.map( from: (T) -> V, to: (V) -> T, supportedValues: (List) -> List = { it.map(from) } @@ -40,14 +40,14 @@ fun EnumPreference.map( * Creates a new [EnumPreference] object wrapping the receiver with the provided [supportedValues]. */ @ExperimentalReadiumApi -fun EnumPreference.withSupportedValues(vararg supportedValues: T): EnumPreference = +public fun EnumPreference.withSupportedValues(vararg supportedValues: T): EnumPreference = withSupportedValues(supportedValues.toList()) /** * Creates a new [EnumPreference] object wrapping the receiver with the provided [supportedValues]. */ @ExperimentalReadiumApi -fun EnumPreference.withSupportedValues(supportedValues: List): EnumPreference = +public fun EnumPreference.withSupportedValues(supportedValues: List): EnumPreference = map(from = { it }, to = { it }, supportedValues = { supportedValues }) /** @@ -55,7 +55,7 @@ fun EnumPreference.withSupportedValues(supportedValues: List): EnumPre * values with [transform]. */ @ExperimentalReadiumApi -fun EnumPreference.mapSupportedValues(transform: (List) -> List): EnumPreference = +public fun EnumPreference.mapSupportedValues(transform: (List) -> List): EnumPreference = map(from = { it }, to = { it }, supportedValues = transform) /** @@ -65,7 +65,7 @@ fun EnumPreference.mapSupportedValues(transform: (List) -> List): E * The value formatter, or [increment] and [decrement] strategy of the receiver can be overwritten. */ @ExperimentalReadiumApi -fun , V : Comparable> RangePreference.map( +public fun , V : Comparable> RangePreference.map( from: (T) -> V, to: (V) -> T, supportedRange: (ClosedRange) -> ClosedRange = { from(it.start)..from(it.endInclusive) }, @@ -86,7 +86,7 @@ fun , V : Comparable> RangePreference.map( * [supportedRange], or overwriting its [formatValue] or [increment] and [decrement] strategy. */ @ExperimentalReadiumApi -fun > RangePreference.map( +public fun > RangePreference.map( supportedRange: (ClosedRange) -> ClosedRange = { it }, formatValue: ((T) -> String)? = null, increment: (RangePreference.() -> Unit)? = null, @@ -106,7 +106,7 @@ fun > RangePreference.map( * and decrement. */ @ExperimentalReadiumApi -fun > RangePreference.withSupportedRange( +public fun > RangePreference.withSupportedRange( range: ClosedRange = supportedRange, progressionStrategy: ProgressionStrategy ): RangePreference = diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Preference.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Preference.kt index 0788520078..fd74422f10 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Preference.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Preference.kt @@ -13,44 +13,45 @@ import org.readium.r2.shared.ExperimentalReadiumApi * which value the [Configurable] will effectively use. */ @ExperimentalReadiumApi -interface Preference { +public interface Preference { /** * The current value of the preference. */ - val value: T? + public val value: T? /** * The value that will be effectively used by the navigator * if preferences are submitted as they are. */ - val effectiveValue: T + public val effectiveValue: T /** * If this preference will be effectively used by the navigator * if preferences are submitted as they are. */ - val isEffective: Boolean + public val isEffective: Boolean /** * Set the preference to [value]. A null value means unsetting the preference. */ - fun set(value: T?) + public fun set(value: T?) } /** * Unset the preference. */ @ExperimentalReadiumApi -fun Preference.clear() = +public fun Preference.clear() { set(null) +} /** * Toggle the preference value. A default value is taken as the initial one if * the preference is currently unset. */ @OptIn(ExperimentalReadiumApi::class) -fun Preference.toggle() { +public fun Preference.toggle() { set(!(value ?: effectiveValue)) } @@ -58,40 +59,40 @@ fun Preference.toggle() { * Returns a new preference with its boolean value flipped. */ @OptIn(ExperimentalReadiumApi::class) -fun Preference.flipped(): Preference = +public fun Preference.flipped(): Preference = map(from = { !it }, to = { !it }) /** * A [Preference] which accepts a closed set of values. */ @ExperimentalReadiumApi -interface EnumPreference : Preference { +public interface EnumPreference : Preference { /** * List of valid values for this preference. */ - val supportedValues: List + public val supportedValues: List } /** * A [Preference] whose values must be in a [ClosedRange] of [T]. */ @ExperimentalReadiumApi -interface RangePreference> : Preference { +public interface RangePreference> : Preference { - val supportedRange: ClosedRange + public val supportedRange: ClosedRange /** * Increment the preference value from its current value or a default value. */ - fun increment() + public fun increment() /** * Decrement the preference value from its current value or a default value. */ - fun decrement() + public fun decrement() /** * Format [value] in a way suitable for display, including unit if relevant. */ - fun formatValue(value: T): String + public fun formatValue(value: T): String } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/PreferenceDelegate.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/PreferenceDelegate.kt index 66c45882b2..ff9915f5d8 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/PreferenceDelegate.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/PreferenceDelegate.kt @@ -12,7 +12,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi import org.readium.r2.shared.InternalReadiumApi @InternalReadiumApi -open class PreferenceDelegate( +public open class PreferenceDelegate( private val getValue: () -> T?, private val getEffectiveValue: () -> T, private val getIsEffective: () -> Boolean, @@ -28,12 +28,13 @@ open class PreferenceDelegate( override val isEffective: Boolean get() = getIsEffective() - override fun set(value: T?) = + public override fun set(value: T?) { updateValue(value) + } } @InternalReadiumApi -class EnumPreferenceDelegate( +public class EnumPreferenceDelegate( getValue: () -> T?, getEffectiveValue: () -> T, getIsEffective: () -> Boolean, @@ -49,7 +50,7 @@ class EnumPreferenceDelegate( } @InternalReadiumApi -class RangePreferenceDelegate>( +public class RangePreferenceDelegate>( getValue: () -> T?, getEffectiveValue: () -> T, getIsEffective: () -> Boolean, diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/ProgressionStrategy.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/ProgressionStrategy.kt index 04bcc633e0..b8eca01445 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/ProgressionStrategy.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/ProgressionStrategy.kt @@ -11,11 +11,11 @@ import org.readium.r2.shared.extensions.equalsDelta /** * A strategy to increment or decrement a setting. */ -interface ProgressionStrategy { +public interface ProgressionStrategy { - fun increment(value: V): V + public fun increment(value: V): V - fun decrement(value: V): V + public fun decrement(value: V): V } /** @@ -25,19 +25,19 @@ interface ProgressionStrategy { * * @param equalsDelta Provide an equality algorithm to compare floating point numbers. */ -class StepsProgression>( +public class StepsProgression>( private val steps: List, private val equalsDelta: (T, T) -> Boolean ) : ProgressionStrategy { - companion object { - operator fun invoke(vararg steps: Int): StepsProgression = + public companion object { + public operator fun invoke(vararg steps: Int): StepsProgression = StepsProgression(steps = steps.toList(), equalsDelta = Int::equals) - operator fun invoke(vararg steps: Float): StepsProgression = + public operator fun invoke(vararg steps: Float): StepsProgression = StepsProgression(steps = steps.toList(), equalsDelta = { a, b -> a.equalsDelta(b) }) - operator fun invoke(vararg steps: Double): StepsProgression = + public operator fun invoke(vararg steps: Double): StepsProgression = StepsProgression(steps = steps.toList(), equalsDelta = { a, b -> a.equalsDelta(b) }) } @@ -56,7 +56,7 @@ class StepsProgression>( * Simple progression strategy which increments or decrements the setting * by a fixed number. */ -class IntIncrement(private val increment: Int) : ProgressionStrategy { +public class IntIncrement(private val increment: Int) : ProgressionStrategy { override fun increment(value: Int): Int = value + increment @@ -67,7 +67,7 @@ class IntIncrement(private val increment: Int) : ProgressionStrategy { * Simple progression strategy which increments or decrements the setting * by a fixed number. */ -class DoubleIncrement(private val increment: Double) : ProgressionStrategy { +public class DoubleIncrement(private val increment: Double) : ProgressionStrategy { override fun increment(value: Double): Double = value + increment diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Types.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Types.kt index 627bbe1ed6..74ff7a9e5e 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Types.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/preferences/Types.kt @@ -24,7 +24,10 @@ import org.readium.r2.shared.ExperimentalReadiumApi @ExperimentalReadiumApi @Serializable -enum class Theme(@ColorInt val contentColor: Int, @ColorInt val backgroundColor: Int) { +public enum class Theme( + @ColorInt public val contentColor: Int, + @ColorInt public val backgroundColor: Int +) { @SerialName("light") LIGHT(contentColor = dayContentColor, backgroundColor = dayBackgroundColor), @SerialName("dark") DARK(contentColor = nightContentColor, backgroundColor = nightBackgroundColor), @SerialName("sepia") SEPIA(contentColor = sepiaContentColor, backgroundColor = sepiaBackgroundColor); @@ -32,7 +35,7 @@ enum class Theme(@ColorInt val contentColor: Int, @ColorInt val backgroundColor: @ExperimentalReadiumApi @Serializable -enum class TextAlign { +public enum class TextAlign { /** Align the text in the center of the page. */ @SerialName("center") CENTER, /** Stretch lines of text that end with a soft line break to fill the width of the page. */ @@ -49,7 +52,7 @@ enum class TextAlign { @ExperimentalReadiumApi @Serializable -enum class ColumnCount { +public enum class ColumnCount { @SerialName("auto") AUTO, @SerialName("1") ONE, @SerialName("2") TWO; @@ -57,7 +60,7 @@ enum class ColumnCount { @ExperimentalReadiumApi @Serializable -enum class ImageFilter { +public enum class ImageFilter { @SerialName("darken") DARKEN, @SerialName("invert") INVERT; } @@ -65,28 +68,26 @@ enum class ImageFilter { /** * Typeface for a publication's text. * - * When not available, the Navigator should use [alternate] as a fallback. - * * For a list of vetted font families, see https://readium.org/readium-css/docs/CSS10-libre_fonts. */ @JvmInline @ExperimentalReadiumApi @Serializable -value class FontFamily(val name: String) { +public value class FontFamily(public val name: String) { - companion object { + public companion object { // Generic font families // See https://www.w3.org/TR/css-fonts-4/#generic-font-families - val SERIF = FontFamily("serif") - val SANS_SERIF = FontFamily("sans-serif") - val CURSIVE = FontFamily("cursive") - val FANTASY = FontFamily("fantasy") - val MONOSPACE = FontFamily("monospace") + public val SERIF: FontFamily = FontFamily("serif") + public val SANS_SERIF: FontFamily = FontFamily("sans-serif") + public val CURSIVE: FontFamily = FontFamily("cursive") + public val FANTASY: FontFamily = FontFamily("fantasy") + public val MONOSPACE: FontFamily = FontFamily("monospace") // Accessibility fonts embedded with Readium - val ACCESSIBLE_DFA = FontFamily("AccessibleDfA") - val IA_WRITER_DUOSPACE = FontFamily("IA Writer Duospace") - val OPEN_DYSLEXIC = FontFamily("OpenDyslexic") + public val ACCESSIBLE_DFA: FontFamily = FontFamily("AccessibleDfA") + public val IA_WRITER_DUOSPACE: FontFamily = FontFamily("IA Writer Duospace") + public val OPEN_DYSLEXIC: FontFamily = FontFamily("OpenDyslexic") } } @@ -96,14 +97,14 @@ value class FontFamily(val name: String) { @ExperimentalReadiumApi @Serializable @JvmInline -value class Color(@ColorInt val int: Int) +public value class Color(@ColorInt public val int: Int) /** * Layout axis. */ @ExperimentalReadiumApi @Serializable -enum class Axis(val value: String) { +public enum class Axis(public val value: String) { @SerialName("horizontal") HORIZONTAL("horizontal"), @SerialName("vertical") VERTICAL("vertical"); } @@ -113,7 +114,7 @@ enum class Axis(val value: String) { */ @ExperimentalReadiumApi @Serializable -enum class Spread(val value: String) { +public enum class Spread(public val value: String) { @SerialName("auto") AUTO("auto"), @SerialName("never") NEVER("never"), @SerialName("always") ALWAYS("always"); @@ -124,7 +125,7 @@ enum class Spread(val value: String) { */ @ExperimentalReadiumApi @Serializable -enum class ReadingProgression(val value: String) { +public enum class ReadingProgression(public val value: String) { @SerialName("ltr") LTR("ltr"), @SerialName("rtl") RTL("rtl"); } @@ -134,7 +135,7 @@ enum class ReadingProgression(val value: String) { */ @ExperimentalReadiumApi @Serializable -enum class Fit(val value: String) { +public enum class Fit(public val value: String) { @SerialName("cover") COVER("cover"), @SerialName("contain") CONTAIN("contain"), @SerialName("width") WIDTH("width"), diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/util/BaseActionModeCallback.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/util/BaseActionModeCallback.kt index 5c71d29144..ce75e7124c 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/util/BaseActionModeCallback.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/util/BaseActionModeCallback.kt @@ -14,7 +14,7 @@ import android.view.MenuItem * A convenient base implementation of [ActionMode.Callback], when you don't need to override all * methods. */ -abstract class BaseActionModeCallback : ActionMode.Callback { +public abstract class BaseActionModeCallback : ActionMode.Callback { override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean = false override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean = false override fun onDestroyActionMode(mode: ActionMode) {} diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/util/DirectionalNavigationAdapter.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/util/DirectionalNavigationAdapter.kt index e1d83f1fb2..0a234278d8 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/util/DirectionalNavigationAdapter.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/util/DirectionalNavigationAdapter.kt @@ -32,7 +32,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi * @param animatedTransition: Indicates whether the page turns should be animated. */ @ExperimentalReadiumApi -class DirectionalNavigationAdapter( +public class DirectionalNavigationAdapter( private val tapEdges: Set = setOf(TapEdge.Horizontal), private val handleTapsWhileScrolling: Boolean = false, private val minimumHorizontalEdgeSize: Double = 80.0, @@ -45,7 +45,7 @@ class DirectionalNavigationAdapter( /** * Indicates which viewport edges trigger page turns on tap. */ - enum class TapEdge { + public enum class TapEdge { Horizontal, Vertical; } @@ -90,7 +90,7 @@ class DirectionalNavigationAdapter( } override fun onKey(navigator: VisualNavigator, event: KeyEvent): Boolean { - if (event.type != KeyEvent.Type.Down || !event.modifiers.isEmpty()) { + if (event.type != KeyEvent.Type.Down || event.modifiers.isNotEmpty()) { return false } diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/util/EdgeTapNavigation.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/util/EdgeTapNavigation.kt index 5685b82eb0..b4d05761a1 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/util/EdgeTapNavigation.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/util/EdgeTapNavigation.kt @@ -1,12 +1,4 @@ package org.readium.r2.navigator.util -import org.readium.r2.navigator.VisualNavigator - @Deprecated("Replaced by [DirectionalNavigationAdapter].", replaceWith = ReplaceWith("DirectionalNavigationAdapter"), level = DeprecationLevel.ERROR) -class EdgeTapNavigation( - private val navigator: VisualNavigator, - private val minimumEdgeSize: Double = 200.0, - private val edgeThresholdPercent: Double? = 0.3, - private val animatedTransition: Boolean = false, - private val handleTapsWhileScrolling: Boolean = false -) +public class EdgeTapNavigation diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/util/FragmentFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/util/FragmentFactory.kt index bb16b84fd5..9061f3d6e5 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/util/FragmentFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/util/FragmentFactory.kt @@ -16,7 +16,7 @@ import org.readium.r2.shared.extensions.tryOrNull * [factory] closure. */ @InternalReadiumApi -inline fun createFragmentFactory(crossinline factory: () -> T): FragmentFactory = object : FragmentFactory() { +public inline fun createFragmentFactory(crossinline factory: () -> T): FragmentFactory = object : FragmentFactory() { override fun instantiate(classLoader: ClassLoader, className: String): Fragment { return when (className) { @@ -38,9 +38,9 @@ inline fun createFragmentFactory(crossinline factory: () * ``` */ @InternalReadiumApi -class CompositeFragmentFactory(private val factories: List) : FragmentFactory() { +public class CompositeFragmentFactory(private val factories: List) : FragmentFactory() { - constructor(vararg factories: FragmentFactory) : this(factories.toList()) + public constructor(vararg factories: FragmentFactory) : this(factories.toList()) override fun instantiate(classLoader: ClassLoader, className: String): Fragment { for (factory in factories) { diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/util/ViewModelFactory.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/util/ViewModelFactory.kt index d9369a0202..449ca59807 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/util/ViewModelFactory.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/util/ViewModelFactory.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.InternalReadiumApi * given [factory] closure. */ @InternalReadiumApi -inline fun createViewModelFactory(crossinline factory: () -> T): ViewModelProvider.Factory = +public inline fun createViewModelFactory(crossinline factory: () -> T): ViewModelProvider.Factory = object : ViewModelProvider.Factory { override fun create(modelClass: Class): V { diff --git a/readium/navigator/src/main/res/drawable/readium_baseline_forward_10_white_24.png b/readium/navigator/src/main/res/drawable/readium_baseline_forward_10_white_24.png deleted file mode 100755 index 4028f34ff99cca84dc15eafb77bd43aa1ddfae60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1015 zcmVo9=1rHu9l_8x))5F3U9f!JJbSne29pXE2<$omnF2YPBpTG!`~g1RrXf z$&}J-B6wVrOeXdA6T!3DEUV~Xn21j_&1PZC6(V|Sm(9|mcE*aPS~sJ`T^ESBCadLj zy+wnx%xHtd<{~c0YKzHjqDk6kwaMof(NkG%vszNbo+&2|7ERQU*-pFYoitAtFPs^) zv4urat$9&&ewqsncK4F$PDp`6{9rcd?mBH#?f71_Z<+(kxXJv~N`d_7#1b%H?^{`Be=#PxO2$mn%hYm;4_H0h$1g zN(Hu2k7Df@6LIWue}MP+fpUi6w&#m1f=8+(Z@yq zBj+R9Bvpo9MawEB1T;8FA3#s%7A;9?X`rZ6subrVx-OMS6WiK;&NDLCA-W({igw0` zrduynkabNLjnytyjw=fncPm6YJrP}5>E-nyh(6RbRe+{GKr~c`R9Oxz-ry*oXF+se zsyuIi=y6R`88r1Yh~7%oU|~Z*^s%;O{4hTP(Lf8Q>ahJ>wpmMNH9bKz%ND76oUX`Z zw^_Wz71!HLQRLJGcd5bMmQVA+^6oNOvFlUyd8m|&Jt7-;%5)TaIMsp%515-?o_B_A z{u(c7Z!Nnx%0-^n%iKJoA=QezRocC&wj5%tN*U*XRC`wNwn}*0aw+9{*<}~Ir3Fh< z#~Osv4RoBQsWH&Xd45ugpPj2!YFw=53SXFNZYKM}nT{hZAh4 ld8(MYy1Kf$y1Kf$-vD;hsqu-H9T@-s002ovPDHLkV1g&<;{5;s diff --git a/readium/navigator/src/main/res/drawable/readium_baseline_replay_10_white_24.png b/readium/navigator/src/main/res/drawable/readium_baseline_replay_10_white_24.png deleted file mode 100755 index 653f5452704823598f3acfb1d9c41d1e42e36b41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1028 zcmV+f1pE7mP)qqS|@wvAwI@5cGIZQDHSNvhu)b`L7)6V9~mZI(iPDl02< zPvY@OJU)rXC-L|s9-qYHlX!d*k5A(9NjyG@$0zalBp#o{PAYv*PdG zl|^%eLaT=2=_mGfEeqTMR@m*IzYYK^tyhByO}|hIo)DX-W339TV?LPeb5EKFzRn#C z&J%kgl!DzAy0JzDDmcqZ6)+_4=g^G`?G{SI2(bxTS6d+BI9&nLy=>LoNziz)0ijgf zsL%s-dL<9Baj1j`>TzL92eZVM+98xs&eG!Sk}fT}TcP2ldw|@<-Md36>12{Z-)kO9 zKy%+IG+C!mT27JmekcL&%Q_{Lp3h{xsd_Mn3GJnU_>$gb!V1Kdt{8V{YRx=eos*MySebnuUhqS*7-TXjo1+o1~AN*~phE z9{P(o!l3kyT}Cu_z6t7LybClBO@TIU&|7WvalJO7X|aX7{AO{rhrjQ%MQFOTbbt#z y={r4*wb-JHT$m`Z~Df*BafCZDwc^29w|978G? plNp)=Km51n;8#DVkv_$ki-GCDeZ`wzAGd%sdb;|#taD0e0szsl7@+_F diff --git a/readium/navigator/src/main/res/drawable/readium_ic_play_arrow_white_24dp.png b/readium/navigator/src/main/res/drawable/readium_ic_play_arrow_white_24dp.png deleted file mode 100644 index be5c062b5feeba5eff766b2fdae6dccb60cb4b0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z$oYG;uuoF`1aODUuH)UwnS^i z62=e)(*V{`2k`*b5=Y_d%(4?EPx_&_WMu+pnDW{BolE^Uxj)}+yLIc`8R zg{90Lt0f&`?lL^eViO2AZ`iSm@yJ!6R31a2DNst&xD8@?udTeN#I8%r_sg2!eom$?*X_%R&Z!t~|1-cBYK4gm#+1_nk5gW={^?qALV VOCpPJ@c;vi!PC{xWt~$(69D@(h;je` diff --git a/readium/navigator/src/main/res/drawable/readium_ic_skip_next_white_24dp.png b/readium/navigator/src/main/res/drawable/readium_ic_skip_next_white_24dp.png deleted file mode 100644 index 19c4929cca13b462dee093c2156ca904e52c4fad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z^LQt;uuoF`1Y2e9%~|l>%&f$ zg_kt9Uio5{z#evh>jtB=g!P7|jSU+azGiEd&dOAqxOz`#SLZX8=YO~-=s(>1`@F;% z7^n-LS2W|H{Q2{3`{(M~f3OwLariW~{mo=X&rh?0%@iVwoLRR#m)Xd8(p_(5!?zjC zW(qf-&f)dAb|Q2qMDd?P2140PE}_?HYd-Es6#;R0aPwX z)}VoZ#>xFo*?A}HkL;c^(caDdlelD!m(LT!?N4UaF0@pP*L;66{M7c`=~eQpe$#u6{1-oD!MWgRJ*37*6h35c^4-ARzU|x|q)oQAfQvV|n^}wB+M3~L&=?GA9=cqVv&%iW`HEwy9<;72claaCf7n>KDW7<$32ae>N}6KfLv)XJmOs-IeQS z@9bub^-glQI!Wrn)+MYZx}A)n-dPUUCrK>$fAad)C2TM1OUi+QU^SPr8vZbGC@}nF q6>wnq#I4Z4a75gJfsqBsyTA2URmg#B2af_nlfl!~&t;ucLK6TQaGnhS diff --git a/readium/navigator/src/main/res/layout/readium_navigator_item_spinner_font.xml b/readium/navigator/src/main/res/layout/readium_navigator_item_spinner_font.xml deleted file mode 100644 index 7ab9e9559a..0000000000 --- a/readium/navigator/src/main/res/layout/readium_navigator_item_spinner_font.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/readium/navigator/src/main/res/values/colors.xml b/readium/navigator/src/main/res/values/colors.xml deleted file mode 100644 index 1067c7ebf4..0000000000 --- a/readium/navigator/src/main/res/values/colors.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - #1f21b5 - #17188c - #eceaeb - #17188c - - - @color/readium_colorPrimaryDark - @color/readium_colorAccent - - diff --git a/readium/opds/build.gradle.kts b/readium/opds/build.gradle.kts index 8658e084d0..6c1af44654 100644 --- a/readium/opds/build.gradle.kts +++ b/readium/opds/build.gradle.kts @@ -42,6 +42,10 @@ android { namespace = "org.readium.r2.opds" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-opds" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt b/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt index 4a90f1cc60..a300195080 100644 --- a/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt +++ b/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt @@ -25,40 +25,43 @@ import org.readium.r2.shared.util.http.HttpClient import org.readium.r2.shared.util.http.HttpRequest import org.readium.r2.shared.util.http.fetchWithDecoder -enum class OPDSParserError { +public enum class OPDSParserError { MissingTitle } -data class MimeTypeParameters( +public data class MimeTypeParameters( var type: String, var parameters: MutableMap = mutableMapOf() ) -object Namespaces { - const val Opds = "http://opds-spec.org/2010/catalog" - const val Dc = "http://purl.org/dc/elements/1.1/" - const val Dcterms = "http://purl.org/dc/terms/" - const val Atom = "http://www.w3.org/2005/Atom" - const val Search = "http://a9.com/-/spec/opensearch/1.1/" - const val Thread = "http://purl.org/syndication/thread/1.0" +public object Namespaces { + public const val Opds: String = "http://opds-spec.org/2010/catalog" + public const val Dc: String = "http://purl.org/dc/elements/1.1/" + public const val Dcterms: String = "http://purl.org/dc/terms/" + public const val Atom: String = "http://www.w3.org/2005/Atom" + public const val Search: String = "http://a9.com/-/spec/opensearch/1.1/" + public const val Thread: String = "http://purl.org/syndication/thread/1.0" } -class OPDS1Parser { - companion object { +public class OPDS1Parser { + public companion object { - suspend fun parseUrlString(url: String, client: HttpClient = DefaultHttpClient()): Try { + public suspend fun parseUrlString(url: String, client: HttpClient = DefaultHttpClient()): Try { return client.fetchWithDecoder(HttpRequest(url)) { this.parse(it.body, URL(url)) } } - suspend fun parseRequest(request: HttpRequest, client: HttpClient = DefaultHttpClient()): Try { + public suspend fun parseRequest( + request: HttpRequest, + client: HttpClient = DefaultHttpClient() + ): Try { return client.fetchWithDecoder(request) { this.parse(it.body, URL(request.url)) } } - fun parse(xmlData: ByteArray, url: URL): ParseData { + public fun parse(xmlData: ByteArray, url: URL): ParseData { val root = XmlParser().parse(xmlData.inputStream()) return if (root.name == "feed") ParseData(parseFeed(root, url), null, 1) @@ -176,7 +179,7 @@ class OPDS1Parser { } @Suppress("unused") - suspend fun retrieveOpenSearchTemplate(feed: Feed): Try { + public suspend fun retrieveOpenSearchTemplate(feed: Feed): Try { var openSearchURL: URL? = null var selfMimeType: String? = null diff --git a/readium/opds/src/main/java/org/readium/r2/opds/OPDS2Parser.kt b/readium/opds/src/main/java/org/readium/r2/opds/OPDS2Parser.kt index 39360086cf..3656ba49c0 100644 --- a/readium/opds/src/main/java/org/readium/r2/opds/OPDS2Parser.kt +++ b/readium/opds/src/main/java/org/readium/r2/opds/OPDS2Parser.kt @@ -25,7 +25,7 @@ import org.readium.r2.shared.util.http.HttpClient import org.readium.r2.shared.util.http.HttpRequest import org.readium.r2.shared.util.http.fetchWithDecoder -enum class OPDS2ParserError { +public enum class OPDS2ParserError { MetadataNotFound, InvalidLink, MissingTitle, @@ -33,25 +33,28 @@ enum class OPDS2ParserError { InvalidGroup, } -class OPDS2Parser { +public class OPDS2Parser { - companion object { + public companion object { private lateinit var feed: Feed - suspend fun parseUrlString(url: String, client: HttpClient = DefaultHttpClient()): Try { + public suspend fun parseUrlString(url: String, client: HttpClient = DefaultHttpClient()): Try { return client.fetchWithDecoder(HttpRequest(url)) { this.parse(it.body, URL(url)) } } - suspend fun parseRequest(request: HttpRequest, client: HttpClient = DefaultHttpClient()): Try { + public suspend fun parseRequest( + request: HttpRequest, + client: HttpClient = DefaultHttpClient() + ): Try { return client.fetchWithDecoder(request) { this.parse(it.body, URL(request.url)) } } - fun parse(jsonData: ByteArray, url: URL): ParseData { + public fun parse(jsonData: ByteArray, url: URL): ParseData { return if (isFeed(jsonData)) { ParseData(parseFeed(jsonData, url), null, 2) } else { diff --git a/readium/shared/build.gradle.kts b/readium/shared/build.gradle.kts index 22dff30ed8..2c4225340c 100644 --- a/readium/shared/build.gradle.kts +++ b/readium/shared/build.gradle.kts @@ -43,6 +43,10 @@ android { namespace = "org.readium.r2.shared" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-shared" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/shared/src/main/java/org/readium/r2/shared/Deprecated.kt b/readium/shared/src/main/java/org/readium/r2/shared/Deprecated.kt index b3d793f758..268a1d9c20 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/Deprecated.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/Deprecated.kt @@ -25,74 +25,74 @@ import org.readium.r2.shared.publication.encryption.Encryption import org.readium.r2.shared.publication.presentation.Presentation import org.readium.r2.shared.util.Href -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Locator")) -typealias Locator = org.readium.r2.shared.publication.Locator +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Locator"), level = DeprecationLevel.ERROR) +public typealias Locator = org.readium.r2.shared.publication.Locator -@Deprecated("Renamed into [Locator.Locations]", ReplaceWith("Locator.Locations", "org.readium.r2.shared.publication.Locator")) -typealias Locations = org.readium.r2.shared.publication.Locator.Locations +@Deprecated("Renamed into [Locator.Locations]", ReplaceWith("Locator.Locations", "org.readium.r2.shared.publication.Locator"), level = DeprecationLevel.ERROR) +public typealias Locations = org.readium.r2.shared.publication.Locator.Locations -@Deprecated("Renamed into [Locator.Text]", ReplaceWith("Locator.Text", "org.readium.r2.shared.publication.Locator")) -typealias LocatorText = org.readium.r2.shared.publication.Locator.Text +@Deprecated("Renamed into [Locator.Text]", ReplaceWith("Locator.Text", "org.readium.r2.shared.publication.Locator"), level = DeprecationLevel.ERROR) +public typealias LocatorText = org.readium.r2.shared.publication.Locator.Text -@Deprecated("Moved to another package", ReplaceWith("Locator.Text", "org.readium.r2.shared.publication.html.DomRange")) -typealias DomRange = org.readium.r2.shared.publication.html.DomRange +@Deprecated("Moved to another package", ReplaceWith("Locator.Text", "org.readium.r2.shared.publication.html.DomRange"), level = DeprecationLevel.ERROR) +public typealias DomRange = org.readium.r2.shared.publication.html.DomRange -@Deprecated("Renamed into [DomRange.Point]", ReplaceWith("DomRange.Point", "org.readium.r2.shared.publication.html.DomRange")) -typealias Range = org.readium.r2.shared.publication.html.DomRange.Point +@Deprecated("Renamed into [DomRange.Point]", ReplaceWith("DomRange.Point", "org.readium.r2.shared.publication.html.DomRange"), level = DeprecationLevel.ERROR) +public typealias Range = org.readium.r2.shared.publication.html.DomRange.Point -@Deprecated("Refactored into [LocalizedString]", ReplaceWith("org.readium.r2.shared.publication.LocalizedString")) -typealias MultilanguageString = org.readium.r2.shared.publication.LocalizedString +@Deprecated("Refactored into [LocalizedString]", ReplaceWith("org.readium.r2.shared.publication.LocalizedString"), level = DeprecationLevel.ERROR) +public typealias MultilanguageString = org.readium.r2.shared.publication.LocalizedString -@Deprecated("Renamed into [ReadingProgression]", ReplaceWith("org.readium.r2.shared.publication.ReadingProgression")) -typealias PageProgressionDirection = org.readium.r2.shared.publication.ReadingProgression +@Deprecated("Renamed into [ReadingProgression]", ReplaceWith("org.readium.r2.shared.publication.ReadingProgression"), level = DeprecationLevel.ERROR) +public typealias PageProgressionDirection = org.readium.r2.shared.publication.ReadingProgression -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Publication")) -typealias Publication = org.readium.r2.shared.publication.Publication +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Publication"), level = DeprecationLevel.ERROR) +public typealias Publication = org.readium.r2.shared.publication.Publication -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Link")) -typealias Link = Link +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Link"), level = DeprecationLevel.ERROR) +public typealias Link = Link -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Properties")) -typealias Properties = Properties +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Properties"), level = DeprecationLevel.ERROR) +public typealias Properties = Properties -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Metadata")) -typealias Metadata = Metadata +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Metadata"), level = DeprecationLevel.ERROR) +public typealias Metadata = Metadata -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Contributor")) -typealias Contributor = Contributor +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Contributor"), level = DeprecationLevel.ERROR) +public typealias Contributor = Contributor -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Collection")) -typealias Collection = Collection +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Collection"), level = DeprecationLevel.ERROR) +public typealias Collection = Collection -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Subject")) -typealias Subject = Subject +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.Subject"), level = DeprecationLevel.ERROR) +public typealias Subject = Subject -@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.encryption.Encryption")) -typealias Encryption = Encryption +@Deprecated("Moved to another package", ReplaceWith("org.readium.r2.shared.publication.encryption.Encryption"), level = DeprecationLevel.ERROR) +public typealias Encryption = Encryption -@Deprecated("Refactored into [Presentation]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation")) -typealias Rendition = Presentation +@Deprecated("Refactored into [Presentation]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation"), level = DeprecationLevel.ERROR) +public typealias Rendition = Presentation -@Deprecated("Refactored into [EpubLayout]", ReplaceWith("org.readium.r2.shared.publication.epub.EpubLayout")) -typealias RenditionLayout = org.readium.r2.shared.publication.epub.EpubLayout +@Deprecated("Refactored into [EpubLayout]", ReplaceWith("org.readium.r2.shared.publication.epub.EpubLayout"), level = DeprecationLevel.ERROR) +public typealias RenditionLayout = org.readium.r2.shared.publication.epub.EpubLayout -@Deprecated("Refactored into [Presentation.Overflow]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation.Overflow")) -typealias RenditionFlow = Presentation.Overflow +@Deprecated("Refactored into [Presentation.Overflow]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation.Overflow"), level = DeprecationLevel.ERROR) +public typealias RenditionFlow = Presentation.Overflow -@Deprecated("Refactored into [Presentation.Orientation]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation.Orientation")) -typealias RenditionOrientation = Presentation.Orientation +@Deprecated("Refactored into [Presentation.Orientation]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation.Orientation"), level = DeprecationLevel.ERROR) +public typealias RenditionOrientation = Presentation.Orientation -@Deprecated("Refactored into [Presentation.Spread]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation.Spread")) -typealias RenditionSpread = Presentation.Spread +@Deprecated("Refactored into [Presentation.Spread]", ReplaceWith("org.readium.r2.shared.publication.presentation.Presentation.Spread"), level = DeprecationLevel.ERROR) +public typealias RenditionSpread = Presentation.Spread -@Deprecated("Use [Manifest::fromJSON] instead", ReplaceWith("Manifest.fromJSON(pubDict)", "org.readium.r2.shared.publication.Manifest")) -fun parsePublication(pubDict: JSONObject): org.readium.r2.shared.publication.Publication { +@Deprecated("Use [Manifest::fromJSON] instead", ReplaceWith("Manifest.fromJSON(pubDict)", "org.readium.r2.shared.publication.Manifest"), level = DeprecationLevel.ERROR) +public fun parsePublication(pubDict: JSONObject): org.readium.r2.shared.publication.Publication { return org.readium.r2.shared.publication.Manifest.fromJSON(pubDict)?.let { Publication(it) } ?: throw Exception("Invalid publication") } -@Deprecated("Use [Link::fromJSON] instead", ReplaceWith("Link.fromJSON(linkDict)", "org.readium.r2.shared.publication.Link")) -fun parseLink(linkDict: JSONObject, feedUrl: URL? = null): Link = +@Deprecated("Use [Link::fromJSON] instead", ReplaceWith("Link.fromJSON(linkDict)", "org.readium.r2.shared.publication.Link"), level = DeprecationLevel.ERROR) +public fun parseLink(linkDict: JSONObject, feedUrl: URL? = null): Link = Link.fromJSON(linkDict, normalizeHref = { if (feedUrl == null) { it @@ -101,9 +101,9 @@ fun parseLink(linkDict: JSONObject, feedUrl: URL? = null): Link = } }) ?: Link(href = "#") -@Deprecated("Moved to another package", ReplaceWith("removeLastComponent()", "org.readium.r2.shared.extensions.removeLastComponent")) -fun URL.removeLastComponent(): URL = removeLastComponent() +@Deprecated("Moved to another package", ReplaceWith("removeLastComponent()", "org.readium.r2.shared.extensions.removeLastComponent"), level = DeprecationLevel.ERROR) +public fun URL.removeLastComponent(): URL = removeLastComponent() -@Deprecated("Use `Href().string` instead", replaceWith = ReplaceWith("Href(href, base).string")) -fun normalize(base: String, href: String?): String = +@Deprecated("Use `Href().string` instead", replaceWith = ReplaceWith("Href(href, base).string"), level = DeprecationLevel.ERROR) +public fun normalize(base: String, href: String?): String = Href(href ?: "", baseHref = base).string diff --git a/readium/shared/src/main/java/org/readium/r2/shared/Injectable.kt b/readium/shared/src/main/java/org/readium/r2/shared/Injectable.kt index 7a176488c7..118b83f9df 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/Injectable.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/Injectable.kt @@ -10,14 +10,10 @@ package org.readium.r2.shared import java.io.Serializable -import org.readium.r2.shared.util.MapCompanion -enum class Injectable(val rawValue: String) : Serializable { +@Deprecated("Migrate the HTTP server, see the migration guide", level = DeprecationLevel.ERROR) +public enum class Injectable(public val value: String) : Serializable { Script("scripts"), Font("fonts"), Style("styles"); - - companion object : MapCompanion(values(), Injectable::rawValue) - - override fun toString(): String = rawValue } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/JSONable.kt b/readium/shared/src/main/java/org/readium/r2/shared/JSONable.kt index dc2e8cf77f..0564ce5c30 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/JSONable.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/JSONable.kt @@ -12,16 +12,16 @@ package org.readium.r2.shared import org.json.JSONArray import org.json.JSONObject -interface JSONable { +public interface JSONable { /** * Serializes the object to its JSON representation. */ - fun toJSON(): JSONObject + public fun toJSON(): JSONObject } /** * Serializes a list of [JSONable] into a [JSONArray]. */ -fun List.toJSON(): JSONArray = +public fun List.toJSON(): JSONArray = JSONArray(map(JSONable::toJSON)) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlayNode.kt b/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlayNode.kt index a0ec7b58dd..bbcc07edcf 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlayNode.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlayNode.kt @@ -11,14 +11,16 @@ package org.readium.r2.shared import java.io.Serializable -data class Clip( +@InternalReadiumApi +public data class Clip( val audioResource: String? = null, val fragmentId: String? = null, val start: Double? = null, val end: Double? = null ) -data class MediaOverlayNode( +@InternalReadiumApi +public data class MediaOverlayNode( val text: String, // an URI possibly finishing by a fragment (textFile#id) val audio: String?, // an URI possibly finishing by a simple timer (audioFile#t=start,end) val children: List = listOf(), diff --git a/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlays.kt b/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlays.kt index 185573e64c..71b95528a2 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlays.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/MediaOverlays.kt @@ -11,13 +11,14 @@ package org.readium.r2.shared import java.io.Serializable -data class MediaOverlays(private val nodes: List = listOf()) : Serializable { - fun clip(ref: String): Clip? { +@InternalReadiumApi +public data class MediaOverlays(private val nodes: List = listOf()) : Serializable { + public fun clip(ref: String): Clip? { val fragmentNode = nodeForFragment(ref) return fragmentNode?.clip } - fun nodeForFragment(ref: String?): MediaOverlayNode? = findNode(ref, this.nodes) + private fun nodeForFragment(ref: String?): MediaOverlayNode? = findNode(ref, this.nodes) private fun findNode(ref: String?, inNodes: List): MediaOverlayNode? { for (node in inNodes) { @@ -29,7 +30,7 @@ data class MediaOverlays(private val nodes: List = listOf()) : return null } - data class NextNodeResult(val found: MediaOverlayNode?, val prevFound: Boolean) + public data class NextNodeResult(val found: MediaOverlayNode?, val prevFound: Boolean) private fun nodeAfterFragment(ref: String?): MediaOverlayNode? = findNextNode(ref, this.nodes).found diff --git a/readium/shared/src/main/java/org/readium/r2/shared/OptIn.kt b/readium/shared/src/main/java/org/readium/r2/shared/OptIn.kt index 882d18d465..7afc6ad859 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/OptIn.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/OptIn.kt @@ -15,7 +15,7 @@ package org.readium.r2.shared ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR) -annotation class InternalReadiumApi +public annotation class InternalReadiumApi @RequiresOptIn( level = RequiresOptIn.Level.WARNING, @@ -23,7 +23,7 @@ annotation class InternalReadiumApi ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class ExperimentalReadiumApi +public annotation class ExperimentalReadiumApi @RequiresOptIn( level = RequiresOptIn.Level.WARNING, @@ -31,7 +31,7 @@ annotation class ExperimentalReadiumApi ) @Retention(value = AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class DelicateReadiumApi +public annotation class DelicateReadiumApi @RequiresOptIn( level = RequiresOptIn.Level.WARNING, @@ -39,7 +39,7 @@ annotation class DelicateReadiumApi ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class PdfSupport +public annotation class PdfSupport @RequiresOptIn( level = RequiresOptIn.Level.WARNING, @@ -47,4 +47,4 @@ annotation class PdfSupport ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) -annotation class Search +public annotation class Search diff --git a/readium/shared/src/main/java/org/readium/r2/shared/ReadiumCSS.kt b/readium/shared/src/main/java/org/readium/r2/shared/ReadiumCSS.kt index 498d338ac0..f3b62944dd 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/ReadiumCSS.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/ReadiumCSS.kt @@ -1,78 +1,56 @@ -@file:Suppress("DEPRECATION") - package org.readium.r2.shared -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val FONT_SIZE_REF = "fontSize" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val FONT_FAMILY_REF = "fontFamily" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val FONT_OVERRIDE_REF = "fontOverride" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val APPEARANCE_REF = "appearance" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val SCROLL_REF = "scroll" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val PUBLISHER_DEFAULT_REF = "advancedSettings" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val TEXT_ALIGNMENT_REF = "textAlign" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val COLUMN_COUNT_REF = "colCount" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val WORD_SPACING_REF = "wordSpacing" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val LETTER_SPACING_REF = "letterSpacing" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val PAGE_MARGINS_REF = "pageMargins" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val LINE_HEIGHT_REF = "lineHeight" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val FONT_SIZE_REF: String = "fontSize" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val FONT_FAMILY_REF: String = "fontFamily" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val FONT_OVERRIDE_REF: String = "fontOverride" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val APPEARANCE_REF: String = "appearance" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val SCROLL_REF: String = "scroll" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val PUBLISHER_DEFAULT_REF: String = "advancedSettings" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val TEXT_ALIGNMENT_REF: String = "textAlign" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val COLUMN_COUNT_REF: String = "colCount" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val WORD_SPACING_REF: String = "wordSpacing" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val LETTER_SPACING_REF: String = "letterSpacing" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val PAGE_MARGINS_REF: String = "pageMargins" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val LINE_HEIGHT_REF: String = "lineHeight" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val FONT_SIZE_NAME = "--USER__$FONT_SIZE_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val FONT_FAMILY_NAME = "--USER__$FONT_FAMILY_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val FONT_OVERRIDE_NAME = "--USER__$FONT_OVERRIDE_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val APPEARANCE_NAME = "--USER__$APPEARANCE_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val SCROLL_NAME = "--USER__$SCROLL_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val PUBLISHER_DEFAULT_NAME = "--USER__$PUBLISHER_DEFAULT_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val TEXT_ALIGNMENT_NAME = "--USER__$TEXT_ALIGNMENT_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val COLUMN_COUNT_NAME = "--USER__$COLUMN_COUNT_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val WORD_SPACING_NAME = "--USER__$WORD_SPACING_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val LETTER_SPACING_NAME = "--USER__$LETTER_SPACING_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val PAGE_MARGINS_NAME = "--USER__$PAGE_MARGINS_REF" -@Deprecated("Migrate to the new Settings API (see migration guide)") -const val LINE_HEIGHT_NAME = "--USER__$LINE_HEIGHT_REF" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val FONT_SIZE_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val FONT_FAMILY_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val FONT_OVERRIDE_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val APPEARANCE_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val SCROLL_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val PUBLISHER_DEFAULT_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val TEXT_ALIGNMENT_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val COLUMN_COUNT_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val WORD_SPACING_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val LETTER_SPACING_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val PAGE_MARGINS_NAME: String = "" +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public const val LINE_HEIGHT_NAME: String = "" // List of strings that can identify the name of a CSS custom property // Also used for storing UserSettings in UserDefaults -@Deprecated("Migrate to the new Settings API (see migration guide)") -enum class ReadiumCSSName(val ref: String) { - fontSize("--USER__fontSize"), - fontFamily("--USER__fontFamily"), - fontOverride("--USER__fontOverride"), - appearance("--USER__appearance"), - scroll("--USER__scroll"), - publisherDefault("--USER__advancedSettings"), - textAlignment("--USER__textAlign"), - columnCount("--USER__colCount"), - wordSpacing("--USER__wordSpacing"), - letterSpacing("--USER__letterSpacing"), - pageMargins("--USER__pageMargins"), - lineHeight("--USER__lineHeight"), - paraIndent("--USER__paraIndent"), - hyphens("--USER__bodyHyphens"), - ligatures("--USER__ligatures"); - - companion object { - fun ref(name: String): ReadiumCSSName = valueOf(name) - } -} +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.WARNING) +public enum class ReadiumCSSName(public val ref: String) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/RootFile.kt b/readium/shared/src/main/java/org/readium/r2/shared/RootFile.kt index b3865c0d17..194c1c29c1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/RootFile.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/RootFile.kt @@ -9,23 +9,11 @@ package org.readium.r2.shared -class RootFile() { - - constructor( - rootPath: String = "", - rootFilePath: String = "", - mimetype: String = "", - version: Double? = null - ) : this() { - this.rootPath = rootPath - this.rootFilePath = rootFilePath - this.mimetype = mimetype - this.version = version - } - - var rootPath: String = "" +@Deprecated("Not used anymore", level = DeprecationLevel.ERROR) +public class RootFile { + public var rootPath: String = "" // Path to OPF - var rootFilePath: String = "" - var mimetype: String = "" - var version: Double? = null + public var rootFilePath: String = "" + public var mimetype: String = "" + public var version: Double? = null } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/UserException.kt b/readium/shared/src/main/java/org/readium/r2/shared/UserException.kt index 2d42c4fc21..515bd7fd7b 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/UserException.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/UserException.kt @@ -17,15 +17,15 @@ import org.readium.r2.shared.extensions.asInstance /** * An exception that can be presented to the user using a localized message. */ -open class UserException protected constructor( +public open class UserException protected constructor( protected val content: Content, cause: Throwable? ) : Exception(cause) { - constructor(@StringRes userMessageId: Int, vararg args: Any?, cause: Throwable? = null) : + public constructor(@StringRes userMessageId: Int, vararg args: Any?, cause: Throwable? = null) : this(Content(userMessageId, *args), cause) - constructor( + public constructor( @PluralsRes userMessageId: Int, quantity: Int?, vararg args: Any?, @@ -33,10 +33,10 @@ open class UserException protected constructor( ) : this(Content(userMessageId, quantity, *args), cause) - constructor(message: String, cause: Throwable? = null) : + public constructor(message: String, cause: Throwable? = null) : this(Content(message), cause) - constructor(cause: UserException) : + public constructor(cause: UserException) : this(Content(cause), cause) /** @@ -44,7 +44,7 @@ open class UserException protected constructor( * * @param includesCauses Includes nested [UserException] causes in the user message when true. */ - open fun getUserMessage(context: Context, includesCauses: Boolean = true): String = + public open fun getUserMessage(context: Context, includesCauses: Boolean = true): String = content.getUserMessage(context, cause, includesCauses) /** @@ -52,7 +52,7 @@ open class UserException protected constructor( */ protected sealed class Content { - abstract fun getUserMessage( + public abstract fun getUserMessage( context: Context, cause: Throwable? = null, includesCauses: Boolean = true @@ -61,7 +61,7 @@ open class UserException protected constructor( /** * Holds a nested [UserException]. */ - class Exception(val exception: UserException) : Content() { + public class Exception(public val exception: UserException) : Content() { override fun getUserMessage( context: Context, cause: Throwable?, @@ -77,7 +77,7 @@ open class UserException protected constructor( * @param args Optional arguments to expand in the message. * @param quantity Quantity to use if the user message is a quantity strings. */ - class LocalizedString( + public class LocalizedString( private val userMessageId: Int, private val args: Array, private val quantity: Int? @@ -114,7 +114,7 @@ open class UserException protected constructor( * Holds an already localized string message. For example, received from an HTTP * Problem Details object. */ - class Message(private val message: String) : Content() { + public class Message(private val message: String) : Content() { override fun getUserMessage( context: Context, cause: Throwable?, @@ -122,14 +122,18 @@ open class UserException protected constructor( ): String = message } - companion object { - operator fun invoke(@StringRes userMessageId: Int, vararg args: Any?) = + public companion object { + public operator fun invoke(@StringRes userMessageId: Int, vararg args: Any?): Content = LocalizedString(userMessageId, args, null) - operator fun invoke(@PluralsRes userMessageId: Int, quantity: Int?, vararg args: Any?) = + public operator fun invoke( + @PluralsRes userMessageId: Int, + quantity: Int?, + vararg args: Any? + ): Content = LocalizedString(userMessageId, args, quantity) - operator fun invoke(cause: UserException) = + public operator fun invoke(cause: UserException): Content = Exception(cause) - operator fun invoke(message: String) = + public operator fun invoke(message: String): Content = Message(message) } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/UserProperties.kt b/readium/shared/src/main/java/org/readium/r2/shared/UserProperties.kt index 3399243241..583a38fc7d 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/UserProperties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/UserProperties.kt @@ -7,91 +7,42 @@ * LICENSE file present in the project repository where this source code is maintained. */ -@file:Suppress("DEPRECATION") +@file:Suppress("UNUSED_PARAMETER") package org.readium.r2.shared import java.io.Serializable -@Deprecated("Migrate to the new Settings API (see migration guide)") -sealed class UserProperty(var ref: String, var name: String) { +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public sealed class UserProperty(public var ref: String, public var name: String) - private val value: String - get() = this.toString() - - abstract override fun toString(): String - fun getJson(): String { - return """{name:"$name",value:"$this"}""" - } -} - -// TODO add here your new Subclasses of UserPreference. It has to be an abstract class inheriting from UserSetting. - -@Deprecated("Migrate to the new Settings API (see migration guide)") -class Enumerable(var index: Int, private val values: List, ref: String, name: String) : UserProperty(ref, name) { - override fun toString() = values[index] -} +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public class Enumerable( + public var index: Int, + private val values: List, + ref: String, + name: String +) -@Deprecated("Migrate to the new Settings API (see migration guide)") -class Incremental( - var value: Float, - val min: Float, - val max: Float, +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public class Incremental( + public var value: Float, + public val min: Float, + public val max: Float, private val step: Float, private val suffix: String, ref: String, name: String -) : UserProperty(ref, name) { - - fun increment() { - value += (if (value + step <= max) step else 0.0f) - } - - fun decrement() { - value -= (if (value - step >= min) step else 0.0f) - } - - override fun toString() = value.toString() + suffix -} - -@Deprecated("Migrate to the new Settings API (see migration guide)") -class Switchable(onValue: String, offValue: String, var on: Boolean, ref: String, name: String) : UserProperty(ref, name) { +) - private val values = mapOf(true to onValue, false to offValue) - - fun switch() { - on = !on - } - - override fun toString() = values[on] ?: error("") -} - -@Deprecated("Migrate to the new Settings API (see migration guide)") -class UserProperties : Serializable { - - val properties: MutableList = mutableListOf() - - fun addIncremental( - nValue: Float, - min: Float, - max: Float, - step: Float, - suffix: String, - ref: String, - name: String - ) { - properties.add(Incremental(nValue, min, max, step, suffix, ref, name)) - } - - fun addSwitchable(onValue: String, offValue: String, on: Boolean, ref: String, name: String) { - properties.add(Switchable(onValue, offValue, on, ref, name)) - } - - fun addEnumerable(index: Int, values: List, ref: String, name: String) { - properties.add(Enumerable(index, values, ref, name)) - } +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public class Switchable( + onValue: String, + offValue: String, + public var on: Boolean, + ref: String, + name: String +) - inline fun getByRef(ref: String) = properties.firstOrNull { - it.ref == ref - }!! as T -} +@Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) +public class UserProperties : Serializable diff --git a/readium/shared/src/main/java/org/readium/r2/shared/asset/Asset.kt b/readium/shared/src/main/java/org/readium/r2/shared/asset/Asset.kt index 2c79a6637b..e4c2938d08 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/asset/Asset.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/asset/Asset.kt @@ -11,27 +11,27 @@ import org.readium.r2.shared.util.mediatype.MediaType /** * An asset which is either a single resource or a container that holds multiple resources. */ -sealed class Asset { +public sealed class Asset { /** * Name of the asset, e.g. a filename. */ - abstract val name: String + public abstract val name: String /** * Media type of the asset. */ - abstract val mediaType: MediaType + public abstract val mediaType: MediaType /** * Type of the asset source. */ - abstract val assetType: AssetType + public abstract val assetType: AssetType /** * Releases in-memory resources related to this asset. */ - abstract suspend fun close() + public abstract suspend fun close() /** * A single resource asset. @@ -40,10 +40,10 @@ sealed class Asset { * @param mediaType Media type of the asset. * @param resource Opened resource to access the asset. */ - class Resource( + public class Resource( override val name: String, override val mediaType: MediaType, - val resource: org.readium.r2.shared.resource.Resource + public val resource: org.readium.r2.shared.resource.Resource ) : Asset() { override val assetType: AssetType = @@ -62,11 +62,11 @@ sealed class Asset { * @param exploded If this container is an exploded or packaged container. * @param container Opened container to access asset resources. */ - class Container( + public class Container( override val name: String, override val mediaType: MediaType, exploded: Boolean, - val container: org.readium.r2.shared.resource.Container + public val container: org.readium.r2.shared.resource.Container ) : Asset() { override val assetType: AssetType = diff --git a/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt b/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt index a8daa0f188..2b9aaff848 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.util.Url import org.readium.r2.shared.util.mediatype.* import org.readium.r2.shared.util.toUrl -class AssetRetriever( +public class AssetRetriever( private val resourceFactory: ResourceFactory, private val containerFactory: ContainerFactory, private val archiveFactory: ArchiveFactory, @@ -26,7 +26,7 @@ class AssetRetriever( sniffers: List ) { - constructor(context: Context) : this( + public constructor(context: Context) : this( resourceFactory = FileResourceFactory(), containerFactory = DirectoryContainerFactory(), archiveFactory = DefaultArchiveFactory(), @@ -34,78 +34,78 @@ class AssetRetriever( sniffers = MediaType.sniffers ) - sealed class Error : org.readium.r2.shared.error.Error { + public sealed class Error : org.readium.r2.shared.error.Error { - class SchemeNotSupported( - val scheme: String, + public class SchemeNotSupported( + public val scheme: String, override val cause: org.readium.r2.shared.error.Error?, ) : Error() { - constructor(scheme: String, exception: Exception) : + public constructor(scheme: String, exception: Exception) : this(scheme, ThrowableError(exception)) override val message: String = "Scheme $scheme is not supported." } - class NotFound( - val url: Url, + public class NotFound( + public val url: Url, override val cause: org.readium.r2.shared.error.Error? ) : Error() { - constructor(url: Url, exception: Exception) : + public constructor(url: Url, exception: Exception) : this(url, ThrowableError(exception)) override val message: String = "Asset could not be found at $url." } - class InvalidAsset( + public class InvalidAsset( override val cause: org.readium.r2.shared.error.Error? ) : Error() { - constructor(exception: Exception) : + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Asset looks corrupted." } - class ArchiveFormatNotSupported( + public class ArchiveFormatNotSupported( override val cause: org.readium.r2.shared.error.Error? ) : Error() { - constructor(exception: Exception) : + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Archive factory does not support this kind of archive." } - class Forbidden( - val url: Url, + public class Forbidden( + public val url: Url, override val cause: org.readium.r2.shared.error.Error ) : Error() { - constructor(url: Url, exception: Exception) : + public constructor(url: Url, exception: Exception) : this(url, ThrowableError(exception)) override val message: String = "Access to asset at url $url is forbidden." } - class Unavailable( + public class Unavailable( override val cause: org.readium.r2.shared.error.Error ) : Error() { - constructor(exception: Exception) : + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Asset seems not to be available at the moment." } - class OutOfMemory( + public class OutOfMemory( error: OutOfMemoryError ) : Error() { @@ -116,7 +116,7 @@ class AssetRetriever( ThrowableError(error) } - class Unknown( + public class Unknown( private val exception: Exception ) : Error() { @@ -131,7 +131,7 @@ class AssetRetriever( /** * Retrieves an asset from a known media and asset type again. */ - suspend fun retrieve( + public suspend fun retrieve( url: Url, mediaType: MediaType, assetType: AssetType @@ -236,7 +236,7 @@ class AssetRetriever( /** * Retrieves an asset from a local file. */ - suspend fun retrieve( + public suspend fun retrieve( file: File, mediaType: String? = null, fileExtension: String? = null, @@ -250,7 +250,7 @@ class AssetRetriever( /** * Retrieves an asset from a local file. */ - suspend fun retrieve( + public suspend fun retrieve( file: File, mediaTypes: List, fileExtensions: List, @@ -268,7 +268,7 @@ class AssetRetriever( /** * Retrieves an asset from an Uri. */ - suspend fun retrieve( + public suspend fun retrieve( uri: Uri, mediaType: String? = null, fileExtension: String? = null, @@ -282,7 +282,7 @@ class AssetRetriever( /** * Retrieves an asset from a Uri. */ - suspend fun retrieve( + public suspend fun retrieve( uri: Uri, mediaTypes: List, fileExtensions: List, @@ -296,7 +296,7 @@ class AssetRetriever( /** * Retrieves an asset from a Url. */ - suspend fun retrieve( + public suspend fun retrieve( url: Url, mediaType: String? = null, fileExtension: String? = null @@ -307,7 +307,7 @@ class AssetRetriever( /** * Retrieves an asset from a Url. */ - suspend fun retrieve( + public suspend fun retrieve( url: Url, mediaTypes: List, fileExtensions: List diff --git a/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetType.kt b/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetType.kt index 9e678234b3..c5731503b7 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetType.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetType.kt @@ -8,7 +8,7 @@ package org.readium.r2.shared.asset import org.readium.r2.shared.util.MapCompanion -enum class AssetType(val rawValue: String) { +public enum class AssetType(public val value: String) { /** * A simple resource. @@ -25,5 +25,5 @@ enum class AssetType(val rawValue: String) { */ Archive("archive"); - companion object : MapCompanion(values(), AssetType::rawValue) + public companion object : MapCompanion(values(), AssetType::value) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/drm/DRM.kt b/readium/shared/src/main/java/org/readium/r2/shared/drm/DRM.kt index 03599f9c9f..30784496a7 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/drm/DRM.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/drm/DRM.kt @@ -10,34 +10,25 @@ package org.readium.r2.shared.drm import java.io.Serializable -import org.readium.r2.shared.util.MapCompanion -data class DRM(val brand: Brand) : Serializable { - val scheme: Scheme - var license: DRMLicense? = null +@Deprecated("Not used anymore", level = DeprecationLevel.ERROR) +public class DRM { - enum class Brand(val rawValue: String) : Serializable { + @Deprecated("Not used anymore", level = DeprecationLevel.ERROR) + public enum class Brand(public val rawValue: String) : Serializable { lcp("lcp"); - - companion object : MapCompanion(values(), Brand::rawValue) } - enum class Scheme(val rawValue: String) : Serializable { + @Deprecated("Not used anymore", level = DeprecationLevel.ERROR) + public enum class Scheme(public val rawValue: String) : Serializable { lcp("http://readium.org/2014/01/lcp"); - - companion object : MapCompanion(values(), Scheme::rawValue) - } - - init { - when (brand) { - Brand.lcp -> scheme = Scheme.lcp - } } } -interface DRMLicense : Serializable { - val encryptionProfile: String? - fun decipher(data: ByteArray): ByteArray? - val canCopy: Boolean - fun copy(text: String): String? +@Deprecated("Not used anymore", level = DeprecationLevel.ERROR) +public interface DRMLicense : Serializable { + public val encryptionProfile: String? + public fun decipher(data: ByteArray): ByteArray? + public val canCopy: Boolean + public fun copy(text: String): String? } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/error/Error.kt b/readium/shared/src/main/java/org/readium/r2/shared/error/Error.kt index 7ab7005c5e..dedf070fa7 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/error/Error.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/error/Error.kt @@ -9,17 +9,17 @@ package org.readium.r2.shared.error /** * Describes an error. */ -interface Error { +public interface Error { /** * An error message. */ - val message: String + public val message: String /** * The cause error or null if there is none. */ - val cause: Error? + public val cause: Error? } /** @@ -27,8 +27,8 @@ interface Error { * * @param throwable the cause Throwable */ -class ThrowableError( - val throwable: Throwable +public class ThrowableError( + public val throwable: Throwable ) : Error { override val message: String = @@ -41,7 +41,7 @@ class ThrowableError( /** * A basic [Error] implementation with a message. */ -class MessageError( +public class MessageError( override val message: String, ) : Error { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/error/Try.kt b/readium/shared/src/main/java/org/readium/r2/shared/error/Try.kt index c20b8f444c..3fb8db45b9 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/error/Try.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/error/Try.kt @@ -7,33 +7,33 @@ package org.readium.r2.shared.error /** A [Result] type which can be used as a return type. */ -sealed class Try { +public sealed class Try { - companion object { + public companion object { /** Returns an instance that encapsulates the given value as successful value. */ - fun success(success: Success): Try = Success(success) + public fun success(success: Success): Try = Success(success) /** Returns the encapsulated Throwable exception if this instance represents failure or null if it is success. */ - fun failure(failure: Failure): Try = Failure(failure) + public fun failure(failure: Failure): Try = Failure(failure) } - abstract val isSuccess: Boolean - abstract val isFailure: Boolean + public abstract val isSuccess: Boolean + public abstract val isFailure: Boolean /** Returns the encapsulated value if this instance represents success or null if it is failure. */ - abstract fun getOrNull(): Success? + public abstract fun getOrNull(): Success? /** Returns the encapsulated [Throwable] exception if this instance represents failure or null if it is success. */ - abstract fun failureOrNull(): Failure? + public abstract fun failureOrNull(): Failure? - class Success(val value: S) : Try() { + public class Success(public val value: S) : Try() { override val isSuccess: Boolean get() = true override val isFailure: Boolean get() = false override fun getOrNull(): S? = value override fun failureOrNull(): F? = null } - class Failure(val value: F) : Try() { + public class Failure(public val value: F) : Try() { override val isSuccess: Boolean get() = false override val isFailure: Boolean get() = true override fun getOrNull(): S? = null @@ -44,7 +44,7 @@ sealed class Try { * Returns the encapsulated result of the given transform function applied to the encapsulated value * if this instance represents success or the original encapsulated [Throwable] exception if it is failure. */ - inline fun map(transform: (value: Success) -> R): Try = + public inline fun map(transform: (value: Success) -> R): Try = when (this) { is Try.Success -> success(transform(value)) is Try.Failure -> failure(value) @@ -54,7 +54,7 @@ sealed class Try { * Returns the encapsulated result of the given transform function applied to the encapsulated failure * if this instance represents failure or the original encapsulated success value if it is a success. */ - inline fun mapFailure(transform: (value: Failure) -> F): Try = + public inline fun mapFailure(transform: (value: Failure) -> F): Try = when (this) { is Try.Success -> success(value) is Try.Failure -> failure(transform(failureOrNull()!!)) @@ -64,7 +64,10 @@ sealed class Try { * Returns the result of [onSuccess] for the encapsulated value if this instance represents success or * the result of [onFailure] function for the encapsulated value if it is failure. */ - inline fun fold(onSuccess: (value: Success) -> R, onFailure: (exception: Failure) -> R): R = + public inline fun fold( + onSuccess: (value: Success) -> R, + onFailure: (exception: Failure) -> R + ): R = when (this) { is Try.Success -> onSuccess(value) is Try.Failure -> onFailure(failureOrNull()!!) @@ -74,7 +77,7 @@ sealed class Try { * Performs the given action on the encapsulated value if this instance represents success. * Returns the original [Try] unchanged. */ - inline fun onSuccess(action: (value: Success) -> Unit): Try { + public inline fun onSuccess(action: (value: Success) -> Unit): Try { if (this is Try.Success) action(value) return this } @@ -83,7 +86,7 @@ sealed class Try { * Performs the given action on the encapsulated value if this instance represents failure. * Returns the original [Try] unchanged. */ - inline fun onFailure(action: (exception: Failure) -> Unit): Try { + public inline fun onFailure(action: (exception: Failure) -> Unit): Try { if (this is Try.Failure) action(failureOrNull()!!) return this } @@ -93,7 +96,7 @@ sealed class Try { * Returns the encapsulated value if this instance represents success * or throws the encapsulated Throwable exception if it is failure. */ -fun Try.getOrThrow(): S = +public fun Try.getOrThrow(): S = when (this) { is Try.Success -> value is Try.Failure -> throw value @@ -102,7 +105,7 @@ fun Try.getOrThrow(): S = /** * Returns the encapsulated value if this instance represents success or the [defaultValue] if it is failure. */ -fun Try.getOrDefault(defaultValue: R): R = +public fun Try.getOrDefault(defaultValue: R): R = when (this) { is Try.Success -> value is Try.Failure -> defaultValue @@ -112,7 +115,7 @@ fun Try.getOrDefault(defaultValue: R): R = * Returns the encapsulated value if this instance represents success or the result of [onFailure] function * for the encapsulated value if it is failure. */ -inline fun Try.getOrElse(onFailure: (exception: F) -> R): R = +public inline fun Try.getOrElse(onFailure: (exception: F) -> R): R = when (this) { is Try.Success -> value is Try.Failure -> onFailure(value) @@ -122,7 +125,7 @@ inline fun Try.getOrElse(onFailure: (exception: F) -> R): R * Returns the encapsulated result of the given transform function applied to the encapsulated * value if this instance represents success or the original encapsulated value if it is failure. */ -inline fun Try.flatMap(transform: (value: S) -> Try): Try = +public inline fun Try.flatMap(transform: (value: S) -> Try): Try = when (this) { is Try.Success -> transform(value) is Try.Failure -> Try.failure(value) @@ -132,7 +135,7 @@ inline fun Try.flatMap(transform: (value: S) -> Try): Try< * Returns the encapsulated result of the given transform function applied to the encapsulated value * if this instance represents failure or the original encapsulated value if it is success. */ -inline fun Try.tryRecover(transform: (exception: F) -> Try): Try = +public inline fun Try.tryRecover(transform: (exception: F) -> Try): Try = when (this) { is Try.Success -> Try.success(value) is Try.Failure -> transform(value) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Bitmap.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Bitmap.kt index 65b2e35043..b1d4b87e39 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Bitmap.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Bitmap.kt @@ -15,6 +15,7 @@ import java.io.ByteArrayOutputStream import kotlin.math.min import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import org.readium.r2.shared.InternalReadiumApi /** * Resizes a bitmap to fit [maxSize] with bilinear filtering. @@ -36,7 +37,8 @@ internal fun Bitmap.scaleToFit(maxSize: Size): Bitmap { internal val Bitmap.size get() = Size(width, height) -suspend fun Bitmap.toPng(quality: Int = 100): ByteArray? = withContext(Dispatchers.Default) { +@InternalReadiumApi +public suspend fun Bitmap.toPng(quality: Int = 100): ByteArray? = withContext(Dispatchers.Default) { val stream = ByteArrayOutputStream() compress(Bitmap.CompressFormat.PNG, quality, stream).let { if (it) stream.toByteArray() else null diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/ByteArray.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/ByteArray.kt index c6e890703c..19149a5bd1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/ByteArray.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/ByteArray.kt @@ -12,6 +12,7 @@ package org.readium.r2.shared.extensions import java.io.ByteArrayOutputStream import java.security.MessageDigest import java.util.zip.Inflater +import org.readium.r2.shared.InternalReadiumApi import timber.log.Timber /** @@ -19,7 +20,8 @@ import timber.log.Timber * * @param nowrap If true then support GZIP compatible compression, see the documentation of [Inflater] */ -fun ByteArray.inflate(nowrap: Boolean = false, bufferSize: Int = 32 * 1024 /* 32 KB */): ByteArray = +@InternalReadiumApi +public fun ByteArray.inflate(nowrap: Boolean = false, bufferSize: Int = 32 * 1024 /* 32 KB */): ByteArray = ByteArrayOutputStream().use { output -> val inflater = Inflater(nowrap) inflater.setInput(this) @@ -34,7 +36,8 @@ fun ByteArray.inflate(nowrap: Boolean = false, bufferSize: Int = 32 * 1024 /* 32 } /** Computes the MD5 hash of the byte array. */ -fun ByteArray.md5(): String? = +@InternalReadiumApi +public fun ByteArray.md5(): String? = try { MessageDigest .getInstance("MD5") diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Date.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Date.kt index 595336f9e7..67d2e040b9 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Date.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Date.kt @@ -12,6 +12,8 @@ package org.readium.r2.shared.extensions import java.util.* import org.joda.time.DateTime import org.joda.time.DateTimeZone +import org.readium.r2.shared.InternalReadiumApi -fun Date.toIso8601String(timeZone: TimeZone = TimeZone.getTimeZone("UTC")): String = +@InternalReadiumApi +public fun Date.toIso8601String(timeZone: TimeZone = TimeZone.getTimeZone("UTC")): String = DateTime(this, DateTimeZone.forTimeZone(timeZone)).toString() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Exception.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Exception.kt index 2a52d7dcee..a2bee64dfb 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Exception.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Exception.kt @@ -9,25 +9,29 @@ package org.readium.r2.shared.extensions +import org.readium.r2.shared.InternalReadiumApi import timber.log.Timber /** * Returns the result of the given [closure], or null if an [Exception] was raised. */ -inline fun tryOrNull(closure: () -> T): T? = +@InternalReadiumApi +public inline fun tryOrNull(closure: () -> T): T? = tryOr(null, closure) /** * Returns the result of the given [closure], or [default] if an [Exception] was raised. */ -inline fun tryOr(default: T, closure: () -> T): T = +@InternalReadiumApi +public inline fun tryOr(default: T, closure: () -> T): T = try { closure() } catch (e: Exception) { default } /** * Returns the result of the given [closure], or null if an [Exception] was raised. * The [Exception] will be logged. */ -inline fun tryOrLog(closure: () -> T): T? = +@InternalReadiumApi +public inline fun tryOrLog(closure: () -> T): T? = try { closure() } catch (e: Exception) { Timber.e(e) null @@ -36,13 +40,15 @@ inline fun tryOrLog(closure: () -> T): T? = /** * Finds the first cause instance of the given type. */ -inline fun Throwable.asInstance(): T? = +@InternalReadiumApi +public inline fun Throwable.asInstance(): T? = asInstance(T::class.java) /** * Finds the first cause instance of the given type. */ -fun Throwable.asInstance(klass: Class): R? = +@InternalReadiumApi +public fun Throwable.asInstance(klass: Class): R? = @Suppress("UNCHECKED_CAST") when { klass.isInstance(this) -> this as R diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/File.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/File.kt index 88831e7826..f380f89ca9 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/File.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/File.kt @@ -12,6 +12,7 @@ package org.readium.r2.shared.extensions import java.io.File import java.io.FileInputStream import java.security.MessageDigest +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.util.mediatype.MediaType import org.readium.r2.shared.util.mediatype.MediaTypeRetriever import timber.log.Timber @@ -21,7 +22,8 @@ import timber.log.Timber * * Returns null if [File] is a directory or a file that failed to be read. */ -fun File.md5(): String? = +@InternalReadiumApi +public fun File.md5(): String? = try { val md = MessageDigest.getInstance("MD5") // https://stackoverflow.com/questions/10143731/android-optimal-buffer-size @@ -48,7 +50,8 @@ fun File.md5(): String? = /** * Returns whether the `other` is a descendant of this file. */ -fun File.isParentOf(other: File): Boolean { +@InternalReadiumApi +public fun File.isParentOf(other: File): Boolean { val canonicalThis = canonicalFile var parent = other.canonicalFile.parentFile while (parent != null) { @@ -66,5 +69,5 @@ fun File.isParentOf(other: File): Boolean { * If unknown, fallback on `MediaType.BINARY`. */ @Deprecated("Explicitly use MediaTypeRetriever", level = DeprecationLevel.ERROR) -suspend fun File.mediaType(mediaTypeHint: String? = null): MediaType = +public suspend fun File.mediaType(mediaTypeHint: String? = null): MediaType = MediaTypeRetriever().retrieve(this, mediaType = mediaTypeHint) ?: MediaType.BINARY diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Float.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Float.kt index 45e7ebbfcd..81a4893225 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Float.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Float.kt @@ -10,9 +10,9 @@ import kotlin.math.abs import org.readium.r2.shared.InternalReadiumApi @InternalReadiumApi -fun Float.equalsDelta(other: Float, delta: Float = 0.001f) = +public fun Float.equalsDelta(other: Float, delta: Float = 0.001f): Boolean = this == other || abs(this - other) < delta @InternalReadiumApi -fun Double.equalsDelta(other: Double, delta: Double = 0.001) = +public fun Double.equalsDelta(other: Double, delta: Double = 0.001): Boolean = this == other || abs(this - other) < delta diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Flow.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Flow.kt index 2a459af6ec..46685c96f8 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Flow.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Flow.kt @@ -15,7 +15,7 @@ import org.readium.r2.shared.InternalReadiumApi * [coroutineScope]. */ @InternalReadiumApi -fun StateFlow.mapStateIn( +public fun StateFlow.mapStateIn( coroutineScope: CoroutineScope, transform: (value: T) -> M ): StateFlow = @@ -31,7 +31,7 @@ fun StateFlow.mapStateIn( * given [coroutineScope]. */ @InternalReadiumApi -fun StateFlow.combineStateIn( +public fun StateFlow.combineStateIn( coroutineScope: CoroutineScope, flow: StateFlow, transform: (a: T1, b: T2) -> R diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Intent.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Intent.kt index 17096f2095..5536b235ab 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/Intent.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/Intent.kt @@ -20,22 +20,22 @@ import org.readium.r2.shared.publication.Metadata import org.readium.r2.shared.publication.Publication import timber.log.Timber -private val extraKey = "publicationId" +private const val extraKey = "publicationId" private val deprecationException = IllegalArgumentException("The [publication] intent extra is not supported anymore. Use the shared [PublicationRepository] instead.") @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Intent.putPublication(publication: Publication) { +public fun Intent.putPublication(publication: Publication) { val id = PublicationRepository.add(publication) putExtra(extraKey, id) } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Intent.putPublicationFrom(activity: Activity) { +public fun Intent.putPublicationFrom(activity: Activity) { putExtra(extraKey, activity.intent.getStringExtra(extraKey)) } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Intent.getPublication(activity: Activity?): Publication { +public fun Intent.getPublication(activity: Activity?): Publication { if (hasExtra("publication")) { if (BuildConfig.DEBUG) { throw deprecationException @@ -57,7 +57,7 @@ fun Intent.getPublication(activity: Activity?): Publication { } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Intent.getPublicationOrNull(): Publication? { +public fun Intent.getPublicationOrNull(): Publication? { if (hasExtra("publication")) { if (BuildConfig.DEBUG) { throw deprecationException @@ -70,13 +70,13 @@ fun Intent.getPublicationOrNull(): Publication? { } @Suppress("UNUSED_PARAMETER") -@Deprecated("The `activity` parameter is not necessary", ReplaceWith("getPublicationOrNull()"), level = DeprecationLevel.WARNING) -fun Intent.getPublicationOrNull(activity: Activity): Publication? { +@Deprecated("The `activity` parameter is not necessary", level = DeprecationLevel.ERROR) +public fun Intent.getPublicationOrNull(activity: Activity): Publication? { throw NotImplementedError() } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Intent.destroyPublication(activity: Activity?) { +public fun Intent.destroyPublication(activity: Activity?) { if (activity == null || activity.isFinishing) { getStringExtra(extraKey)?.let { PublicationRepository.remove(it) @@ -85,18 +85,18 @@ fun Intent.destroyPublication(activity: Activity?) { } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Bundle.putPublication(publication: Publication) { +public fun Bundle.putPublication(publication: Publication) { val id = PublicationRepository.add(publication) putString(extraKey, id) } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Bundle.putPublicationFrom(activity: Activity) { +public fun Bundle.putPublicationFrom(activity: Activity) { putString(extraKey, activity.intent.getStringExtra(extraKey)) } @Deprecated("Use a repository to share publications between components", level = DeprecationLevel.ERROR) -fun Bundle.getPublicationOrNull(): Publication? { +public fun Bundle.getPublicationOrNull(): Publication? { return getString(extraKey)?.let { PublicationRepository.get(it) } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/JSON.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/JSON.kt index 88c092fe2a..1c506afc18 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/JSON.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/JSON.kt @@ -13,13 +13,15 @@ import android.os.Parcel import kotlinx.parcelize.Parceler import org.json.JSONArray import org.json.JSONObject +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.JSONable import timber.log.Timber /** * Unwraps recursively the [JSONObject] to a [Map]. */ -fun JSONObject.toMap(): Map { +@InternalReadiumApi +public fun JSONObject.toMap(): Map { val map = mutableMapOf() for (key in keys()) { if (!isNull(key)) { @@ -32,7 +34,8 @@ fun JSONObject.toMap(): Map { /** * Unwraps recursively the [JSONArray] to a [List]. */ -fun JSONArray.toList(): List { +@InternalReadiumApi +public fun JSONArray.toList(): List { val list = mutableListOf() for (i in 0 until length()) { list.add(unwrapJSON(get(i))) @@ -69,7 +72,8 @@ private fun wrapJSON(value: Any?): Any? = when (value) { * Maps [name] to [jsonObject], clobbering any existing name/value mapping with the same name. If * the [JSONObject] is empty, any existing mapping for [name] is removed. */ -fun JSONObject.putIfNotEmpty(name: String, jsonObject: JSONObject?) { +@InternalReadiumApi +public fun JSONObject.putIfNotEmpty(name: String, jsonObject: JSONObject?) { if (jsonObject == null || jsonObject.length() == 0) { remove(name) return @@ -82,7 +86,8 @@ fun JSONObject.putIfNotEmpty(name: String, jsonObject: JSONObject?) { * Maps [name] to [jsonArray], clobbering any existing name/value mapping with the same name. If * the [JSONArray] is empty, any existing mapping for [name] is removed. */ -fun JSONObject.putIfNotEmpty(name: String, jsonArray: JSONArray?) { +@InternalReadiumApi +public fun JSONObject.putIfNotEmpty(name: String, jsonArray: JSONArray?) { if (jsonArray == null || jsonArray.length() == 0) { remove(name) return @@ -96,7 +101,8 @@ fun JSONObject.putIfNotEmpty(name: String, jsonArray: JSONArray?) { * name/value mapping with the same name. If the [JSONObject] argument is empty, any existing mapping * for [name] is removed. */ -fun JSONObject.putIfNotEmpty(name: String, jsonable: JSONable?) { +@InternalReadiumApi +public fun JSONObject.putIfNotEmpty(name: String, jsonable: JSONable?) { val json = jsonable?.toJSON() if (json == null || json.length() == 0) { remove(name) @@ -146,7 +152,8 @@ internal fun JSONObject.putIfNotEmpty(name: String, map: Map) { * positive integer, or [fallback] otherwise. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optPositiveInt(name: String, fallback: Int = -1, remove: Boolean = false): Int? { +@InternalReadiumApi +public fun JSONObject.optPositiveInt(name: String, fallback: Int = -1, remove: Boolean = false): Int? { val int = optInt(name, fallback) val value = if (int >= 0) int else null if (remove) { @@ -160,7 +167,12 @@ fun JSONObject.optPositiveInt(name: String, fallback: Int = -1, remove: Boolean * positive double, or [fallback] otherwise. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optPositiveDouble(name: String, fallback: Double = -1.0, remove: Boolean = false): Double? { +@InternalReadiumApi +public fun JSONObject.optPositiveDouble( + name: String, + fallback: Double = -1.0, + remove: Boolean = false +): Double? { val double = optDouble(name, fallback) val value = if (double >= 0) double else null if (remove) { @@ -174,7 +186,8 @@ fun JSONObject.optPositiveDouble(name: String, fallback: Double = -1.0, remove: * mapping exists, it is not a string or it is empty. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optNullableString(name: String, remove: Boolean = false): String? { +@InternalReadiumApi +public fun JSONObject.optNullableString(name: String, remove: Boolean = false): String? { val value = if (remove) this.remove(name) else this.opt(name) val string = value as? String return string?.takeUnless(String::isEmpty) @@ -185,7 +198,8 @@ fun JSONObject.optNullableString(name: String, remove: Boolean = false): String? * mapping exists. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optNullableBoolean(name: String, remove: Boolean = false): Boolean? { +@InternalReadiumApi +public fun JSONObject.optNullableBoolean(name: String, remove: Boolean = false): Boolean? { if (!has(name)) { return null } @@ -201,7 +215,8 @@ fun JSONObject.optNullableBoolean(name: String, remove: Boolean = false): Boolea * mapping exists. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optNullableInt(name: String, remove: Boolean = false): Int? { +@InternalReadiumApi +public fun JSONObject.optNullableInt(name: String, remove: Boolean = false): Int? { if (!has(name)) { return null } @@ -217,7 +232,8 @@ fun JSONObject.optNullableInt(name: String, remove: Boolean = false): Int? { * mapping exists. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optNullableLong(name: String, remove: Boolean = false): Long? { +@InternalReadiumApi +public fun JSONObject.optNullableLong(name: String, remove: Boolean = false): Long? { if (!has(name)) { return null } @@ -233,7 +249,8 @@ fun JSONObject.optNullableLong(name: String, remove: Boolean = false): Long? { * mapping exists. * If [remove] is true, then the mapping will be removed from the [JSONObject]. */ -fun JSONObject.optNullableDouble(name: String, remove: Boolean = false): Double? { +@InternalReadiumApi +public fun JSONObject.optNullableDouble(name: String, remove: Boolean = false): Double? { if (!has(name)) { return null } @@ -251,7 +268,8 @@ fun JSONObject.optNullableDouble(name: String, remove: Boolean = false): Double? * * E.g. ["a", "b"] or "a" */ -fun JSONObject.optStringsFromArrayOrSingle(name: String, remove: Boolean = false): List { +@InternalReadiumApi +public fun JSONObject.optStringsFromArrayOrSingle(name: String, remove: Boolean = false): List { val value = if (remove) this.remove(name) else opt(name) return when (value) { @@ -266,7 +284,8 @@ fun JSONObject.optStringsFromArrayOrSingle(name: String, remove: Boolean = false * in the original [JSONObject]. * If the tranform returns `null`, it is not included in the output list. */ -fun JSONObject.mapNotNull(transform: (Pair) -> T?): List { +@InternalReadiumApi +public fun JSONObject.mapNotNull(transform: (Pair) -> T?): List { val result = mutableListOf() for (key in keys()) { val transformedValue = transform(Pair(key, get(key))) @@ -282,7 +301,8 @@ fun JSONObject.mapNotNull(transform: (Pair) -> T?): List { * in the original [JSONArray]. * If the tranform returns `null`, it is not included in the output list. */ -fun JSONArray.mapNotNull(transform: (Any) -> T?): List { +@InternalReadiumApi +public fun JSONArray.mapNotNull(transform: (Any) -> T?): List { val result = mutableListOf() for (i in 0 until length()) { val transformedValue = transform(get(i)) @@ -327,7 +347,8 @@ internal fun JSONArray?.parseObjects(factory: (Any) -> T?): List { /** * Implementation of a [Parceler] to be used with [@Parcelize] to serialize JSON objects. */ -object JSONParceler : Parceler> { +@InternalReadiumApi +public object JSONParceler : Parceler> { override fun create(parcel: Parcel): Map = try { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/LongRange.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/LongRange.kt index 6317ebcf20..9e1ac1d830 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/LongRange.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/LongRange.kt @@ -9,11 +9,16 @@ package org.readium.r2.shared.extensions -fun LongRange.coerceFirstNonNegative() = LongRange(first.coerceAtLeast(0), last) +import org.readium.r2.shared.InternalReadiumApi -fun LongRange.coerceIn(range: LongRange) = LongRange(first.coerceAtLeast(range.first), last.coerceAtMost(range.last)) +@InternalReadiumApi +public fun LongRange.coerceFirstNonNegative(): LongRange = LongRange(first.coerceAtLeast(0), last) -fun LongRange.requireLengthFitInt() = this.apply { require(last - first + 1 <= Int.MAX_VALUE) } +@InternalReadiumApi +public fun LongRange.coerceIn(range: LongRange): LongRange = LongRange(first.coerceAtLeast(range.first), last.coerceAtMost(range.last)) + +@InternalReadiumApi +public fun LongRange.requireLengthFitInt(): LongRange = this.apply { require(last - first + 1 <= Int.MAX_VALUE) } internal fun LongRange.contains(range: LongRange) = contains(range.first) && contains(range.last) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/String.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/String.kt index b8a0bde976..9151295ec3 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/String.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/String.kt @@ -17,8 +17,10 @@ import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.json.JSONException import org.json.JSONObject +import org.readium.r2.shared.InternalReadiumApi -fun String.iso8601ToDate(): Date? = +@InternalReadiumApi +public fun String.iso8601ToDate(): Date? = try { // We assume that a date without a time zone component is in UTC. To handle this properly, // we need to set the default time zone of Joda to UTC, since by default it uses the local @@ -39,7 +41,8 @@ fun String.iso8601ToDate(): Date? = * If this string starts with the given [prefix], returns this string. * Otherwise, returns a copy of this string after adding the [prefix]. */ -fun String.addPrefix(prefix: CharSequence): String { +@InternalReadiumApi +public fun String.addPrefix(prefix: CharSequence): String { if (startsWith(prefix)) { return this } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/extensions/URL.kt b/readium/shared/src/main/java/org/readium/r2/shared/extensions/URL.kt index 7daf557937..dade60fa16 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/extensions/URL.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/extensions/URL.kt @@ -11,8 +11,10 @@ package org.readium.r2.shared.extensions import java.io.File import java.net.URL +import org.readium.r2.shared.InternalReadiumApi -fun URL.removeLastComponent(): URL { +@InternalReadiumApi +public fun URL.removeLastComponent(): URL { val lastPathComponent = path.split("/") .lastOrNull { it.isNotEmpty() } ?: return this @@ -26,5 +28,6 @@ fun URL.removeLastComponent(): URL { } /** Returns the file extension of the URL. */ -val URL.extension: String? get() = +@InternalReadiumApi +public val URL.extension: String? get() = File(path).extension.ifBlank { null } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/BytesResource.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/BytesResource.kt index a2c8654237..56c4f32efd 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/BytesResource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/BytesResource.kt @@ -6,20 +6,22 @@ package org.readium.r2.shared.fetcher import kotlinx.coroutines.runBlocking +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.error.Try import org.readium.r2.shared.publication.Link import org.readium.r2.shared.resource.Resource import org.readium.r2.shared.resource.ResourceTry -sealed class BaseBytesResource( +@InternalReadiumApi +public sealed class BaseBytesResource( private val link: Link, protected val resource: org.readium.r2.shared.resource.BytesResource ) : Resource by resource, Fetcher.Resource { - constructor(link: Link, bytes: suspend () -> ResourceTry) : + protected constructor(link: Link, bytes: suspend () -> ResourceTry) : this(link, org.readium.r2.shared.resource.BytesResource(bytes)) - constructor(link: Link, bytes: ByteArray) : + protected constructor(link: Link, bytes: ByteArray) : this(link, { Try.success(bytes) }) override suspend fun link(): Link = @@ -30,21 +32,21 @@ sealed class BaseBytesResource( } /** Creates a Resource serving [ByteArray]. */ -class BytesResource( +public class BytesResource( link: Link, bytes: suspend () -> ByteArray ) : BaseBytesResource(link, { Try.success(bytes()) }) { - constructor(link: Link, bytes: ByteArray) : this(link, { bytes }) + public constructor(link: Link, bytes: ByteArray) : this(link, { bytes }) } /** Creates a Resource serving a [String]. */ -class StringResource( +public class StringResource( link: Link, string: suspend () -> String ) : BaseBytesResource(link, { Try.success(string()).map { it.toByteArray() } }) { - constructor(link: Link, string: String) : this(link, { string }) + public constructor(link: Link, string: String) : this(link, { string }) override fun toString(): String = "${javaClass.simpleName}(${runBlocking { resource.bytes().map { it.toString() } } })" diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ContainerFetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ContainerFetcher.kt index 62a0bde77d..46e9624c0a 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ContainerFetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ContainerFetcher.kt @@ -20,7 +20,7 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever import org.readium.r2.shared.util.use /** Provides access to entries of a [Container]. */ -class ContainerFetcher( +public class ContainerFetcher( private val container: Container, private val mediaTypeRetriever: MediaTypeRetriever ) : Fetcher { @@ -33,8 +33,9 @@ class ContainerFetcher( override fun get(link: Link): Fetcher.Resource = EntryResource(link, container) - override suspend fun close() = + override suspend fun close() { container.close() + } private class EntryResource( val originalLink: Link, diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Fetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Fetcher.kt index bd918c12e4..3b4b9ec203 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Fetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Fetcher.kt @@ -13,12 +13,12 @@ import org.readium.r2.shared.resource.ResourceTry import org.readium.r2.shared.util.SuspendingCloseable /** Provides access to a [Resource] from a [Link]. */ -interface Fetcher : SuspendingCloseable { +public interface Fetcher : SuspendingCloseable { /** * Acts as a proxy to an actual resource by handling read access. */ - interface Resource : org.readium.r2.shared.resource.Resource { + public interface Resource : org.readium.r2.shared.resource.Resource { /** * Returns the link from which the resource was retrieved. @@ -26,7 +26,7 @@ interface Fetcher : SuspendingCloseable { * It might be modified by the [Resource] to include additional metadata, e.g. the * `Content-Type` HTTP header in [Link.type]. */ - suspend fun link(): Link + public suspend fun link(): Link } /** @@ -37,7 +37,7 @@ interface Fetcher : SuspendingCloseable { * If the medium has an inherent resource order, it should be followed. * Otherwise, HREFs are sorted alphabetically. */ - suspend fun links(): List + public suspend fun links(): List /** * Returns the [Resource] at the given [link]'s HREF. @@ -45,18 +45,18 @@ interface Fetcher : SuspendingCloseable { * A [Resource] is always returned, since for some cases we can't know if it exists before * actually fetching it, such as HTTP. Therefore, errors are handled at the Resource level. */ - fun get(link: Link): Resource + public fun get(link: Link): Resource /** Returns the [Resource] at the given [href]. */ - fun get(href: String): Resource = + public fun get(href: String): Resource = get(Link(href = href)) // To be able to add extensions on Fetcher.Companion in other components... - companion object + public companion object } /** A [Fetcher] providing no resources at all. */ -class EmptyFetcher : Fetcher { +public class EmptyFetcher : Fetcher { override suspend fun links(): List = emptyList() @@ -67,20 +67,20 @@ class EmptyFetcher : Fetcher { override suspend fun close() {} } -class ResourceFetcher( +public class ResourceFetcher( private val link: Link, private val resource: org.readium.r2.shared.resource.Resource ) : Fetcher { - companion object { + public companion object { - suspend operator fun invoke(resource: Resource): ResourceFetcher { + public suspend operator fun invoke(resource: Resource): ResourceFetcher { val link = resource.link() return ResourceFetcher(link, resource) } } - class Resource( + public class Resource( private val link: Link, private val resource: org.readium.r2.shared.resource.Resource ) : Fetcher.Resource { @@ -88,7 +88,7 @@ class ResourceFetcher( override val file: File? = resource.file - override suspend fun link() = + override suspend fun link(): Link = link override suspend fun length(): ResourceTry = diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/FileFetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/FileFetcher.kt index 7133e5c086..904274f0bf 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/FileFetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/FileFetcher.kt @@ -23,13 +23,13 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever * [paths] contains the reachable local paths, indexed by the exposed HREF. Sub-paths are reachable * as well, to be able to access a whole directory. */ -class FileFetcher( +public class FileFetcher( private val paths: Map, private val mediaTypeRetriever: MediaTypeRetriever ) : Fetcher { /** Provides access to the given local [file] at [href]. */ - constructor(href: String, file: File, mediaTypeRetriever: MediaTypeRetriever) : + public constructor(href: String, file: File, mediaTypeRetriever: MediaTypeRetriever) : this(mapOf(href to file), mediaTypeRetriever) private val openedResources: MutableList> = LinkedList() @@ -73,12 +73,14 @@ class FileFetcher( openedResources.clear() } - class FileResource(val link: Link, val resource: org.readium.r2.shared.resource.FileResource) : - Resource by resource, Fetcher.Resource { + public class FileResource( + public val link: Link, + public val resource: org.readium.r2.shared.resource.FileResource + ) : Resource by resource, Fetcher.Resource { - companion object { + public companion object { - operator fun invoke(link: Link, file: File): FileResource = + public operator fun invoke(link: Link, file: File): FileResource = FileResource(link, org.readium.r2.shared.resource.FileResource(file)) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Resource.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Resource.kt index 50fa83e464..d2c91fc141 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Resource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/Resource.kt @@ -10,6 +10,7 @@ import java.io.File import kotlinx.coroutines.* import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.error.Try import org.readium.r2.shared.error.flatMap import org.readium.r2.shared.extensions.coerceIn @@ -26,10 +27,10 @@ import org.readium.r2.shared.resource.ResourceTry * * If the transformation doesn't apply, simply return resource unchanged. */ -typealias ResourceTransformer = (Fetcher.Resource) -> Fetcher.Resource +public typealias ResourceTransformer = (Fetcher.Resource) -> Fetcher.Resource /** Creates a Resource that will always return the given [error]. */ -class FailureResource(private val link: Link, private val error: Resource.Exception) : +public class FailureResource(private val link: Link, private val error: Resource.Exception) : Fetcher.Resource { internal constructor(link: Link, cause: Throwable) : this(link, Resource.Exception.Other(cause)) @@ -49,7 +50,7 @@ class FailureResource(private val link: Link, private val error: Resource.Except /** * Resource that will act as a proxy to a fallback resource if the [originalResource] errors out. */ -class FallbackResource( +public class FallbackResource( private val originalResource: Fetcher.Resource, private val fallbackResourceFactory: (Resource.Exception) -> Fetcher.Resource ) : Fetcher.Resource { @@ -85,13 +86,15 @@ class FallbackResource( /** * Falls back to alternative resources when the receiver fails. */ -fun Fetcher.Resource.fallback(fallbackResourceFactory: (Resource.Exception) -> Fetcher.Resource): Fetcher.Resource = +public fun Fetcher.Resource.fallback( + fallbackResourceFactory: (Resource.Exception) -> Fetcher.Resource +): Fetcher.Resource = FallbackResource(this, fallbackResourceFactory) /** * Falls back to the given alternative [Fetcher.Resource] when the receiver fails. */ -fun Fetcher.Resource.fallback(fallbackResource: Fetcher.Resource): Fetcher.Resource = +public fun Fetcher.Resource.fallback(fallbackResource: Fetcher.Resource): Fetcher.Resource = FallbackResource(this) { fallbackResource } /** @@ -99,7 +102,7 @@ fun Fetcher.Resource.fallback(fallbackResource: Fetcher.Resource): Fetcher.Resou * * Every function is delegating to the proxied resource, and subclasses should override some of them. */ -abstract class ProxyResource(protected val resource: Fetcher.Resource) : Fetcher.Resource { +public abstract class ProxyResource(protected val resource: Fetcher.Resource) : Fetcher.Resource { override val file: File? = resource.file @@ -109,7 +112,7 @@ abstract class ProxyResource(protected val resource: Fetcher.Resource) : Fetcher override suspend fun read(range: LongRange?): ResourceTry = resource.read(range) - override suspend fun close() = resource.close() + override suspend fun close() { resource.close() } override fun toString(): String = "${javaClass.simpleName}($resource)" @@ -124,16 +127,19 @@ abstract class ProxyResource(protected val resource: Fetcher.Resource) : Fetcher * Warning: The transformation runs on the full content of [resource], so it's not appropriate for * large resources which can't be held in memory. */ -abstract class TransformingResource( +public abstract class TransformingResource( resource: Fetcher.Resource, private val cacheBytes: Boolean = true ) : ProxyResource(resource) { - companion object { + public companion object { /** * Creates a [TransformingResource] using the given [transform] function. */ - operator fun invoke(resource: Fetcher.Resource, transform: suspend (ByteArray) -> ByteArray): TransformingResource = + public operator fun invoke( + resource: Fetcher.Resource, + transform: suspend (ByteArray) -> ByteArray + ): TransformingResource = object : TransformingResource(resource) { override suspend fun transform(data: ResourceTry): ResourceTry = data.mapCatching { transform(it) } @@ -142,7 +148,7 @@ abstract class TransformingResource( private lateinit var _bytes: ResourceTry - abstract suspend fun transform(data: ResourceTry): ResourceTry + public abstract suspend fun transform(data: ResourceTry): ResourceTry private suspend fun bytes(): ResourceTry { if (::_bytes.isInitialized) @@ -174,7 +180,7 @@ abstract class TransformingResource( /** * Wraps a [Fetcher.Resource] which will be created only when first accessing one of its members. */ -class LazyResource(private val factory: suspend () -> Fetcher.Resource) : Fetcher.Resource { +public class LazyResource(private val factory: suspend () -> Fetcher.Resource) : Fetcher.Resource { private lateinit var _resource: Fetcher.Resource @@ -212,7 +218,7 @@ class LazyResource(private val factory: suspend () -> Fetcher.Resource) : Fetche * * This doesn't implement [ProxyResource] to avoid forgetting the synchronization for a future API. */ -class SynchronizedResource( +public class SynchronizedResource( private val resource: Fetcher.Resource ) : Fetcher.Resource { @@ -230,8 +236,9 @@ class SynchronizedResource( override suspend fun read(range: LongRange?): ResourceTry = mutex.withLock { resource.read(range) } - override suspend fun close() = + override suspend fun close() { mutex.withLock { resource.close() } + } override fun toString(): String = "${javaClass.simpleName}($resource)" @@ -240,7 +247,7 @@ class SynchronizedResource( /** * Wraps this resource in a [SynchronizedResource] to protect the access from multiple threads. */ -fun Fetcher.Resource.synchronized(): SynchronizedResource = +public fun Fetcher.Resource.synchronized(): SynchronizedResource = SynchronizedResource(this) /** @@ -260,14 +267,14 @@ fun Fetcher.Resource.synchronized(): SynchronizedResource = * by avoiding requesting the length from the underlying resource. * @param bufferSize Size of the buffer chunks to read. */ -class BufferingResource( +public class BufferingResource( resource: Fetcher.Resource, resourceLength: Long? = null, private val bufferSize: Long = DEFAULT_BUFFER_SIZE, ) : ProxyResource(resource) { - companion object { - const val DEFAULT_BUFFER_SIZE: Long = 8192 + internal companion object { + internal const val DEFAULT_BUFFER_SIZE: Long = 8192 } /** @@ -380,10 +387,10 @@ class BufferingResource( * by avoiding requesting the length from the underlying resource. * @param size Size of the buffer chunks to read. */ -fun Fetcher.Resource.buffered( +public fun Fetcher.Resource.buffered( resourceLength: Long? = null, size: Long = BufferingResource.DEFAULT_BUFFER_SIZE -) = +): BufferingResource = BufferingResource(resource = this, resourceLength = resourceLength, bufferSize = size) /** @@ -391,7 +398,8 @@ fun Fetcher.Resource.buffered( * * If the [transform] throws an [Exception], it is wrapped in a failure with Resource.Exception.Other. */ -inline fun ResourceTry.mapCatching(transform: (value: S) -> R): ResourceTry = +@InternalReadiumApi +public inline fun ResourceTry.mapCatching(transform: (value: S) -> R): ResourceTry = try { map(transform) } catch (e: Exception) { @@ -400,5 +408,6 @@ inline fun ResourceTry.mapCatching(transform: (value: S) -> R): Resour Try.failure(Resource.Exception.wrap(e)) } -inline fun ResourceTry.flatMapCatching(transform: (value: S) -> ResourceTry): ResourceTry = +@InternalReadiumApi +public inline fun ResourceTry.flatMapCatching(transform: (value: S) -> ResourceTry): ResourceTry = mapCatching(transform).flatMap { it } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ResourceContentExtractor.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ResourceContentExtractor.kt index 2ec26954f2..2127d82ebc 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ResourceContentExtractor.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ResourceContentExtractor.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.jsoup.Jsoup import org.jsoup.parser.Parser -import org.readium.r2.shared.Search +import org.readium.r2.shared.ExperimentalReadiumApi import org.readium.r2.shared.error.Try import org.readium.r2.shared.resource.ResourceTry import org.readium.r2.shared.resource.readAsString @@ -19,26 +19,26 @@ import org.readium.r2.shared.util.mediatype.MediaType /** * Extracts pure content from a marked-up (e.g. HTML) or binary (e.g. PDF) resource. */ -@Search -interface ResourceContentExtractor { +@ExperimentalReadiumApi +public interface ResourceContentExtractor { /** * Extracts the text content of the given [resource]. */ - suspend fun extractText(resource: Fetcher.Resource): ResourceTry = Try.success("") + public suspend fun extractText(resource: Fetcher.Resource): ResourceTry = Try.success("") - interface Factory { + public interface Factory { /** * Creates a [ResourceContentExtractor] instance for the given [resource]. * * Return null if the resource format is not supported. */ - suspend fun createExtractor(resource: Fetcher.Resource): ResourceContentExtractor? + public suspend fun createExtractor(resource: Fetcher.Resource): ResourceContentExtractor? } } -@Search -class DefaultResourceContentExtractorFactory : ResourceContentExtractor.Factory { +@ExperimentalReadiumApi +public class DefaultResourceContentExtractorFactory : ResourceContentExtractor.Factory { override suspend fun createExtractor(resource: Fetcher.Resource): ResourceContentExtractor? = when (resource.link().mediaType) { @@ -50,8 +50,8 @@ class DefaultResourceContentExtractorFactory : ResourceContentExtractor.Factory /** * [ResourceContentExtractor] implementation for HTML resources. */ -@Search -class HtmlResourceContentExtractor : ResourceContentExtractor { +@ExperimentalReadiumApi +public class HtmlResourceContentExtractor : ResourceContentExtractor { override suspend fun extractText(resource: Fetcher.Resource): ResourceTry = withContext(Dispatchers.IO) { resource.readAsString().mapCatching { html -> diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/RoutingFetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/RoutingFetcher.kt index 50977135fc..2c97ef9466 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/RoutingFetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/RoutingFetcher.kt @@ -20,16 +20,19 @@ import org.readium.r2.shared.resource.Resource * * The [routes] will be tested in the given order. */ -class RoutingFetcher(private val routes: List) : Fetcher { +public class RoutingFetcher(private val routes: List) : Fetcher { /** * Holds a child fetcher and the predicate used to determine if it can answer a request. * * The default value for [accepts] means that the fetcher will accept any link. */ - class Route(val fetcher: Fetcher, val accepts: (Link) -> Boolean = { true }) + public class Route( + public val fetcher: Fetcher, + public val accepts: (Link) -> Boolean = { true } + ) - constructor(local: Fetcher, remote: Fetcher) : + public constructor(local: Fetcher, remote: Fetcher) : this(listOf(Route(local, Link::isLocal), Route(remote))) override suspend fun links(): List = routes.flatMap { it.fetcher.links() } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/TransformingFetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/TransformingFetcher.kt index 682e4a4616..b02cd8a89b 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/TransformingFetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/TransformingFetcher.kt @@ -15,12 +15,12 @@ import org.readium.r2.shared.publication.Link * Transforms the resources' content of a child fetcher using a list of [ResourceTransformer] * functions. */ -class TransformingFetcher( +public class TransformingFetcher( private val fetcher: Fetcher, private val transformers: List ) : Fetcher { - constructor(fetcher: Fetcher, transformer: ResourceTransformer) : + public constructor(fetcher: Fetcher, transformer: ResourceTransformer) : this(fetcher, listOf(transformer)) override suspend fun links(): List = fetcher.links() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Acquisition.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Acquisition.kt index a064034015..91e8ab6ee9 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Acquisition.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Acquisition.kt @@ -27,7 +27,7 @@ import org.readium.r2.shared.util.mediatype.MediaType * https://drafts.opds.io/schema/acquisition-object.schema.json */ @Parcelize -data class Acquisition( +public data class Acquisition( val type: String, val children: List = emptyList() ) : JSONable, Parcelable { @@ -39,18 +39,18 @@ data class Acquisition( /** * Serializes an [Acquisition] to its JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("type", type) putIfNotEmpty("child", children) } - companion object { + public companion object { /** * Creates an [Acquisition] from its JSON representation. * If the acquisition can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Acquisition? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Acquisition? { val type = json?.optNullableString("type") if (type == null) { warnings?.log(Acquisition::class.java, "[type] is required", json) @@ -67,7 +67,7 @@ data class Acquisition( * Creates a list of [Acquisition] from its JSON representation. * If an acquisition can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSONArray( + public fun fromJSONArray( json: JSONArray?, warnings: WarningLogger? = null ): List { @@ -75,19 +75,19 @@ data class Acquisition( } } - @Deprecated("Use [type] instead", ReplaceWith("type")) + @Deprecated("Use [type] instead", ReplaceWith("type"), level = DeprecationLevel.ERROR) val typeAcquisition: String? get() = type - @Deprecated("Use [children] instead", ReplaceWith("children")) + @Deprecated("Use [children] instead", ReplaceWith("children"), level = DeprecationLevel.ERROR) val child: List get() = children } -@Deprecated("Renamed into [Acquisition]", ReplaceWith("Acquisition")) -typealias IndirectAcquisition = Acquisition +@Deprecated("Renamed into [Acquisition]", ReplaceWith("Acquisition"), level = DeprecationLevel.ERROR) +public typealias IndirectAcquisition = Acquisition -@Deprecated("Use [Acquisition::fromJSON] instead", ReplaceWith("Acquisition.fromJSON")) -fun parseIndirectAcquisition(indirectAcquisitionDict: JSONObject): Acquisition = +@Deprecated("Use [Acquisition::fromJSON] instead", ReplaceWith("Acquisition.fromJSON"), level = DeprecationLevel.ERROR) +public fun parseIndirectAcquisition(indirectAcquisitionDict: JSONObject): Acquisition = Acquisition.fromJSON(indirectAcquisitionDict) ?: throw Exception("Invalid indirect acquisition") diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Availability.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Availability.kt index ffc0382de6..f7269900ac 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Availability.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Availability.kt @@ -30,37 +30,37 @@ import org.readium.r2.shared.util.logging.log * @param until Timestamp for the next state change. */ @Parcelize -data class Availability( +public data class Availability( val state: State, val since: Date? = null, val until: Date? = null ) : JSONable, Parcelable { - enum class State(val value: String) { + public enum class State(public val value: String) { AVAILABLE("available"), UNAVAILABLE("unavailable"), RESERVED("reserved"), READY("ready"); - companion object : MapCompanion(values(), State::value) + public companion object : MapCompanion(values(), State::value) } /** * Serializes an [Availability] to its JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("state", state.value) put("since", since?.toIso8601String()) put("until", until?.toIso8601String()) } - companion object { + public companion object { /** * Creates an [Availability] from its JSON representation. * If the availability can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Availability? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Availability? { val state = State(json?.optNullableString("state")) if (state == null) { warnings?.log(Availability::class.java, "[state] is required", json) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Copies.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Copies.kt index 9ca56025fe..c1a318d0d8 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Copies.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Copies.kt @@ -21,7 +21,7 @@ import org.readium.r2.shared.extensions.optPositiveInt * https://drafts.opds.io/schema/properties.schema.json */ @Parcelize -data class Copies( +public data class Copies( val total: Int? = null, val available: Int? = null ) : JSONable, Parcelable { @@ -29,17 +29,17 @@ data class Copies( /** * Serializes an [Copies] to its JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("total", total) put("available", available) } - companion object { + public companion object { /** * Creates an [Copies] from its JSON representation. */ - fun fromJSON(json: JSONObject?): Copies? { + public fun fromJSON(json: JSONObject?): Copies? { json ?: return null return Copies( total = json.optPositiveInt("total"), diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Facet.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Facet.kt index 29947eb3b1..1fdd479399 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Facet.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Facet.kt @@ -11,7 +11,7 @@ package org.readium.r2.shared.opds import org.readium.r2.shared.publication.Link -data class Facet( +public data class Facet( val title: String, var metadata: OpdsMetadata = OpdsMetadata(title = title), var links: MutableList = mutableListOf() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Feed.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Feed.kt index 2badb74a5c..d364988f90 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Feed.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Feed.kt @@ -13,7 +13,7 @@ import java.net.URL import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Publication -data class Feed( +public data class Feed( val title: String, val type: Int, val href: URL, @@ -26,4 +26,4 @@ data class Feed( var context: MutableList = mutableListOf() ) -data class ParseData(val feed: Feed?, val publication: Publication?, val type: Int) +public data class ParseData(val feed: Feed?, val publication: Publication?, val type: Int) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Group.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Group.kt index d2a4fdf828..7a17e3ece6 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Group.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Group.kt @@ -12,9 +12,9 @@ package org.readium.r2.shared.opds import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Publication -data class Group(val title: String) { +public data class Group(val title: String) { var metadata: OpdsMetadata = OpdsMetadata(title = title) - var links = mutableListOf() - var publications = mutableListOf() - var navigation = mutableListOf() + var links: MutableList = mutableListOf() + var publications: MutableList = mutableListOf() + var navigation: MutableList = mutableListOf() } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Holds.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Holds.kt index 27fce88f84..4bf60ce4a9 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Holds.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Holds.kt @@ -21,7 +21,7 @@ import org.readium.r2.shared.extensions.optPositiveInt * https://drafts.opds.io/schema/properties.schema.json */ @Parcelize -data class Holds( +public data class Holds( val total: Int? = null, val position: Int? = null ) : JSONable, Parcelable { @@ -29,17 +29,17 @@ data class Holds( /** * Serializes an [Holds] to its JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("total", total) put("position", position) } - companion object { + public companion object { /** * Creates an [Holds] from its JSON representation. */ - fun fromJSON(json: JSONObject?): Holds? { + public fun fromJSON(json: JSONObject?): Holds? { json ?: return null return Holds( total = json.optPositiveInt("total"), diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/OpdsMetadata.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/OpdsMetadata.kt index 1990ab9aa0..147df3bc0e 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/OpdsMetadata.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/OpdsMetadata.kt @@ -11,7 +11,7 @@ package org.readium.r2.shared.opds import java.util.* -data class OpdsMetadata( +public data class OpdsMetadata( var title: String, var numberOfItems: Int? = null, var itemsPerPage: Int? = null, diff --git a/readium/shared/src/main/java/org/readium/r2/shared/opds/Price.kt b/readium/shared/src/main/java/org/readium/r2/shared/opds/Price.kt index 0e332c3674..1d873a1cea 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/opds/Price.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/opds/Price.kt @@ -28,7 +28,7 @@ import org.readium.r2.shared.util.logging.log * inherent with Double and the JSON parsing. */ @Parcelize -data class Price( +public data class Price( val currency: String, val value: Double ) : JSONable, Parcelable { @@ -36,18 +36,18 @@ data class Price( /** * Serializes an [Price] to its JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("currency", currency) put("value", value) } - companion object { + public companion object { /** * Creates an [Price] from its JSON representation. * If the price can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Price? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Price? { val currency = json?.optNullableString("currency") val value = json?.optPositiveDouble("value") if (currency == null || value == null) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/parser/xml/XmlParser.kt b/readium/shared/src/main/java/org/readium/r2/shared/parser/xml/XmlParser.kt index ea4b60e561..c10a8b15da 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/parser/xml/XmlParser.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/parser/xml/XmlParser.kt @@ -13,6 +13,7 @@ import java.io.IOException import java.io.InputStream import java.util.* import javax.xml.XMLConstants +import org.readium.r2.shared.InternalReadiumApi import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import org.xmlpull.v1.XmlPullParserFactory @@ -22,15 +23,19 @@ import org.xmlpull.v1.XmlPullParserFactory * [isNamespaceAware] behaves as defined in XmlPullParser specification. * If [isCaseSensitive] is false, attribute and tag names are lowercased during the parsing */ -class XmlParser(val isNamespaceAware: Boolean = true, val isCaseSensitive: Boolean = true) { +@InternalReadiumApi +public class XmlParser( + private val isNamespaceAware: Boolean = true, + private val isCaseSensitive: Boolean = true +) { - val parser: XmlPullParser = XmlPullParserFactory.newInstance().let { + private val parser: XmlPullParser = XmlPullParserFactory.newInstance().let { it.isNamespaceAware = isNamespaceAware it.newPullParser() } @Throws(XmlPullParserException::class, IOException::class) - fun parse(stream: InputStream): ElementNode { + public fun parse(stream: InputStream): ElementNode { parser.setInput(stream, null) // let the parser try to determine input encoding val stack = Stack, AttributeMap, String>>() @@ -103,17 +108,22 @@ class XmlParser(val isNamespaceAware: Boolean = true, val isCaseSensitive: Boole } } -data class Attribute(val name: String, val namespace: String, val value: String) +@InternalReadiumApi +public data class Attribute(val name: String, val namespace: String, val value: String) -typealias AttributeMap = Map> +@InternalReadiumApi +public typealias AttributeMap = Map> -sealed class Node +@InternalReadiumApi +public sealed class Node /** Container for text in the XML tree */ -data class TextNode(val text: String) : Node() +@InternalReadiumApi +public data class TextNode(val text: String) : Node() /** Represents a node with children in the XML tree */ -data class ElementNode( +@InternalReadiumApi +public data class ElementNode( val name: String, val namespace: String = "", val lang: String = "", @@ -131,23 +141,23 @@ data class ElementNode( /** Return the value of an attribute picked in the same namespace as this [ElementNode], * fallback to no namespace and at last to null. */ - fun getAttr(name: String) = getAttrNs(name, namespace) ?: getAttrNs(name, "") + public fun getAttr(name: String): String? = getAttrNs(name, namespace) ?: getAttrNs(name, "") /** Return the value of an attribute picked in a specific namespace or null if it does not exist */ - fun getAttrNs(name: String, namespace: String) = attributes[namespace]?.get(name) + public fun getAttrNs(name: String, namespace: String): String? = attributes[namespace]?.get(name) /** Return a list of all ElementNode children */ - fun getAll() = children.filterIsInstance() + public fun getAll(): List = children.filterIsInstance() /** Return a list of [ElementNode] children with the given name and namespace */ - fun get(name: String, namespace: String) = + public fun get(name: String, namespace: String): List = getAll().filter { it.name == name && it.namespace == namespace } /** Return the first [ElementNode] child with the given name and namespace, or null if there is none */ - fun getFirst(name: String, namespace: String) = get(name, namespace).firstOrNull() + public fun getFirst(name: String, namespace: String): ElementNode? = get(name, namespace).firstOrNull() /** Recursively collect all descendent [ElementNode] with the given name and namespace into a list */ - fun collect(name: String, namespace: String): List { + public fun collect(name: String, namespace: String): List { val founded: MutableList = mutableListOf() for (c in getAll()) { if (c.name == name && c.namespace == namespace) founded.add(c) @@ -157,7 +167,7 @@ data class ElementNode( } /** Recursively collect and concatenate all descendent [TextNode] in depth-first order */ - fun collectText(): String { + public fun collectText(): String { val text = StringBuilder() for (c in children) { when (c) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Accessibility.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Accessibility.kt index c4be22b88f..d3e229b85c 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Accessibility.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Accessibility.kt @@ -45,7 +45,7 @@ import org.readium.r2.shared.util.logging.log * dangerous to some users. */ @Parcelize -data class Accessibility( +public data class Accessibility( val conformsTo: Set, val certification: Certification? = null, val summary: String? = null, @@ -60,17 +60,17 @@ data class Accessibility( */ @Parcelize @JvmInline - value class Profile(val uri: String) : Parcelable { + public value class Profile(public val uri: String) : Parcelable { - companion object { + public companion object { - val EPUB_A11Y_10_WCAG_20_A = Profile("http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-a") + public val EPUB_A11Y_10_WCAG_20_A: Profile = Profile("http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-a") - val EPUB_A11Y_10_WCAG_20_AA = Profile("http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-aa") + public val EPUB_A11Y_10_WCAG_20_AA: Profile = Profile("http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-aa") - val EPUB_A11Y_10_WCAG_20_AAA = Profile("http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-aaa") + public val EPUB_A11Y_10_WCAG_20_AAA: Profile = Profile("http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-aaa") - fun Set.toJSONArray(): JSONArray = + public fun Set.toJSONArray(): JSONArray = JSONArray(this.map(Profile::uri)) } } @@ -86,7 +86,7 @@ data class Accessibility( * in the associated [certifiedBy] property. */ @Parcelize - data class Certification( + public data class Certification( val certifiedBy: String?, val credential: String?, val report: String? @@ -98,14 +98,14 @@ data class Accessibility( put("report", report) } - companion object { + public companion object { /** * Parses a [Certification] from its RWPM JSON representation. * * If the certification can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON( + public fun fromJSON( json: JSONObject?, warnings: WarningLogger? = null ): Certification? { @@ -134,43 +134,43 @@ data class Accessibility( */ @Parcelize @JvmInline - value class AccessMode(val value: String) : Parcelable { + public value class AccessMode(public val value: String) : Parcelable { - companion object { + public companion object { /** * Indicates that the resource contains information encoded in auditory form. */ - val AUDITORY = AccessMode("auditory") + public val AUDITORY: AccessMode = AccessMode("auditory") /** * Indicates that the resource contains charts encoded in visual form. */ - val CHART_ON_VISUAL = AccessMode("chartOnVisual") + public val CHART_ON_VISUAL: AccessMode = AccessMode("chartOnVisual") /** * Indicates that the resource contains chemical equations encoded in visual form. */ - val CHEM_ON_VISUAL = AccessMode("chemOnVisual") + public val CHEM_ON_VISUAL: AccessMode = AccessMode("chemOnVisual") /** * Indicates that the resource contains information encoded such that color perception is necessary. */ - val COLOR_DEPENDENT = AccessMode("colorDependent") + public val COLOR_DEPENDENT: AccessMode = AccessMode("colorDependent") /** * Indicates that the resource contains diagrams encoded in visual form. */ - val DIAGRAM_ON_VISUAL = AccessMode("diagramOnVisual") + public val DIAGRAM_ON_VISUAL: AccessMode = AccessMode("diagramOnVisual") /** * Indicates that the resource contains mathematical notations encoded in visual form. */ - val MATH_ON_VISUAL = AccessMode("mathOnVisual") + public val MATH_ON_VISUAL: AccessMode = AccessMode("mathOnVisual") /** * Indicates that the resource contains musical notation encoded in visual form. */ - val MUSIC_ON_VISUAL = AccessMode("musicOnVisual") + public val MUSIC_ON_VISUAL: AccessMode = AccessMode("musicOnVisual") /** * Indicates that the resource contains information encoded in tactile form. @@ -179,32 +179,32 @@ data class Accessibility( * using a braille system, this is not always the case. Tactile perception may also indicate, * for example, the use of tactile graphics to convey information. */ - val TACTILE = AccessMode("tactile") + public val TACTILE: AccessMode = AccessMode("tactile") /** * Indicates that the resource contains text encoded in visual form. */ - val TEXT_ON_VISUAL = AccessMode("textOnVisual") + public val TEXT_ON_VISUAL: AccessMode = AccessMode("textOnVisual") /** * Indicates that the resource contains information encoded in textual form. */ - val TEXTUAL = AccessMode("textual") + public val TEXTUAL: AccessMode = AccessMode("textual") /** * Indicates that the resource contains information encoded in visual form. */ - val VISUAL = AccessMode("visual") + public val VISUAL: AccessMode = AccessMode("visual") /** * Creates a list of [AccessMode] from its RWPM JSON representation. */ - fun fromJSONArray(json: JSONArray?): List = + public fun fromJSONArray(json: JSONArray?): List = json?.filterIsInstance(String::class.java) ?.map { AccessMode(it) } .orEmpty() - fun Set.toJSONArray(): JSONArray = + public fun Set.toJSONArray(): JSONArray = JSONArray(this.map(AccessMode::value)) } } @@ -215,7 +215,7 @@ data class Accessibility( */ @Parcelize @Serializable - enum class PrimaryAccessMode(val value: String) : Parcelable { + public enum class PrimaryAccessMode(public val value: String) : Parcelable { /** * Indicates that auditory perception is necessary to consume the information. @@ -240,17 +240,17 @@ data class Accessibility( */ @SerialName("visual") VISUAL("visual"); - companion object : MapCompanion(values(), PrimaryAccessMode::value) { + public companion object : MapCompanion(values(), PrimaryAccessMode::value) { /** * Creates a list of [PrimaryAccessMode] from its RWPM JSON representation. */ - fun fromJSONArray(json: JSONArray?): List = + public fun fromJSONArray(json: JSONArray?): List = json?.filterIsInstance(String::class.java) ?.mapNotNull { get(it) } .orEmpty() - fun Set.toJSONArray(): JSONArray = + public fun Set.toJSONArray(): JSONArray = JSONArray(this.map(PrimaryAccessMode::value)) } } @@ -261,13 +261,13 @@ data class Accessibility( */ @Parcelize @JvmInline - value class Feature(val value: String) : Parcelable { + public value class Feature(public val value: String) : Parcelable { - companion object { + public companion object { /** * The work includes annotations from the author, instructor and/or others. */ - val ANNOTATIONS = Feature("annotations") + public val ANNOTATIONS: Feature = Feature("annotations") /** * Indicates the resource includes ARIA roles to organize and improve the structure and navigation. @@ -275,74 +275,74 @@ data class Accessibility( * The use of this value corresponds to the inclusion of Document Structure, Landmark, * Live Region, and Window roles [WAI-ARIA]. */ - val ARIA = Feature("ARIA") + public val ARIA: Feature = Feature("ARIA") /** * The work includes bookmarks to facilitate navigation to key points. */ - val BOOKMARKS = Feature("bookmark") + public val BOOKMARKS: Feature = Feature("bookmark") /** * The work includes an index to the content. */ - val INDEX = Feature("index") + public val INDEX: Feature = Feature("index") /** * The work includes equivalent print page numbers. This setting is most commonly used * with ebooks for which there is a print equivalent. */ - val PRINT_PAGE_NUMBERS = Feature("printPageNumbers") + public val PRINT_PAGE_NUMBERS: Feature = Feature("printPageNumbers") /** * The reading order of the content is clearly defined in the markup * (e.g., figures, sidebars and other secondary content has been marked up to allow it * to be skipped automatically and/or manually escaped from). */ - val READING_ORDER = Feature("readingOrder") + public val READING_ORDER: Feature = Feature("readingOrder") /** * The use of headings in the work fully and accurately reflects the document hierarchy, * allowing navigation by assistive technologies. */ - val STRUCTURAL_NAVIGATION = Feature("structuralNavigation") + public val STRUCTURAL_NAVIGATION: Feature = Feature("structuralNavigation") /** * The work includes a table of contents that provides links to the major sections of the content. */ - val TABLE_OF_CONTENTS = Feature("tableOfContents") + public val TABLE_OF_CONTENTS: Feature = Feature("tableOfContents") /** * The contents of the PDF have been tagged to permit access by assistive technologies. */ - val TAGGED_PDF = Feature("taggedPDF") + public val TAGGED_PDF: Feature = Feature("taggedPDF") /** * Alternative text is provided for visual content (e.g., via the HTML `alt` attribute). */ - val ALTERNATIVE_TEXT = Feature("alternativeText") + public val ALTERNATIVE_TEXT: Feature = Feature("alternativeText") /** * Audio descriptions are available (e.g., via an HTML `track` element with its `kind` * attribute set to "descriptions"). */ - val AUDIO_DESCRIPTION = Feature("audioDescription") + public val AUDIO_DESCRIPTION: Feature = Feature("audioDescription") /** * Indicates that synchronized captions are available for audio and video content. */ - val CAPTIONS = Feature("captions") + public val CAPTIONS: Feature = Feature("captions") /** * Textual descriptions of math equations are included, whether in the alt attribute * for image-based equations, */ - val DESCRIBED_MATH = Feature("describeMath") + public val DESCRIBED_MATH: Feature = Feature("describeMath") /** * Descriptions are provided for image-based visual content and/or complex structures * such as tables, mathematics, diagrams, and charts. */ - val LONG_DESCRIPTION = Feature("longDescription") + public val LONG_DESCRIPTION: Feature = Feature("longDescription") /** * Indicates that `ruby` annotations HTML are provided in the content. Ruby annotations @@ -351,17 +351,17 @@ data class Accessibility( * * The absence of rubyAnnotations implies that no CJK ideographic characters have ruby. */ - val RUBY_ANNOTATIONS = Feature("rubyAnnotations") + public val RUBY_ANNOTATIONS: Feature = Feature("rubyAnnotations") /** * Sign language interpretation is available for audio and video content. */ - val SIGN_LANGUAGE = Feature("signLanguage") + public val SIGN_LANGUAGE: Feature = Feature("signLanguage") /** * Indicates that a transcript of the audio content is available. */ - val TRANSCRIPT = Feature("transcript") + public val TRANSCRIPT: Feature = Feature("transcript") /** * Display properties are controllable by the user. This property can be set, for example, @@ -369,7 +369,7 @@ data class Accessibility( * It can also be used to indicate that styling in document formats like Word and PDF * can be modified. */ - val DISPLAY_TRANSFORMABILITY = Feature("displayTransformability") + public val DISPLAY_TRANSFORMABILITY: Feature = Feature("displayTransformability") /** * Describes a resource that offers both audio and text, with information that allows them @@ -377,93 +377,93 @@ data class Accessibility( * This term is not recommended when the only material that is synchronized is * the document headings. */ - val SYNCHRONIZED_AUDIO_TEXT = Feature("synchronizedAudioText") + public val SYNCHRONIZED_AUDIO_TEXT: Feature = Feature("synchronizedAudioText") /** * For content with timed interaction, this value indicates that the user can control * the timing to meet their needs (e.g., pause and reset) */ - val TIMING_CONTROL = Feature("timingControl") + public val TIMING_CONTROL: Feature = Feature("timingControl") /** * No digital rights management or other content restriction protocols have been applied * to the resource. */ - val UNLOCKED = Feature("unlocked") + public val UNLOCKED: Feature = Feature("unlocked") /** * Identifies that chemical information is encoded using the ChemML markup language. */ - val CHEM_ML = Feature("ChemML") + public val CHEM_ML: Feature = Feature("ChemML") /** * Identifies that mathematical equations and formulas are encoded in the LaTeX * typesetting system. */ - val LATEX = Feature("latex") + public val LATEX: Feature = Feature("latex") /** * Identifies that mathematical equations and formulas are encoded in MathML. */ - val MATH_ML = Feature("MathML") + public val MATH_ML: Feature = Feature("MathML") /** * One or more of SSML, Pronunciation-Lexicon, and CSS3-Speech properties has been used * to enhance text-to-speech playback quality. */ - val TTS_MARKUP = Feature("ttsMarkup") + public val TTS_MARKUP: Feature = Feature("ttsMarkup") /** * Audio content with speech in the foreground meets the contrast thresholds set out * in WCAG Success Criteria 1.4.7. */ - val HIGH_CONTRAST_AUDIO = Feature("highContrastAudio") + public val HIGH_CONTRAST_AUDIO: Feature = Feature("highContrastAudio") /** * Content meets the visual contrast threshold set out in WCAG Success Criteria 1.4.6. */ - val HIGH_CONTRAST_DISPLAY = Feature("highContrastDisplay") + public val HIGH_CONTRAST_DISPLAY: Feature = Feature("highContrastDisplay") /** * The content has been formatted to meet large print guidelines. * * The property is not set if the font size can be increased. See DISPLAY_TRANSFORMABILITY. */ - val LARGE_PRINT = Feature("largePrint") + public val LARGE_PRINT: Feature = Feature("largePrint") /** * The content is in braille format, or alternatives are available in braille. */ - val BRAILLE = Feature("braille") + public val BRAILLE: Feature = Feature("braille") /** * When used with creative works such as books, indicates that the resource includes * tactile graphics. When used to describe an image resource or physical object, * indicates that the resource is a tactile graphic. */ - val TACTILE_GRAPHIC = Feature("tactileGraphic") + public val TACTILE_GRAPHIC: Feature = Feature("tactileGraphic") /** * When used with creative works such as books, indicates that the resource includes models * to generate tactile 3D objects. When used to describe a physical object, * indicates that the resource is a tactile 3D object. */ - val TACTILE_OBJECT = Feature("tactileObject") + public val TACTILE_OBJECT: Feature = Feature("tactileObject") /** * Indicates that the resource does not contain any accessibility features. */ - val NONE = Feature("none") + public val NONE: Feature = Feature("none") /** * Creates a list of [Feature] from its RWPM JSON representation. */ - fun fromJSONArray(json: JSONArray?): List = + public fun fromJSONArray(json: JSONArray?): List = json?.filterIsInstance(String::class.java) ?.map { Feature(it) } .orEmpty() - fun Set.toJSONArray(): JSONArray = + public fun Set.toJSONArray(): JSONArray = JSONArray(this.map(Feature::value)) } } @@ -473,19 +473,19 @@ data class Accessibility( */ @Parcelize @JvmInline - value class Hazard(val value: String) : Parcelable { + public value class Hazard(public val value: String) : Parcelable { - companion object { + public companion object { /** * Indicates that the resource presents a flashing hazard for photosensitive persons. */ - val FLASHING = Hazard("flashing") + public val FLASHING: Hazard = Hazard("flashing") /** * Indicates that the resource does not present a flashing hazard. */ - val NO_FLASHING_HAZARD = Hazard("noFlashingHazard") + public val NO_FLASHING_HAZARD: Hazard = Hazard("noFlashingHazard") /** * Indicates that the resource contains instances of motion simulation that @@ -494,44 +494,44 @@ data class Accessibility( * Some examples of motion simulation include video games with a first-person perspective * and CSS-controlled backgrounds that move when a user scrolls a page. */ - val MOTION_SIMULATION = Hazard("motionSimulation") + public val MOTION_SIMULATION: Hazard = Hazard("motionSimulation") /** * Indicates that the resource does not contain instances of motion simulation. * * See MOTION_SIMULATION. */ - val NO_MOTION_SIMULATION_HAZARD = Hazard("noMotionSimulationHazard") + public val NO_MOTION_SIMULATION_HAZARD: Hazard = Hazard("noMotionSimulationHazard") /** * Indicates that the resource contains auditory sounds that may affect some individuals. */ - val SOUND = Hazard("sound") + public val SOUND: Hazard = Hazard("sound") /** * Indicates that the resource does not contain auditory hazards. */ - val NO_SOUND_HAZARD = Hazard("noSoundHazard") + public val NO_SOUND_HAZARD: Hazard = Hazard("noSoundHazard") /** * Indicates that the author is not able to determine if the resource presents any hazards. */ - val UNKNOWN = Hazard("unknown") + public val UNKNOWN: Hazard = Hazard("unknown") /** * Indicates that the resource does not contain any hazards. */ - val NONE = Hazard("none") + public val NONE: Hazard = Hazard("none") /** * Creates a list of [Hazard] from its RWPM JSON representation. */ - fun fromJSONArray(json: JSONArray?): List = + public fun fromJSONArray(json: JSONArray?): List = json?.filterIsInstance(String::class.java) ?.map { Hazard(it) } .orEmpty() - fun Set.toJSONArray(): JSONArray = + public fun Set.toJSONArray(): JSONArray = JSONArray(this.map(Hazard::value)) } } @@ -546,14 +546,14 @@ data class Accessibility( putIfNotEmpty("feature", features.toJSONArray()) } - companion object { + public companion object { /** * Parses a [Accessibility] from its RWPM JSON representation. * * If the accessibility metadata can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON(json: Any?): Accessibility? { + public fun fromJSON(json: Any?): Accessibility? { if (json !is JSONObject) { return null } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Collection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Collection.kt index 2424c17af5..0e84b501c0 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Collection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Collection.kt @@ -13,4 +13,4 @@ package org.readium.r2.shared.publication * Collection type used for collection/series metadata. * For convenience, the JSON schema reuse the Contributor's definition. */ -typealias Collection = Contributor +public typealias Collection = Contributor diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/ContentLayout.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/ContentLayout.kt index 0677ba3cbe..2c8396f597 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/ContentLayout.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/ContentLayout.kt @@ -13,7 +13,6 @@ package org.readium.r2.shared.publication import android.os.Parcelable import kotlinx.parcelize.Parcelize -import org.readium.r2.shared.util.MapWithDefaultCompanion /** * The [ContentLayout] defines how a [Publication] should be laid out, based on the declared @@ -25,8 +24,8 @@ import org.readium.r2.shared.util.MapWithDefaultCompanion * @param cssId Identifier for this layout style, shared with ReadiumCSS. */ @Parcelize -@Deprecated("Use `Metadata.effectiveReadingProgression` instead", level = DeprecationLevel.WARNING) -enum class ContentLayout(val cssId: String) : Parcelable { +@Deprecated("Use `Metadata.effectiveReadingProgression` instead", level = DeprecationLevel.ERROR) +public enum class ContentLayout(private val cssId: String) : Parcelable { // Right to left RTL("rtl"), // Left to right @@ -35,16 +34,4 @@ enum class ContentLayout(val cssId: String) : Parcelable { CJK_VERTICAL("cjk-vertical"), // Asian language, horizontally laid out CJK_HORIZONTAL("cjk-horizontal"); - - companion object : MapWithDefaultCompanion(values(), ContentLayout::cssId, LTR) { - - @Deprecated("Renamed to [RTL]", ReplaceWith("ContentLayout.RTL")) - val rtl: ContentLayout = RTL - @Deprecated("Renamed to [LTR]", ReplaceWith("ContentLayout.LTR")) - val ltr: ContentLayout = LTR - @Deprecated("Renamed to [CJK_VERTICAL]", ReplaceWith("ContentLayout.CJK_VERTICAL")) - val cjkv: ContentLayout = CJK_VERTICAL - @Deprecated("Renamed to [CJK_HORIZONTAL]", ReplaceWith("ContentLayout.CJK_HORIZONTAL")) - val cjkh: ContentLayout = CJK_HORIZONTAL - } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Contributor.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Contributor.kt index cdd476d199..39416255ec 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Contributor.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Contributor.kt @@ -23,15 +23,15 @@ import org.readium.r2.shared.util.logging.log * https://readium.org/webpub-manifest/schema/contributor-object.schema.json * * @param localizedName The name of the contributor. + * @param localizedSortAs The string used to sort the name of the contributor. * @param identifier An unambiguous reference to this contributor. - * @param sortAs The string used to sort the name of the contributor. * @param roles The roles of the contributor in the publication making. * @param position The position of the publication in this collection/series, * when the contributor represents a collection. * @param links Used to retrieve similar publications for the given contributor. */ @Parcelize -data class Contributor( +public data class Contributor( val localizedName: LocalizedString, val localizedSortAs: LocalizedString? = null, val identifier: String? = null, @@ -43,7 +43,7 @@ data class Contributor( /** * Shortcut to create a [Contributor] using a string as [name]. */ - constructor(name: String) : this( + public constructor(name: String) : this( localizedName = LocalizedString(name) ) @@ -60,7 +60,7 @@ data class Contributor( /** * Serializes a [Subject] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { putIfNotEmpty("name", localizedName) put("identifier", identifier) putIfNotEmpty("sortAs", localizedSortAs) @@ -69,7 +69,7 @@ data class Contributor( putIfNotEmpty("links", links) } - companion object { + public companion object { /** * Parses a [Contributor] from its RWPM JSON representation. @@ -79,7 +79,7 @@ data class Contributor( * provided [normalizeHref] closure. * If the contributor can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON( + public fun fromJSON( json: Any?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -114,7 +114,7 @@ data class Contributor( * provided [normalizeHref] closure. * If a contributor can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSONArray( + public fun fromJSONArray( json: Any?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Link.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Link.kt index faddd21ea4..5d73e851e3 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Link.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Link.kt @@ -26,12 +26,13 @@ import org.readium.r2.shared.util.mediatype.MediaType * Function used to recursively transform the href of a [Link] when parsing its JSON * representation. */ -typealias LinkHrefNormalizer = (String) -> String + +public typealias LinkHrefNormalizer = (String) -> String /** * Default href normalizer for [Link], doing nothing. */ -val LinkHrefNormalizerIdentity: LinkHrefNormalizer = { it } +public val LinkHrefNormalizerIdentity: LinkHrefNormalizer = { it } /** * Link Object for the Readium Web Publication Manifest. @@ -53,7 +54,7 @@ val LinkHrefNormalizerIdentity: LinkHrefNormalizer = { it } * collection role. */ @Parcelize -data class Link( +public data class Link( val href: String, val type: String? = null, val templated: Boolean = false, @@ -89,7 +90,7 @@ data class Link( * * See RFC 6570 on URI template. */ - fun expandTemplate(parameters: Map): Link = + public fun expandTemplate(parameters: Map): Link = copy(href = URITemplate(href).expand(parameters), templated = false) /** @@ -97,7 +98,7 @@ data class Link( * * If the link's [href] is already absolute, the [baseUrl] is ignored. */ - fun toUrl(baseUrl: String?): String? { + public fun toUrl(baseUrl: String?): String? { val href = href.removePrefix("/") if (href.isBlank()) { return null @@ -128,10 +129,10 @@ data class Link( /** * Makes a copy of this [Link] after merging in the given additional other [properties]. */ - fun addProperties(properties: Map): Link = + public fun addProperties(properties: Map): Link = copy(properties = this.properties.add(properties)) - companion object { + public companion object { /** * Creates an [Link] from its RWPM JSON representation. @@ -139,7 +140,7 @@ data class Link( * [normalizeHref] closure. * If the link can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON( + public fun fromJSON( json: JSONObject?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -173,7 +174,7 @@ data class Link( * [normalizeHref] closure. * If a link can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSONArray( + public fun fromJSONArray( json: JSONArray?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -194,84 +195,84 @@ data class Link( /** * Returns the first [Link] with the given [href], or null if not found. */ -fun List.indexOfFirstWithHref(href: String): Int? = +public fun List.indexOfFirstWithHref(href: String): Int? = indexOfFirst { it.href == href } .takeUnless { it == -1 } /** * Finds the first link matching the given HREF. */ -fun List.firstWithHref(href: String): Link? = firstOrNull { it.href == href } +public fun List.firstWithHref(href: String): Link? = firstOrNull { it.href == href } /** * Finds the first link with the given relation. */ -fun List.firstWithRel(rel: String): Link? = firstOrNull { it.rels.contains(rel) } +public fun List.firstWithRel(rel: String): Link? = firstOrNull { it.rels.contains(rel) } /** * Finds all the links with the given relation. */ -fun List.filterByRel(rel: String): List = filter { it.rels.contains(rel) } +public fun List.filterByRel(rel: String): List = filter { it.rels.contains(rel) } /** * Finds the first link matching the given media type. */ -fun List.firstWithMediaType(mediaType: MediaType): Link? = firstOrNull { +public fun List.firstWithMediaType(mediaType: MediaType): Link? = firstOrNull { it.mediaType.matches(mediaType) } /** * Finds all the links matching the given media type. */ -fun List.filterByMediaType(mediaType: MediaType): List = filter { +public fun List.filterByMediaType(mediaType: MediaType): List = filter { it.mediaType.matches(mediaType) } /** * Finds all the links matching any of the given media types. */ -fun List.filterByMediaTypes(mediaTypes: List): List = filter { +public fun List.filterByMediaTypes(mediaTypes: List): List = filter { mediaTypes.any { mediaType -> mediaType.matches(it.type) } } /** * Returns whether all the resources in the collection are bitmaps. */ -val List.allAreBitmap: Boolean get() = isNotEmpty() && all { +public val List.allAreBitmap: Boolean get() = isNotEmpty() && all { it.mediaType.isBitmap } /** * Returns whether all the resources in the collection are audio clips. */ -val List.allAreAudio: Boolean get() = isNotEmpty() && all { +public val List.allAreAudio: Boolean get() = isNotEmpty() && all { it.mediaType.isAudio } /** * Returns whether all the resources in the collection are video clips. */ -val List.allAreVideo: Boolean get() = isNotEmpty() && all { +public val List.allAreVideo: Boolean get() = isNotEmpty() && all { it.mediaType.isVideo } /** * Returns whether all the resources in the collection are HTML documents. */ -val List.allAreHtml: Boolean get() = isNotEmpty() && all { +public val List.allAreHtml: Boolean get() = isNotEmpty() && all { it.mediaType.isHtml } /** * Returns whether all the resources in the collection are matching the given media type. */ -fun List.allMatchMediaType(mediaType: MediaType): Boolean = isNotEmpty() && all { +public fun List.allMatchMediaType(mediaType: MediaType): Boolean = isNotEmpty() && all { mediaType.matches(it.mediaType) } /** * Returns whether all the resources in the collection are matching any of the given media types. */ -fun List.allMatchMediaTypes(mediaTypes: List): Boolean = isNotEmpty() && all { +public fun List.allMatchMediaTypes(mediaTypes: List): Boolean = isNotEmpty() && all { mediaTypes.any { mediaType -> mediaType.matches(it.mediaType) } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/LocalizedString.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/LocalizedString.kt index 8169ebd555..e67de039c7 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/LocalizedString.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/LocalizedString.kt @@ -22,17 +22,17 @@ import org.readium.r2.shared.util.logging.log * Represents a string with multiple [translations] indexed by a BCP 47 language tag. */ @Parcelize -data class LocalizedString(val translations: Map = emptyMap()) : JSONable, Parcelable { +public data class LocalizedString(val translations: Map = emptyMap()) : JSONable, Parcelable { @Parcelize - data class Translation( + public data class Translation( val string: String ) : Parcelable /** * Shortcut to create a [LocalizedString] using a single string for a given language. */ - constructor(value: String, lang: String? = null) : this( + public constructor(value: String, lang: String? = null) : this( translations = mapOf(lang to Translation(string = value)) ) @@ -58,7 +58,7 @@ data class LocalizedString(val translations: Map = emptyMa * 3. on the English language * 4. the first translation found */ - fun getOrFallback(language: String?): Translation? { + public fun getOrFallback(language: String?): Translation? { return translations[language] ?: translations[Locale.getDefault().toLanguageTag()] ?: translations[null] @@ -71,42 +71,42 @@ data class LocalizedString(val translations: Map = emptyMa * Returns a new [LocalizedString] after adding (or replacing) the translation with the given * [language]. */ - fun copyWithString(language: String?, string: String): LocalizedString = + public fun copyWithString(language: String?, string: String): LocalizedString = copy(translations = translations + Pair(language, Translation(string = string))) /** * Returns a new [LocalizedString] after applying the [transform] function to each language. */ - fun mapLanguages(transform: (Map.Entry) -> String?): LocalizedString = + public fun mapLanguages(transform: (Map.Entry) -> String?): LocalizedString = copy(translations = translations.mapKeys(transform)) /** * Returns a new [LocalizedString] after applying the [transform] function to each translation. */ - fun mapTranslations(transform: (Map.Entry) -> Translation): LocalizedString = + public fun mapTranslations(transform: (Map.Entry) -> Translation): LocalizedString = copy(translations = translations.mapValues(transform)) /** * Serializes a [LocalizedString] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { for ((language, translation) in translations) { put(language ?: UNDEFINED_LANGUAGE, translation.string) } } - companion object { + public companion object { /** * BCP-47 tag for an undefined language. */ - const val UNDEFINED_LANGUAGE = "und" + public const val UNDEFINED_LANGUAGE: String = "und" /** * Shortcut to create a [LocalizedString] using a map of translations indexed by the BCP 47 * language tag. */ - fun fromStrings(strings: Map): LocalizedString = LocalizedString( + public fun fromStrings(strings: Map): LocalizedString = LocalizedString( translations = strings .mapValues { (_, string) -> Translation(string = string) } ) @@ -132,7 +132,7 @@ data class LocalizedString(val translations: Map = emptyMa * } * ] */ - fun fromJSON(json: Any?, warnings: WarningLogger? = null): LocalizedString? { + public fun fromJSON(json: Any?, warnings: WarningLogger? = null): LocalizedString? { json ?: return null return when (json) { @@ -145,7 +145,7 @@ data class LocalizedString(val translations: Map = emptyMa } } - private fun fromJSONObject(json: JSONObject, warnings: WarningLogger?): LocalizedString? { + private fun fromJSONObject(json: JSONObject, warnings: WarningLogger?): LocalizedString { val translations = mutableMapOf() for (key in json.keys()) { val string = json.optNullableString(key) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Locator.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Locator.kt index a658b86e32..3cd937d72c 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Locator.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Locator.kt @@ -33,7 +33,7 @@ import org.readium.r2.shared.util.logging.log * https://readium.org/architecture/models/locators/ */ @Parcelize -data class Locator( +public data class Locator( val href: String, val type: String, val title: String? = null, @@ -53,7 +53,7 @@ data class Locator( * @param otherLocations Additional locations for extensions. */ @Parcelize - data class Locations( + public data class Locations( val fragments: List = emptyList(), val progression: Double? = null, val position: Int? = null, @@ -61,7 +61,7 @@ data class Locator( val otherLocations: @WriteWith Map = emptyMap() ) : JSONable, Parcelable { - override fun toJSON() = JSONObject(otherLocations).apply { + override fun toJSON(): JSONObject = JSONObject(otherLocations).apply { putIfNotEmpty("fragments", fragments) put("progression", progression) put("position", position) @@ -72,11 +72,11 @@ data class Locator( * Syntactic sugar to access the [otherLocations] values by subscripting [Locations] directly. * `locations["cssSelector"] == locations.otherLocations["cssSelector"]` */ - operator fun get(key: String): Any? = otherLocations[key] + public operator fun get(key: String): Any? = otherLocations[key] - companion object { + public companion object { - fun fromJSON(json: JSONObject?): Locations { + public fun fromJSON(json: JSONObject?): Locations { val fragments = json?.optStringsFromArrayOrSingle("fragments", remove = true)?.takeIf { it.isNotEmpty() } ?: json?.optStringsFromArrayOrSingle("fragment", remove = true) ?: emptyList() @@ -100,7 +100,7 @@ data class Locator( } } - @Deprecated("Renamed to [fragments]", ReplaceWith("fragments")) + @Deprecated("Renamed to [fragments]", ReplaceWith("fragments"), level = DeprecationLevel.ERROR) val fragment: String? get() = fragments.firstOrNull() } @@ -116,19 +116,19 @@ data class Locator( * @param after The text after the locator. */ @Parcelize - data class Text( + public data class Text( val before: String? = null, val highlight: String? = null, val after: String? = null ) : JSONable, Parcelable { - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("before", before) put("highlight", highlight) put("after", after) } - fun substring(range: IntRange): Text { + public fun substring(range: IntRange): Text { highlight ?: return this return tryOr(this) { copy( @@ -139,9 +139,9 @@ data class Locator( } } - companion object { + public companion object { - fun fromJSON(json: JSONObject?) = Text( + public fun fromJSON(json: JSONObject?): Text = Text( before = json?.optNullableString("before"), highlight = json?.optNullableString("highlight"), after = json?.optNullableString("after") @@ -152,13 +152,13 @@ data class Locator( /** * Shortcut to get a copy of the [Locator] with different [Locations] sub-properties. */ - fun copyWithLocations( + public fun copyWithLocations( fragments: List = locations.fragments, progression: Double? = locations.progression, position: Int? = locations.position, totalProgression: Double? = locations.totalProgression, otherLocations: Map = locations.otherLocations - ) = copy( + ): Locator = copy( locations = locations.copy( fragments = fragments, progression = progression, @@ -168,7 +168,7 @@ data class Locator( ) ) - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("href", href) put("type", type) put("title", title) @@ -176,9 +176,9 @@ data class Locator( putIfNotEmpty("text", text) } - companion object { + public companion object { - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Locator? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Locator? { val href = json?.optNullableString("href") val type = json?.optNullableString("type") if (href == null || type == null) { @@ -195,11 +195,11 @@ data class Locator( ) } - fun fromJSONArray( + public fun fromJSONArray( json: JSONArray?, warnings: WarningLogger? = null ): List { - return json.parseObjects { Locator.fromJSON(it as? JSONObject, warnings) } + return json.parseObjects { fromJSON(it as? JSONObject, warnings) } } } } @@ -207,8 +207,8 @@ data class Locator( /** * Creates a [Locator] from a reading order [Link]. */ -@Deprecated("This may create an incorrect `Locator` if the link `type` is missing. Use `publication.locatorFromLink()` instead.") -fun Link.toLocator(): Locator { +@Deprecated("This may create an incorrect `Locator` if the link `type` is missing. Use `publication.locatorFromLink()` instead.", level = DeprecationLevel.ERROR) +public fun Link.toLocator(): Locator { val components = href.split("#", limit = 2) return Locator( href = components.firstOrNull() ?: href, @@ -226,7 +226,7 @@ fun Link.toLocator(): Locator { * For example, a search result or a list of positions. */ @Parcelize -data class LocatorCollection( +public data class LocatorCollection( val metadata: Metadata = Metadata(), val links: List = emptyList(), val locators: List = emptyList(), @@ -238,7 +238,7 @@ data class LocatorCollection( * @param numberOfItems Indicates the total number of locators in the collection. */ @Parcelize - data class Metadata( + public data class Metadata( val localizedTitle: LocalizedString? = null, val numberOfItems: Int? = null, val otherMetadata: @WriteWith Map = mapOf(), @@ -249,14 +249,14 @@ data class LocatorCollection( */ val title: String? get() = localizedTitle?.string - override fun toJSON() = JSONObject(otherMetadata).apply { + override fun toJSON(): JSONObject = JSONObject(otherMetadata).apply { putIfNotEmpty("title", localizedTitle) putOpt("numberOfItems", numberOfItems) } - companion object { + public companion object { - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Metadata { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Metadata { json ?: return Metadata() val localizedTitle = LocalizedString.fromJSON(json.remove("title"), warnings) @@ -271,15 +271,15 @@ data class LocatorCollection( } } - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { putIfNotEmpty("metadata", metadata.toJSON()) putIfNotEmpty("links", links.toJSON()) put("locators", locators.toJSON()) } - companion object { + public companion object { - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): LocatorCollection { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): LocatorCollection { return LocatorCollection( metadata = Metadata.fromJSON(json?.optJSONObject("metadata"), warnings), links = Link.fromJSONArray(json?.optJSONArray("links"), warnings = warnings), diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Manifest.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Manifest.kt index 184fd5567f..da33cba655 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Manifest.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Manifest.kt @@ -25,12 +25,10 @@ import org.readium.r2.shared.util.mediatype.MediaType /** * Holds the metadata of a Readium publication, as described in the Readium Web Publication Manifest. */ -data class Manifest( +public data class Manifest( val context: List = emptyList(), val metadata: Metadata, - // FIXME: Currently Readium requires to set the [Link] with [rel] "self" when adding it to the - // server. So we need to keep [links] as a mutable property. - var links: List = emptyList(), + val links: List = emptyList(), val readingOrder: List = emptyList(), val resources: List = emptyList(), val tableOfContents: List = emptyList(), @@ -41,7 +39,7 @@ data class Manifest( /** * Returns whether this manifest conforms to the given Readium Web Publication Profile. */ - fun conformsTo(profile: Publication.Profile): Boolean { + public fun conformsTo(profile: Publication.Profile): Boolean { if (readingOrder.isEmpty()) { return false } @@ -67,7 +65,7 @@ data class Manifest( * If there's no match, tries again after removing any query parameter and anchor from the * given [href]. */ - fun linkWithHref(href: String): Link? { + public fun linkWithHref(href: String): Link? { fun List.deepLinkWithHref(href: String): Link? { for (l in this) { if (l.href == href) @@ -93,7 +91,7 @@ data class Manifest( /** * Finds the first [Link] with the given relation in the manifest's links. */ - fun linkWithRel(rel: String): Link? = + public fun linkWithRel(rel: String): Link? = readingOrder.firstWithRel(rel) ?: resources.firstWithRel(rel) ?: links.firstWithRel(rel) @@ -101,7 +99,7 @@ data class Manifest( /** * Finds all [Link]s having the given [rel] in the manifest's links. */ - fun linksWithRel(rel: String): List = + public fun linksWithRel(rel: String): List = (readingOrder + resources + links).filterByRel(rel) /** @@ -109,7 +107,7 @@ data class Manifest( * * Returns null if the resource is not found in this manifest. */ - fun locatorFromLink(link: Link): Locator? { + public fun locatorFromLink(link: Link): Locator? { val components = link.href.split("#", limit = 2) val href = components.firstOrNull() ?: link.href val resourceLink = linkWithHref(href) ?: return null @@ -130,7 +128,7 @@ data class Manifest( /** * Serializes a [Publication] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { putIfNotEmpty("@context", context) put("metadata", metadata.toJSON()) put("links", links.toJSON()) @@ -145,7 +143,7 @@ data class Manifest( */ override fun toString(): String = toJSON().toString().replace("\\/", "/") - companion object { + public companion object { /** * Parses a [Manifest] from its RWPM JSON representation. @@ -154,7 +152,7 @@ data class Manifest( * https://readium.org/webpub-manifest/ * https://readium.org/webpub-manifest/schema/publication.schema.json */ - fun fromJSON( + public fun fromJSON( json: JSONObject?, packaged: Boolean = false, warnings: WarningLogger? = null diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Metadata.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Metadata.kt index ec760314e9..462e0694ae 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Metadata.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Metadata.kt @@ -29,7 +29,7 @@ import org.readium.r2.shared.util.logging.log * @param otherMetadata Additional metadata for extensions, as a JSON dictionary. */ @Parcelize -data class Metadata( +public data class Metadata( val identifier: String? = null, // URI val type: String? = null, // URI (@type) val conformsTo: Set = emptySet(), @@ -62,7 +62,7 @@ data class Metadata( val otherMetadata: @WriteWith Map = mapOf() ) : JSONable, Parcelable { - constructor( + public constructor( identifier: String? = null, // URI type: String? = null, // URI (@type) conformsTo: Set = emptySet(), @@ -197,7 +197,7 @@ data class Metadata( /** * Serializes a [Metadata] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject(otherMetadata).apply { + override fun toJSON(): JSONObject = JSONObject(otherMetadata).apply { put("identifier", identifier) put("@type", type) putIfNotEmpty("conformsTo", conformsTo.map { it.uri }) @@ -233,16 +233,16 @@ data class Metadata( * Syntactic sugar to access the [otherMetadata] values by subscripting [Metadata] directly. * `metadata["layout"] == metadata.otherMetadata["layout"]` */ - operator fun get(key: String): Any? = otherMetadata[key] + public operator fun get(key: String): Any? = otherMetadata[key] - companion object { + public companion object { /** * Parses a [Metadata] from its RWPM JSON representation. * * If the metadata can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON( + public fun fromJSON( json: JSONObject?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -341,7 +341,7 @@ data class Metadata( get() = localizedTitle @Deprecated("Use [localizedTitle.get] instead", ReplaceWith("localizedTitle.translationForLanguage(key)?.string"), level = DeprecationLevel.ERROR) - fun titleForLang(key: String): String? = + public fun titleForLang(key: String): String? = localizedTitle.getOrFallback(key)?.string @Deprecated("Use [readingProgression] instead.", ReplaceWith("readingProgression"), level = DeprecationLevel.ERROR) @@ -366,5 +366,5 @@ data class Metadata( val rights: String? get() = null @Deprecated("Renamed into [toJSON]", ReplaceWith("toJSON()")) - fun writeJSON(): JSONObject = toJSON() + public fun writeJSON(): JSONObject = toJSON() } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Properties.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Properties.kt index 3e97a2e932..742dd5782d 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Properties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Properties.kt @@ -24,19 +24,19 @@ import org.readium.r2.shared.extensions.toMap * https://readium.org/webpub-manifest/schema/link.schema.json */ @Parcelize -data class Properties( +public data class Properties( val otherProperties: @WriteWith Map = emptyMap() ) : JSONable, Parcelable { /** * Serializes a [Properties] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject(otherProperties) + override fun toJSON(): JSONObject = JSONObject(otherProperties) /** * Makes a copy of this [Properties] after merging in the given additional other [properties]. */ - fun add(properties: Map): Properties { + public fun add(properties: Map): Properties { val otherProperties = otherProperties.toMutableMap() otherProperties.putAll(properties) return copy(otherProperties = otherProperties) @@ -46,14 +46,14 @@ data class Properties( * Syntactic sugar to access the [otherProperties] values by subscripting [Properties] directly. * `properties["price"] == properties.otherProperties["price"]` */ - operator fun get(key: String): Any? = otherProperties[key] + public operator fun get(key: String): Any? = otherProperties[key] - companion object { + public companion object { /** * Creates a [Properties] from its RWPM JSON representation. */ - fun fromJSON(json: JSONObject?) = Properties( + public fun fromJSON(json: JSONObject?): Properties = Properties( otherProperties = json?.toMap() ?: emptyMap() ) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt index f97b90de75..f128e251b6 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt @@ -9,7 +9,6 @@ package org.readium.r2.shared.publication -import android.net.Uri import android.os.Parcelable import java.net.URL import kotlin.reflect.KClass @@ -37,7 +36,6 @@ import org.readium.r2.shared.publication.services.content.ContentService import org.readium.r2.shared.publication.services.search.SearchService import org.readium.r2.shared.util.Closeable import org.readium.r2.shared.util.SuspendingCloseable -import org.readium.r2.shared.util.mediatype.MediaType internal typealias ServiceFactory = (Publication.Service.Context) -> Publication.Service? @@ -49,7 +47,7 @@ internal typealias ServiceFactory = (Publication.Service.Context) -> Publication * We can't use publication.metadata.identifier directly because it might be null or not really * unique in the reading app. That's why sometimes we require an ID provided by the app. */ -typealias PublicationId = String +public typealias PublicationId = String /** * The Publication shared model is the entry-point for all the metadata and services @@ -61,14 +59,14 @@ typealias PublicationId = String * @param servicesBuilder Holds the list of service factories used to create the instances of * Publication.Service attached to this Publication. */ -class Publication( +public class Publication( manifest: Manifest, private val fetcher: Fetcher = EmptyFetcher(), private val servicesBuilder: ServicesBuilder = ServicesBuilder(), @Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) - var userSettingsUIPreset: MutableMap = mutableMapOf(), + public var userSettingsUIPreset: MutableMap = mutableMapOf(), @Deprecated("Migrate to the new Settings API (see migration guide)", level = DeprecationLevel.ERROR) - var cssStyle: String? = null, + public var cssStyle: String? = null, ) : PublicationServicesHolder { private val _manifest: Manifest @@ -82,79 +80,79 @@ class Publication( // Shortcuts to manifest properties - val context: List get() = _manifest.context - val metadata: Metadata get() = _manifest.metadata - val links: List get() = _manifest.links + public val context: List get() = _manifest.context + public val metadata: Metadata get() = _manifest.metadata + public val links: List get() = _manifest.links /** Identifies a list of resources in reading order for the publication. */ - val readingOrder: List get() = _manifest.readingOrder + public val readingOrder: List get() = _manifest.readingOrder /** Identifies resources that are necessary for rendering the publication. */ - val resources: List get() = _manifest.resources + public val resources: List get() = _manifest.resources /** Identifies the collection that contains a table of contents. */ - val tableOfContents: List get() = _manifest.tableOfContents + public val tableOfContents: List get() = _manifest.tableOfContents - val subcollections: Map> get() = _manifest.subcollections + public val subcollections: Map> get() = _manifest.subcollections @Deprecated("Use conformsTo() to check the kind of a publication.", level = DeprecationLevel.ERROR) - var type: TYPE = TYPE.EPUB + public var type: TYPE = TYPE.EPUB @Deprecated("Version is not available any more.", level = DeprecationLevel.ERROR) - var version: Double = 0.0 + public var version: Double = 0.0 /** * Returns the RWPM JSON representation for this [Publication]'s manifest, as a string. */ - val jsonManifest: String + public val jsonManifest: String get() = _manifest.toJSON().toString().replace("\\/", "/") /** * The URL where this publication is served, computed from the [Link] with `self` relation. */ - val baseUrl: URL? + public val baseUrl: URL? get() = links.firstWithRel("self") ?.let { it.href.toUrlOrNull()?.removeLastComponent() } /** * Returns whether this publication conforms to the given Readium Web Publication Profile. */ - fun conformsTo(profile: Profile): Boolean = + public fun conformsTo(profile: Profile): Boolean = _manifest.conformsTo(profile) /** * Finds the first [Link] with the given HREF in the publication's links. * * Searches through (in order) [readingOrder], [resources] and [links] recursively following - * [alternate] and [children] links. + * `alternate` and `children` links. * * If there's no match, tries again after removing any query parameter and anchor from the * given [href]. */ - fun linkWithHref(href: String): Link? = _manifest.linkWithHref(href) + public fun linkWithHref(href: String): Link? = _manifest.linkWithHref(href) /** * Finds the first [Link] having the given [rel] in the publications's links. */ - fun linkWithRel(rel: String): Link? = _manifest.linkWithRel(rel) + public fun linkWithRel(rel: String): Link? = _manifest.linkWithRel(rel) /** * Finds all [Link]s having the given [rel] in the publications's links. */ - fun linksWithRel(rel: String): List = _manifest.linksWithRel(rel) + public fun linksWithRel(rel: String): List = _manifest.linksWithRel(rel) /** * Creates a new [Locator] object from a [Link] to a resource of this publication. * * Returns null if the resource is not found in this publication. */ - fun locatorFromLink(link: Link): Locator? = _manifest.locatorFromLink(link) + public fun locatorFromLink(link: Link): Locator? = _manifest.locatorFromLink(link) /** * Returns the resource targeted by the given non-templated [link]. */ - fun get(link: Link): Fetcher.Resource { + public fun get(link: Link): Fetcher.Resource { if (DEBUG) { require(!link.templated) { "You must expand templated links before calling [Publication.get]" } } services.services.forEach { service -> service.get(link)?.let { return it } } @@ -182,7 +180,7 @@ class Publication( replaceWith = ReplaceWith("Publication.Profile"), level = DeprecationLevel.WARNING ) - enum class TYPE { + public enum class TYPE { EPUB } @@ -191,7 +189,7 @@ class Publication( replaceWith = ReplaceWith("Publication.Profile"), level = DeprecationLevel.ERROR ) - enum class EXTENSION(var value: String) { + public enum class EXTENSION(public var value: String) { EPUB(".epub"), CBZ(".cbz"), JSON(".json"), @@ -204,11 +202,10 @@ class Publication( /** * Sets the URL where this [Publication]'s RWPM manifest is served. */ - fun setSelfLink(href: String) { - _manifest.links = _manifest.links.toMutableList().apply { - removeAll { it.rels.contains("self") } - add(Link(href = href, type = MediaType.READIUM_WEBPUB_MANIFEST.toString(), rels = setOf("self"))) - } + @Deprecated(message = "Not used anymore.", level = DeprecationLevel.ERROR) + @Suppress("UNUSED_PARAMETER") + public fun setSelfLink(href: String) { + throw NotImplementedError() } /** @@ -218,7 +215,7 @@ class Publication( internal fun linksWithRole(role: String): List = subcollections[role]?.firstOrNull()?.links ?: emptyList() - companion object { + public companion object { /** * Creates the base URL for a [Publication] locally served through HTTP, from the @@ -230,7 +227,7 @@ class Publication( */ @Suppress("UNUSED_PARAMETER") @Deprecated("The HTTP server is not needed anymore (see migration guide)", level = DeprecationLevel.ERROR) - fun localBaseUrlOf(filename: String, port: Int): String { + public fun localBaseUrlOf(filename: String, port: Int): String { throw NotImplementedError() } @@ -239,7 +236,7 @@ class Publication( */ @Suppress("UNUSED_PARAMETER") @Deprecated("The HTTP server is not needed anymore (see migration guide)", level = DeprecationLevel.ERROR) - fun localUrlOf(filename: String, port: Int, href: String): String { + public fun localUrlOf(filename: String, port: Int, href: String): String { throw NotImplementedError() } @@ -252,7 +249,7 @@ class Publication( ), level = DeprecationLevel.ERROR ) - fun fromJSON( + public fun fromJSON( json: JSONObject?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity ): Publication? { @@ -267,31 +264,31 @@ class Publication( * https://readium.org/webpub-manifest/profiles/ */ @Parcelize - data class Profile(val uri: String) : Parcelable { - companion object { + public data class Profile(val uri: String) : Parcelable { + public companion object { /** Profile for EPUB publications. */ - val EPUB = Profile("https://readium.org/webpub-manifest/profiles/epub") + public val EPUB: Profile = Profile("https://readium.org/webpub-manifest/profiles/epub") /** Profile for audiobooks. */ - val AUDIOBOOK = Profile("https://readium.org/webpub-manifest/profiles/audiobook") + public val AUDIOBOOK: Profile = Profile("https://readium.org/webpub-manifest/profiles/audiobook") /** Profile for visual narratives (comics, manga and bandes dessinées). */ - val DIVINA = Profile("https://readium.org/webpub-manifest/profiles/divina") + public val DIVINA: Profile = Profile("https://readium.org/webpub-manifest/profiles/divina") /** Profile for PDF documents. */ - val PDF = Profile("https://readium.org/webpub-manifest/profiles/pdf") + public val PDF: Profile = Profile("https://readium.org/webpub-manifest/profiles/pdf") } } /** * Base interface to be implemented by all publication services. */ - interface Service : Closeable { + public interface Service : Closeable { /** * Container for the context from which a service is created. */ - class Context( - val manifest: Manifest, - val fetcher: Fetcher, - val services: PublicationServicesHolder + public class Context( + public val manifest: Manifest, + public val fetcher: Fetcher, + public val services: PublicationServicesHolder ) /** @@ -311,7 +308,7 @@ class Publication( * ) * ``` */ - val links: List get() = emptyList() + public val links: List get() = emptyList() /** * A service can return a Resource to: @@ -325,10 +322,10 @@ class Publication( * use the [Fetcher] provided by the [Publication.Service.Context] instead of * [Publication.get], otherwise it will trigger an infinite loop. * - * @return The [Resource] containing the response, or null if the service doesn't recognize - * this request. + * @return The [Fetcher.Resource] containing the response, or null if the service doesn't + * recognize this request. */ - fun get(link: Link): Fetcher.Resource? = null + public fun get(link: Link): Fetcher.Resource? = null /** * Closes any opened file handles, removes temporary files, etc. @@ -341,13 +338,13 @@ class Publication( * * Provides helpers to manipulate the list of services of a [Publication]. */ - class ServicesBuilder private constructor( + public class ServicesBuilder private constructor( private val serviceFactories: MutableMap ) { @OptIn(Search::class, ExperimentalReadiumApi::class) @Suppress("UNCHECKED_CAST") - constructor( + public constructor( cache: ServiceFactory? = null, content: ServiceFactory? = null, contentProtection: ServiceFactory? = null, @@ -368,7 +365,7 @@ class Publication( ) /** Builds the actual list of publication services to use in a Publication. */ - fun build(context: Service.Context): List { + public fun build(context: Service.Context): List { val serviceFactories = buildMap { putAll(this@ServicesBuilder.serviceFactories) @@ -391,13 +388,13 @@ class Publication( } /** Gets the publication service factory for the given service type. */ - operator fun get(serviceType: KClass): ServiceFactory? { + public operator fun get(serviceType: KClass): ServiceFactory? { val key = requireNotNull(serviceType.simpleName) return serviceFactories[key] } /** Sets the publication service factory for the given service type. */ - operator fun set(serviceType: KClass, factory: ServiceFactory?) { + public operator fun set(serviceType: KClass, factory: ServiceFactory?) { val key = requireNotNull(serviceType.simpleName) if (factory != null) { serviceFactories[key] = factory @@ -407,7 +404,7 @@ class Publication( } /** Removes the service factory producing the given kind of service, if any. */ - fun remove(serviceType: KClass) { + public fun remove(serviceType: KClass) { val key = requireNotNull(serviceType.simpleName) serviceFactories.remove(key) } @@ -416,7 +413,7 @@ class Publication( * Replaces the service factory associated with the given service type with the result of * [transform]. */ - fun decorate( + public fun decorate( serviceType: KClass, transform: ((ServiceFactory)?) -> ServiceFactory ) { @@ -428,14 +425,14 @@ class Publication( /** * Errors occurring while opening a Publication. */ - sealed class OpeningException : Error { + public sealed class OpeningException : Error { /** * The file format could not be recognized by any parser. */ - class UnsupportedAsset(override val cause: Error? = null) : OpeningException() { + public class UnsupportedAsset(override val cause: Error? = null) : OpeningException() { - constructor(message: String) : this(MessageError(message)) + public constructor(message: String) : this(MessageError(message)) override val message: String = "Asset is not supported." @@ -444,7 +441,7 @@ class Publication( /** * The publication file was not found on the file system. */ - class NotFound(override val cause: Error? = null) : OpeningException() { + public class NotFound(override val cause: Error? = null) : OpeningException() { override val message: String = "Asset couldn't be found." @@ -453,7 +450,7 @@ class Publication( /** * The publication parser failed with the given underlying exception. */ - class ParsingFailed(override val cause: Error? = null) : OpeningException() { + public class ParsingFailed(override val cause: Error? = null) : OpeningException() { override val message: String = "The asset is corrupted so the publication cannot be opened." @@ -462,7 +459,7 @@ class Publication( /** * We're not allowed to open the publication at all, for example because it expired. */ - class Forbidden(override val cause: Error? = null) : OpeningException() { + public class Forbidden(override val cause: Error? = null) : OpeningException() { override val message: String = "You are not allowed to open this publication." @@ -472,7 +469,7 @@ class Publication( * The publication can't be opened at the moment, for example because of a networking error. * This error is generally temporary, so the operation may be retried or postponed. */ - class Unavailable(override val cause: Error? = null) : OpeningException() { + public class Unavailable(override val cause: Error? = null) : OpeningException() { override val message: String = "Not available, please try again later." @@ -482,21 +479,21 @@ class Publication( * The provided credentials are incorrect and we can't open the publication in a * `restricted` state (e.g. for a password-protected ZIP). */ - class IncorrectCredentials(override val cause: Error? = null) : OpeningException() { + public class IncorrectCredentials(override val cause: Error? = null) : OpeningException() { override val message: String = "Provided credentials were incorrect." } - class OutOfMemory(override val cause: Error? = null) : OpeningException() { + public class OutOfMemory(override val cause: Error? = null) : OpeningException() { override val message: String = "There is not enough memory available to open device to read the publication." } - class Unexpected(override val cause: Error? = null) : OpeningException() { + public class Unexpected(override val cause: Error? = null) : OpeningException() { - constructor(exception: Exception) : this(ThrowableError(exception)) + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "An expected error occurred." @@ -509,13 +506,13 @@ class Publication( * A Publication's construction is distributed over the Streamer and its parsers, * so a builder is useful to pass the parts around. */ - class Builder( - var manifest: Manifest, - var fetcher: Fetcher, - var servicesBuilder: ServicesBuilder = ServicesBuilder() + public class Builder( + public var manifest: Manifest, + public var fetcher: Fetcher, + public var servicesBuilder: ServicesBuilder = ServicesBuilder() ) { - fun build(): Publication = Publication( + public fun build(): Publication = Publication( manifest = manifest, fetcher = fetcher, servicesBuilder = servicesBuilder @@ -526,99 +523,75 @@ class Publication( * Finds the first [Link] to the publication's cover (rel = cover). */ @Deprecated("Use [Publication.cover] to get the cover as a [Bitmap]", ReplaceWith("cover"), level = DeprecationLevel.ERROR) - val coverLink: Link? get() = linkWithRel("cover") + public val coverLink: Link? get() = linkWithRel("cover") /** * Copy the [Publication] with a different [PositionListFactory]. * The provided closure will be used to build the [PositionListFactory], with this being the * [Publication]. */ - @Suppress("DEPRECATION", "UNUSED_PARAMETER") @Deprecated("Use [Publication.copy(serviceFactories)] instead", ReplaceWith("Publication.copy(serviceFactories = listOf(positionsServiceFactory)"), level = DeprecationLevel.ERROR) - fun copyWithPositionsFactory(): Publication { + public fun copyWithPositionsFactory(): Publication { throw NotImplementedError() } @Deprecated("Renamed to [listOfAudioClips]", ReplaceWith("listOfAudioClips"), level = DeprecationLevel.ERROR) - val listOfAudioFiles: List = listOfAudioClips + public val listOfAudioFiles: List = listOfAudioClips @Deprecated("Renamed to [listOfVideoClips]", ReplaceWith("listOfVideoClips"), level = DeprecationLevel.ERROR) - val listOfVideos: List = listOfVideoClips + public val listOfVideos: List = listOfVideoClips @Deprecated("Renamed to [linkWithHref]", ReplaceWith("linkWithHref(href)"), level = DeprecationLevel.ERROR) - fun resource(href: String): Link? = linkWithHref(href) + public fun resource(href: String): Link? = linkWithHref(href) @Deprecated("Refactored as a property", ReplaceWith("baseUrl"), level = DeprecationLevel.ERROR) - fun baseUrl(): URL? = baseUrl + public fun baseUrl(): URL? = baseUrl @Deprecated("Renamed [subcollections]", ReplaceWith("subcollections"), level = DeprecationLevel.ERROR) - val otherCollections: Map> get() = subcollections + public val otherCollections: Map> get() = subcollections @Deprecated("Use [setSelfLink] instead", ReplaceWith("setSelfLink"), level = DeprecationLevel.ERROR) - fun addSelfLink(endPoint: String, baseURL: URL) { - setSelfLink( - Uri.parse(baseURL.toString()) - .buildUpon() - .appendEncodedPath("$endPoint/manifest.json") - .build() - .toString() - ) + @Suppress("UNUSED_PARAMETER") + public fun addSelfLink(endPoint: String, baseURL: URL) { + throw NotImplementedError() } - /** - * Finds the first resource [Link] (asset or [readingOrder] item) at the given relative path. - */ @Deprecated("Use [linkWithHref] instead.", ReplaceWith("linkWithHref(href)"), level = DeprecationLevel.ERROR) - fun resourceWithHref(href: String): Link? = linkWithHref(href) + public fun resourceWithHref(href: String): Link? = linkWithHref(href) - /** - * Creates a [Publication]'s [positions]. - * - * The parsers provide an implementation of this interface for each format, but a host app - * might want to use a custom factory to implement, for example, a caching mechanism or use a - * different calculation method. - */ @Deprecated("Use a [ServiceFactory] for a [PositionsService] instead.", level = DeprecationLevel.ERROR) - interface PositionListFactory { - fun create(): List + public interface PositionListFactory { + public fun create(): List } - /** - * Finds the first [Link] matching the given [predicate] in the publications's [Link] - * properties: [resources], [readingOrder] and [links]. - * - * Searches through (in order) [readingOrder], [resources] and [links] - * recursively following [alternate] and [children] links. - * The search order is unspecified. - */ @Deprecated("Use [linkWithHref()] to find a link with the given HREF", replaceWith = ReplaceWith("linkWithHref"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - fun link(predicate: (Link) -> Boolean): Link? = null + public fun link(predicate: (Link) -> Boolean): Link? = null - @Deprecated("Use [jsonManifest] instead", ReplaceWith("jsonManifest")) - fun toJSON() = JSONObject(jsonManifest) + @Deprecated("Use [jsonManifest] instead", ReplaceWith("jsonManifest"), level = DeprecationLevel.ERROR) + public fun toJSON(): JSONObject = JSONObject(jsonManifest) @Deprecated("Use `metadata.effectiveReadingProgression` instead", ReplaceWith("metadata.effectiveReadingProgression"), level = DeprecationLevel.ERROR) - val contentLayout: ReadingProgression get() = metadata.effectiveReadingProgression + public val contentLayout: ReadingProgression get() = metadata.effectiveReadingProgression @Deprecated("Use `metadata.effectiveReadingProgression` instead", ReplaceWith("metadata.effectiveReadingProgression"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - fun contentLayoutForLanguage(language: String?) = metadata.effectiveReadingProgression + public fun contentLayoutForLanguage(language: String?): ReadingProgression = metadata.effectiveReadingProgression } /** * Holds [Publication.Service] instances for a [Publication]. */ -interface PublicationServicesHolder : SuspendingCloseable { +public interface PublicationServicesHolder : SuspendingCloseable { /** * Returns the first publication service that is an instance of [serviceType]. */ - fun findService(serviceType: KClass): T? + public fun findService(serviceType: KClass): T? /** * Returns all the publication services that are instances of [serviceType]. */ - fun findServices(serviceType: KClass): List + public fun findServices(serviceType: KClass): List } internal class ListPublicationServicesHolder( diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/PublicationCollection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/PublicationCollection.kt index 86ade0f660..0831f93305 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/PublicationCollection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/PublicationCollection.kt @@ -29,7 +29,7 @@ import org.readium.r2.shared.util.logging.log * Can be used as extension point in the Readium Web Publication Manifest. */ @Parcelize -data class PublicationCollection( +public data class PublicationCollection( val metadata: @WriteWith Map = emptyMap(), val links: List = emptyList(), val subcollections: Map> = emptyMap() @@ -38,13 +38,13 @@ data class PublicationCollection( /** * Serializes a [PublicationCollection] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("metadata", metadata) putIfNotEmpty("links", links) subcollections.appendToJSONObject(this) } - companion object { + public companion object { /** * Parses a [PublicationCollection] from its RWPM JSON representation. @@ -53,7 +53,7 @@ data class PublicationCollection( * The [links]' href and their children's will be normalized recursively using the * provided [normalizeHref] closure. */ - fun fromJSON( + public fun fromJSON( json: Any?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -102,7 +102,7 @@ data class PublicationCollection( * The [links]' href and their children's will be normalized recursively using the * provided [normalizeHref] closure. */ - fun collectionsFromJSON( + public fun collectionsFromJSON( json: JSONObject, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -150,9 +150,9 @@ internal fun Map>.appendToJSONObject(jsonObj } @Deprecated("Use [subcollections[role].firstOrNull()] instead", ReplaceWith("subcollections[role].firstOrNull()")) -fun Map>.firstWithRole(role: String): PublicationCollection? = +public fun Map>.firstWithRole(role: String): PublicationCollection? = get(role)?.firstOrNull() @Deprecated("Use [subcollections[role]] instead", ReplaceWith("subcollections[role]")) -fun Map>.findAllWithRole(role: String): List = +public fun Map>.findAllWithRole(role: String): List = get(role) ?: emptyList() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/ReadingProgression.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/ReadingProgression.kt index 38910ec267..932b8d4119 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/ReadingProgression.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/ReadingProgression.kt @@ -18,13 +18,13 @@ import org.readium.r2.shared.util.MapCompanion @Serializable @Parcelize -enum class ReadingProgression(val value: String) : Parcelable { +public enum class ReadingProgression(public val value: String) : Parcelable { /** Right to left */ @SerialName("rtl") RTL("rtl"), /** Left to right */ @SerialName("ltr") LTR("ltr"); - companion object : MapCompanion(values(), ReadingProgression::value) { + public companion object : MapCompanion(values(), ReadingProgression::value) { override fun get(key: String?): ReadingProgression? = // For backward compatibility, we allow uppercase keys. diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Subject.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Subject.kt index 749c1a506b..83bcd27392 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Subject.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Subject.kt @@ -23,13 +23,13 @@ import org.readium.r2.shared.util.logging.log /** * https://github.com/readium/webpub-manifest/tree/master/contexts/default#subjects * - * @param sortAs Provides a string that a machine can sort. + * @param localizedSortAs Provides a string that a machine can sort. * @param scheme EPUB 3.1 opf:authority. * @param code EPUB 3.1 opf:term. * @param links Used to retrieve similar publications for the given subjects. */ @Parcelize -data class Subject( +public data class Subject( val localizedName: LocalizedString, val localizedSortAs: LocalizedString? = null, val scheme: String? = null, @@ -40,7 +40,7 @@ data class Subject( /** * Shortcut to create a [Subject] using a string as [name]. */ - constructor(name: String) : this( + public constructor(name: String) : this( localizedName = LocalizedString(name) ) @@ -57,7 +57,7 @@ data class Subject( /** * Serializes a [Subject] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { putIfNotEmpty("name", localizedName) putIfNotEmpty("sortAs", localizedSortAs) put("scheme", scheme) @@ -65,7 +65,7 @@ data class Subject( putIfNotEmpty("links", links) } - companion object { + public companion object { /** * Parses a [Subject] from its RWPM JSON representation. @@ -75,7 +75,7 @@ data class Subject( * provided [normalizeHref] closure. * If the subject can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON( + public fun fromJSON( json: Any?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null @@ -109,7 +109,7 @@ data class Subject( * provided [normalizeHref] closure. * If a subject can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSONArray( + public fun fromJSONArray( json: Any?, normalizeHref: LinkHrefNormalizer = LinkHrefNormalizerIdentity, warnings: WarningLogger? = null diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/archive/Properties.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/archive/Properties.kt index a26fb2c8d0..75d5466b5f 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/archive/Properties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/archive/Properties.kt @@ -27,7 +27,7 @@ import org.readium.r2.shared.util.logging.log * archive. */ @Parcelize -data class ArchiveProperties( +public data class ArchiveProperties( val entryLength: Long, val isEntryCompressed: Boolean ) : JSONable, Parcelable { @@ -37,8 +37,8 @@ data class ArchiveProperties( put("isEntryCompressed", isEntryCompressed) } - companion object { - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): ArchiveProperties? { + public companion object { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): ArchiveProperties? { json ?: return null val entryLength = json.optNullableLong("entryLength") @@ -56,6 +56,6 @@ data class ArchiveProperties( /** * Provides information about how the resource is stored in the publication archive. */ -val Properties.archive: ArchiveProperties? +public val Properties.archive: ArchiveProperties? get() = (this["archive"] as? Map<*, *>) ?.let { ArchiveProperties.fromJSON(JSONObject(it)) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Encryption.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Encryption.kt index 7d7d32e61f..c1f2064432 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Encryption.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Encryption.kt @@ -30,7 +30,7 @@ import org.readium.r2.shared.util.logging.log * @param scheme Identifies the encryption scheme used to encrypt the resource (URI). */ @Parcelize -data class Encryption( +public data class Encryption( val algorithm: String, val compression: String? = null, val originalLength: Long? = null, @@ -41,7 +41,7 @@ data class Encryption( /** * Serializes an [Encryption] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("algorithm", algorithm) put("compression", compression) put("originalLength", originalLength) @@ -49,13 +49,13 @@ data class Encryption( put("scheme", scheme) } - companion object { + public companion object { /** * Creates an [Encryption] from its RWPM JSON representation. * If the encryption can't be parsed, a warning will be logged with [warnings]. */ - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Encryption? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Encryption? { val algorithm = json?.optNullableString("algorithm") if (algorithm.isNullOrEmpty()) { warnings?.log(Encryption::class.java, "[algorithm] is required", json) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Properties.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Properties.kt index c9ce898145..ef88f2bcb2 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Properties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/encryption/Properties.kt @@ -18,6 +18,6 @@ import org.readium.r2.shared.publication.Properties * Indicates that a resource is encrypted/obfuscated and provides relevant information for * decryption. */ -val Properties.encryption: Encryption? +public val Properties.encryption: Encryption? get() = (this["encrypted"] as? Map<*, *>) ?.let { Encryption.fromJSON(JSONObject(it)) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/EpubLayout.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/EpubLayout.kt index 8222e5faa7..bd77d50ea3 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/EpubLayout.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/EpubLayout.kt @@ -18,15 +18,15 @@ import org.readium.r2.shared.util.MapCompanion * https://readium.org/webpub-manifest/schema/extensions/epub/metadata.schema.json */ @Parcelize -enum class EpubLayout(val value: String) : Parcelable { +public enum class EpubLayout(public val value: String) : Parcelable { FIXED("fixed"), REFLOWABLE("reflowable"); - companion object : MapCompanion(values(), EpubLayout::value) { + public companion object : MapCompanion(values(), EpubLayout::value) { - @Deprecated("Renamed to [FIXED]", ReplaceWith("EpubLayout.FIXED")) - val Fixed: EpubLayout get() = FIXED - @Deprecated("Renamed to [REFLOWABLE]", ReplaceWith("EpubLayout.REFLOWABLE")) - val Reflowable: EpubLayout get() = REFLOWABLE + @Deprecated("Renamed to [FIXED]", ReplaceWith("EpubLayout.FIXED"), level = DeprecationLevel.ERROR) + public val Fixed: EpubLayout get() = FIXED + @Deprecated("Renamed to [REFLOWABLE]", ReplaceWith("EpubLayout.REFLOWABLE"), level = DeprecationLevel.ERROR) + public val Reflowable: EpubLayout get() = REFLOWABLE } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Presentation.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Presentation.kt index 98bf50a747..6bf6f2a1e8 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Presentation.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Presentation.kt @@ -16,7 +16,7 @@ import org.readium.r2.shared.publication.presentation.Presentation * Get the layout of the given resource in this publication. * Falls back on REFLOWABLE. */ -fun Presentation.layoutOf(link: Link): EpubLayout { +public fun Presentation.layoutOf(link: Link): EpubLayout { return link.properties.layout ?: layout ?: EpubLayout.REFLOWABLE diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Properties.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Properties.kt index c1c2f3c1df..76de4043d4 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Properties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Properties.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.publication.Properties * Identifies content contained in the linked resource, that cannot be strictly identified using a * media type. */ -val Properties.contains: Set +public val Properties.contains: Set get() = (this["contains"] as? List<*>) ?.filterIsInstance(String::class.java) ?.toSet() @@ -27,5 +27,5 @@ val Properties.contains: Set /** * Hints how the layout of the resource should be presented. */ -val Properties.layout: EpubLayout? +public val Properties.layout: EpubLayout? get() = EpubLayout(this["layout"] as? String) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Publication.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Publication.kt index eb6ec49479..a369a11fc7 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Publication.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/epub/Publication.kt @@ -20,15 +20,15 @@ import org.readium.r2.shared.publication.Publication * Provides navigation to positions in the Publication content that correspond to the locations of * page boundaries present in a print source being represented by this EPUB Publication. */ -val Publication.pageList: List get() = linksWithRole("pageList") +public val Publication.pageList: List get() = linksWithRole("pageList") /** * Identifies fundamental structural components of the publication in order to enable Reading * Systems to provide the User efficient access to them. */ -val Publication.landmarks: List get() = linksWithRole("landmarks") +public val Publication.landmarks: List get() = linksWithRole("landmarks") -val Publication.listOfAudioClips: List get() = linksWithRole("loa") -val Publication.listOfIllustrations: List get() = linksWithRole("loi") -val Publication.listOfTables: List get() = linksWithRole("lot") -val Publication.listOfVideoClips: List get() = linksWithRole("lov") +public val Publication.listOfAudioClips: List get() = linksWithRole("loa") +public val Publication.listOfIllustrations: List get() = linksWithRole("loi") +public val Publication.listOfTables: List get() = linksWithRole("lot") +public val Publication.listOfVideoClips: List get() = linksWithRole("lov") diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/html/DomRange.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/html/DomRange.kt index 0d39ee26de..4ef0ef951d 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/html/DomRange.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/html/DomRange.kt @@ -40,7 +40,7 @@ import org.readium.r2.shared.util.logging.log * @param end A serializable representation of the "end" boundary point of the DOM Range. */ @Parcelize -data class DomRange( +public data class DomRange( val start: Point, val end: Point? = null ) : JSONable, Parcelable { @@ -61,21 +61,21 @@ data class DomRange( * https://github.com/readium/architecture/blob/master/models/locators/extensions/html.md#the-start-and-end-object */ @Parcelize - data class Point( + public data class Point( val cssSelector: String, val textNodeIndex: Int, val charOffset: Int? = null ) : JSONable, Parcelable { - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("cssSelector", cssSelector) put("textNodeIndex", textNodeIndex) put("charOffset", charOffset) } - companion object { + public companion object { - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Point? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): Point? { val cssSelector = json?.optNullableString("cssSelector") val textNodeIndex = json?.optPositiveInt("textNodeIndex") if (cssSelector == null || textNodeIndex == null) { @@ -99,14 +99,14 @@ data class DomRange( val offset: Long? get() = charOffset?.toLong() } - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { putIfNotEmpty("start", start) putIfNotEmpty("end", end) } - companion object { + public companion object { - fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): DomRange? { + public fun fromJSON(json: JSONObject?, warnings: WarningLogger? = null): DomRange? { val start = Point.fromJSON(json?.optJSONObject("start")) if (start == null) { warnings?.log(DomRange::class.java, "[start] is required", json) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/html/Locator.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/html/Locator.kt index 9d0d517cda..74928cb663 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/html/Locator.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/html/Locator.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.publication.Locator /** * A CSS Selector. */ -val Locator.Locations.cssSelector: String? +public val Locator.Locations.cssSelector: String? get() = this["cssSelector"] as? String /** @@ -28,12 +28,12 @@ val Locator.Locations.cssSelector: String? * epubcfi(***) syntax is not used for the [partialCfi] string, i.e. the "fragment" part of the CFI * grammar is ignored. */ -val Locator.Locations.partialCfi: String? +public val Locator.Locations.partialCfi: String? get() = this["partialCfi"] as? String /** * An HTML DOM range. */ -val Locator.Locations.domRange: DomRange? +public val Locator.Locations.domRange: DomRange? get() = (this["domRange"] as? Map<*, *>) ?.let { DomRange.fromJSON(JSONObject(it)) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Properties.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Properties.kt index d308094ed5..55def66d7e 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Properties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Properties.kt @@ -20,14 +20,14 @@ import org.readium.r2.shared.publication.Properties /** * Provides a hint about the expected number of items returned. */ -val Properties.numberOfItems: Int? +public val Properties.numberOfItems: Int? get() = (this["numberOfItems"] as? Int) ?.takeIf { it >= 0 } /** * The price of a publication is tied to its acquisition link. */ -val Properties.price: Price? +public val Properties.price: Price? get() = (this["price"] as? Map<*, *>) ?.let { Price.fromJSON(JSONObject(it)) } @@ -35,7 +35,7 @@ val Properties.price: Price? * Indirect acquisition provides a hint for the expected media type that will be acquired after * additional steps. */ -val Properties.indirectAcquisitions: List +public val Properties.indirectAcquisitions: List get() = (this["indirectAcquisition"] as? List<*>) ?.mapNotNull { if (it !is Map<*, *>) { @@ -47,27 +47,27 @@ val Properties.indirectAcquisitions: List ?: emptyList() @Deprecated("Use [indirectAcquisitions] instead.", ReplaceWith("indirectAcquisitions")) -val Properties.indirectAcquisition: List +public val Properties.indirectAcquisition: List get() = indirectAcquisitions /** * Library-specific features when a specific book is unavailable but provides a hold list. */ -val Properties.holds: Holds? +public val Properties.holds: Holds? get() = (this["holds"] as? Map<*, *>) ?.let { Holds.fromJSON(JSONObject(it)) } /** * Library-specific feature that contains information about the copies that a library has acquired. */ -val Properties.copies: Copies? +public val Properties.copies: Copies? get() = (this["copies"] as? Map<*, *>) ?.let { Copies.fromJSON(JSONObject(it)) } /** * Indicated the availability of a given resource. */ -val Properties.availability: Availability? +public val Properties.availability: Availability? get() = (this["availability"] as? Map<*, *>) ?.let { Availability.fromJSON(JSONObject(it)) } @@ -77,6 +77,6 @@ val Properties.availability: Availability? * * See https://drafts.opds.io/authentication-for-opds-1.0.html */ -val Properties.authenticate: Link? +public val Properties.authenticate: Link? get() = (this["authenticate"] as? Map<*, *>) ?.let { Link.fromJSON(JSONObject(it)) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Publication.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Publication.kt index 2846d867c0..8803978b40 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Publication.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/opds/Publication.kt @@ -14,4 +14,4 @@ import org.readium.r2.shared.publication.Publication // OPDS extensions for [Publication] -val Publication.images: List get() = linksWithRole("images") +public val Publication.images: List get() = linksWithRole("images") diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Metadata.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Metadata.kt index 8ee3358449..2ba7bb03a4 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Metadata.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Metadata.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.publication.Metadata // Presentation extensions for [Metadata] -val Metadata.presentation: Presentation +public val Metadata.presentation: Presentation get() = Presentation.fromJSON( (this["presentation"] as? Map<*, *>) ?.let { JSONObject(it) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Presentation.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Presentation.kt index c06cc66501..f7f840a854 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Presentation.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Presentation.kt @@ -27,12 +27,12 @@ import org.readium.r2.shared.util.MapCompanion * https://readium.org/webpub-manifest/schema/extensions/presentation/metadata.schema.json * * These properties are nullable to avoid having default values when it doesn't make sense for a - * given [Publication]. If a navigator needs a default value when not specified, + * given publication. If a navigator needs a default value when not specified, * Presentation.DEFAULT_X and Presentation.X.DEFAULT can be used. * * @param clipped Specifies whether or not the parts of a linked resource that flow out of the * viewport are clipped. - * @param continuous Indicates how the progression between resources from the [readingOrder] should + * @param continuous Indicates how the progression between resources from the reading order should * be handled. * @param fit Suggested method for constraining a resource inside the viewport. * @param orientation Suggested orientation for the device when displaying the linked resource. @@ -42,7 +42,7 @@ import org.readium.r2.shared.util.MapCompanion * @param layout Hints how the layout of the resource should be presented (EPUB extension). */ @Parcelize -data class Presentation( +public data class Presentation( val clipped: Boolean? = null, val continuous: Boolean? = null, val fit: Fit? = null, @@ -55,7 +55,7 @@ data class Presentation( /** * Serializes a [Presentation] to its RWPM JSON representation. */ - override fun toJSON() = JSONObject().apply { + override fun toJSON(): JSONObject = JSONObject().apply { put("clipped", clipped) put("continuous", continuous) put("fit", fit?.value) @@ -65,22 +65,22 @@ data class Presentation( put("layout", layout?.value) } - companion object { + public companion object { /** * Default value for [clipped], if not specified. */ - const val DEFAULT_CLIPPED = false + public const val DEFAULT_CLIPPED: Boolean = false /** * Default value for [continuous], if not specified. */ - const val DEFAULT_CONTINUOUS = true + public const val DEFAULT_CONTINUOUS: Boolean = true /** * Creates a [Properties] from its RWPM JSON representation. */ - fun fromJSON(json: JSONObject?): Presentation { + public fun fromJSON(json: JSONObject?): Presentation { if (json == null) { return Presentation() } @@ -101,18 +101,18 @@ data class Presentation( */ @Parcelize @Serializable - enum class Fit(val value: String) : Parcelable { + public enum class Fit(public val value: String) : Parcelable { @SerialName("width") WIDTH("width"), @SerialName("height") HEIGHT("height"), @SerialName("contain") CONTAIN("contain"), @SerialName("cover") COVER("cover"); - companion object : MapCompanion(values(), Fit::value) { + public companion object : MapCompanion(values(), Fit::value) { /** * Default value for [Fit], if not specified. */ - val DEFAULT = CONTAIN + public val DEFAULT: Fit = CONTAIN } } @@ -121,24 +121,24 @@ data class Presentation( */ @Parcelize @Serializable - enum class Orientation(val value: String) : Parcelable { + public enum class Orientation(public val value: String) : Parcelable { @SerialName("auto") AUTO("auto"), @SerialName("landscape") LANDSCAPE("landscape"), @SerialName("portrait") PORTRAIT("portrait"); - companion object : MapCompanion(values(), Orientation::value) { + public companion object : MapCompanion(values(), Orientation::value) { /** * Default value for [Orientation], if not specified. */ - val DEFAULT = AUTO - - @Deprecated("Renamed to [AUTO]", ReplaceWith("Orientation.AUTO")) - val Auto: Orientation = AUTO - @Deprecated("Renamed to [LANDSCAPE]", ReplaceWith("Orientation.LANDSCAPE")) - val Landscape: Orientation = LANDSCAPE - @Deprecated("Renamed to [PORTRAIT]", ReplaceWith("Orientation.PORTRAIT")) - val Portrait: Orientation = PORTRAIT + public val DEFAULT: Orientation = AUTO + + @Deprecated("Renamed to [AUTO]", ReplaceWith("Orientation.AUTO"), level = DeprecationLevel.ERROR) + public val Auto: Orientation = AUTO + @Deprecated("Renamed to [LANDSCAPE]", ReplaceWith("Orientation.LANDSCAPE"), level = DeprecationLevel.ERROR) + public val Landscape: Orientation = LANDSCAPE + @Deprecated("Renamed to [PORTRAIT]", ReplaceWith("Orientation.PORTRAIT"), level = DeprecationLevel.ERROR) + public val Portrait: Orientation = PORTRAIT } } @@ -147,24 +147,24 @@ data class Presentation( */ @Parcelize @Serializable - enum class Overflow(val value: String) : Parcelable { + public enum class Overflow(public val value: String) : Parcelable { @SerialName("auto") AUTO("auto"), @SerialName("paginated") PAGINATED("paginated"), @SerialName("scrolled") SCROLLED("scrolled"); - companion object : MapCompanion(values(), Overflow::value) { + public companion object : MapCompanion(values(), Overflow::value) { /** * Default value for [Overflow], if not specified. */ - val DEFAULT = AUTO - - @Deprecated("Renamed to [PAGINATED]", ReplaceWith("Overflow.PAGINATED")) - val Paginated: Overflow = PAGINATED - @Deprecated("Use [presentation.continuous] instead", ReplaceWith("presentation.continuous")) - val Continuous: Overflow = SCROLLED - @Deprecated("Renamed to [SCROLLED]", ReplaceWith("Overflow.SCROLLED")) - val Document: Overflow = SCROLLED + public val DEFAULT: Overflow = AUTO + + @Deprecated("Renamed to [PAGINATED]", ReplaceWith("Overflow.PAGINATED"), level = DeprecationLevel.ERROR) + public val Paginated: Overflow = PAGINATED + @Deprecated("Use [presentation.continuous] instead", ReplaceWith("presentation.continuous"), level = DeprecationLevel.ERROR) + public val Continuous: Overflow = SCROLLED + @Deprecated("Renamed to [SCROLLED]", ReplaceWith("Overflow.SCROLLED"), level = DeprecationLevel.ERROR) + public val Document: Overflow = SCROLLED } } @@ -174,12 +174,12 @@ data class Presentation( */ @Parcelize @Serializable - enum class Page(val value: String) : Parcelable { + public enum class Page(public val value: String) : Parcelable { @SerialName("left") LEFT("left"), @SerialName("right") RIGHT("right"), @SerialName("center") CENTER("center"); - companion object : MapCompanion(values(), Page::value) + public companion object : MapCompanion(values(), Page::value) } /** @@ -188,35 +188,35 @@ data class Presentation( */ @Parcelize @Serializable - enum class Spread(val value: String) : Parcelable { + public enum class Spread(public val value: String) : Parcelable { @SerialName("auto") AUTO("auto"), @SerialName("both") BOTH("both"), @SerialName("none") NONE("none"), @SerialName("landscape") LANDSCAPE("landscape"); - companion object : MapCompanion(values(), Spread::value) { + public companion object : MapCompanion(values(), Spread::value) { /** * Default value for [Spread], if not specified. */ - val DEFAULT = AUTO - - @Deprecated("Renamed to [AUTO]", ReplaceWith("Spread.AUTO")) - val Auto: Spread = AUTO - @Deprecated("Renamed to [LANDSCAPE]", ReplaceWith("Spread.LANDSCAPE")) - val Landscape: Spread = LANDSCAPE - @Deprecated("Renamed to [BOTH]", ReplaceWith("Spread.BOTH")) - val Portrait: Spread = BOTH - @Deprecated("Renamed to [BOTH]", ReplaceWith("Spread.BOTH")) - val Both: Spread = BOTH - @Deprecated("Renamed to [NONE]", ReplaceWith("Spread.NONE")) - val None: Spread = NONE + public val DEFAULT: Spread = AUTO + + @Deprecated("Renamed to [AUTO]", ReplaceWith("Spread.AUTO"), level = DeprecationLevel.ERROR) + public val Auto: Spread = AUTO + @Deprecated("Renamed to [LANDSCAPE]", ReplaceWith("Spread.LANDSCAPE"), level = DeprecationLevel.ERROR) + public val Landscape: Spread = LANDSCAPE + @Deprecated("Renamed to [BOTH]", ReplaceWith("Spread.BOTH"), level = DeprecationLevel.ERROR) + public val Portrait: Spread = BOTH + @Deprecated("Renamed to [BOTH]", ReplaceWith("Spread.BOTH"), level = DeprecationLevel.ERROR) + public val Both: Spread = BOTH + @Deprecated("Renamed to [NONE]", ReplaceWith("Spread.NONE"), level = DeprecationLevel.ERROR) + public val None: Spread = NONE } } - @Deprecated("Use [toJSON] instead", ReplaceWith("toJSON()")) - fun getJSON(): JSONObject = toJSON() + @Deprecated("Use [toJSON] instead", ReplaceWith("toJSON()"), level = DeprecationLevel.ERROR) + public fun getJSON(): JSONObject = toJSON() - @Deprecated("Use [overflow] instead", ReplaceWith("overflow")) + @Deprecated("Use [overflow] instead", ReplaceWith("overflow"), level = DeprecationLevel.ERROR) val flow: Overflow? get() = overflow } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Properties.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Properties.kt index 8b94ab72ce..823e7c9a64 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Properties.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/presentation/Properties.kt @@ -16,37 +16,37 @@ import org.readium.r2.shared.publication.Properties * Specifies whether or not the parts of a linked resource that flow out of the viewport are * clipped. */ -val Properties.clipped: Boolean? +public val Properties.clipped: Boolean? get() = this["clipped"] as? Boolean /** * Suggested method for constraining a resource inside the viewport. */ -val Properties.fit: Presentation.Fit? +public val Properties.fit: Presentation.Fit? get() = Presentation.Fit(this["fit"] as? String) /** * Suggested orientation for the device when displaying the linked resource. */ -val Properties.orientation: Presentation.Orientation? +public val Properties.orientation: Presentation.Orientation? get() = Presentation.Orientation(this["orientation"] as? String) /** * Suggested method for handling overflow while displaying the linked resource. */ -val Properties.overflow: Presentation.Overflow? +public val Properties.overflow: Presentation.Overflow? get() = Presentation.Overflow(this["overflow"] as? String) /** * Indicates how the linked resource should be displayed in a reading environment that displays * synthetic spreads. */ -val Properties.page: Presentation.Page? +public val Properties.page: Presentation.Page? get() = Presentation.Page(this["page"] as? String) /** * Indicates the condition to be met for the linked resource to be rendered within a synthetic * spread. */ -val Properties.spread: Presentation.Spread? +public val Properties.spread: Presentation.Spread? get() = Presentation.Spread(this["spread"] as? String) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt index 34e47cd2f1..6872b4656b 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt @@ -6,6 +6,7 @@ package org.readium.r2.shared.publication.protection +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.asset.Asset import org.readium.r2.shared.error.Try import org.readium.r2.shared.fetcher.ContainerFetcher @@ -23,7 +24,8 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever * [ContentProtection] implementation used as a fallback by the Streamer to detect Adept DRM, * if it is not supported by the app. */ -class AdeptFallbackContentProtection( +@InternalReadiumApi +public class AdeptFallbackContentProtection( private val mediaTypeRetriever: MediaTypeRetriever = MediaTypeRetriever() ) : ContentProtection { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt index a1284d153f..19d73530f6 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt @@ -26,14 +26,14 @@ import org.readium.r2.shared.util.mediatype.MediaType * - Create a [Fetcher] one can access the publication through. * - Create a [ContentProtectionService] publication service. */ -interface ContentProtection { +public interface ContentProtection { - val scheme: Scheme + public val scheme: Scheme /** * Returns if this [ContentProtection] supports the given [asset]. */ - suspend fun supports( + public suspend fun supports( asset: org.readium.r2.shared.asset.Asset ): Boolean @@ -43,7 +43,7 @@ interface ContentProtection { * @return A [Asset] in case of success or a [Publication.OpeningException] if the * asset can't be successfully opened even in restricted mode. */ - suspend fun open( + public suspend fun open( asset: org.readium.r2.shared.asset.Asset, credentials: String?, allowUserInteraction: Boolean, @@ -60,7 +60,7 @@ interface ContentProtection { * It can be used to modify the `Manifest`, the root [Fetcher] or the list of service factories * of a [Publication]. */ - data class Asset( + public data class Asset( val name: String, val mediaType: MediaType, val fetcher: Fetcher, @@ -71,34 +71,38 @@ interface ContentProtection { * Represents a specific Content Protection technology, uniquely identified with an [uri]. */ @JvmInline - value class Scheme( - val uri: String, + public value class Scheme( + public val uri: String, ) { @Deprecated("Define yourself the name to print to users.", level = DeprecationLevel.ERROR) - val name: LocalizedString? get() = null + public val name: LocalizedString? get() = null - companion object { + public companion object { /** Readium LCP DRM scheme. */ - val Lcp = Scheme(uri = "http://readium.org/2014/01/lcp") + public val Lcp: Scheme = Scheme(uri = "http://readium.org/2014/01/lcp") /** Adobe ADEPT DRM scheme. */ - val Adept = Scheme(uri = "http://ns.adobe.com/adept") + public val Adept: Scheme = Scheme(uri = "http://ns.adobe.com/adept") } } - sealed class Exception( + public sealed class Exception( userMessageId: Int, vararg args: Any?, quantity: Int? = null, cause: Throwable? = null ) : UserException(userMessageId, quantity, *args, cause = cause) { - constructor(@StringRes userMessageId: Int, vararg args: Any?, cause: Throwable? = null) : this(userMessageId, *args, quantity = null, cause = cause) + protected constructor( + @StringRes userMessageId: Int, + vararg args: Any?, + cause: Throwable? = null + ) : this(userMessageId, *args, quantity = null, cause = cause) /** * Exception returned when the given Content Protection [scheme] is not supported by the * app. */ - class SchemeNotSupported(val scheme: Scheme? = null, name: String?) : Exception( + public class SchemeNotSupported(public val scheme: Scheme? = null, name: String?) : Exception( if (name == null) R.string.readium_shared_publication_content_protection_exception_not_supported_unknown else R.string.readium_shared_publication_content_protection_exception_not_supported, name diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtectionSchemeRetriever.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtectionSchemeRetriever.kt index d1f1bb982c..a1c0d2f087 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtectionSchemeRetriever.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtectionSchemeRetriever.kt @@ -12,7 +12,7 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever /** * Retrieves [ContentProtection] schemes of assets. */ -class ContentProtectionSchemeRetriever( +public class ContentProtectionSchemeRetriever( contentProtections: List, mediaTypeRetriever: MediaTypeRetriever ) { @@ -22,7 +22,7 @@ class ContentProtectionSchemeRetriever( AdeptFallbackContentProtection(mediaTypeRetriever) ) - suspend fun retrieve(asset: Asset): ContentProtection.Scheme? = + public suspend fun retrieve(asset: Asset): ContentProtection.Scheme? = contentProtections .firstOrNull { it.supports(asset) } ?.scheme diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt index 6a2cedf84d..96dd67a829 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt @@ -7,6 +7,7 @@ package org.readium.r2.shared.publication.protection import org.json.JSONObject +import org.readium.r2.shared.InternalReadiumApi import org.readium.r2.shared.asset.Asset import org.readium.r2.shared.error.Try import org.readium.r2.shared.fetcher.ContainerFetcher @@ -27,7 +28,8 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever * [ContentProtection] implementation used as a fallback by the Streamer to detect LCP DRM * if it is not supported by the app. */ -class LcpFallbackContentProtection( +@InternalReadiumApi +public class LcpFallbackContentProtection( private val mediaTypeRetriever: MediaTypeRetriever = MediaTypeRetriever() ) : ContentProtection { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CacheService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CacheService.kt index 4289256a1c..35b073ca4d 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CacheService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CacheService.kt @@ -26,20 +26,20 @@ import org.readium.r2.shared.util.cache.InMemoryCache * Provides publication-bound caches. */ @InternalReadiumApi -interface CacheService : Publication.Service { +public interface CacheService : Publication.Service { /** * Gets the cache for objects of [valueType] in the given [namespace]. */ - suspend fun cacheOf(valueType: KClass, namespace: String): Cache + public suspend fun cacheOf(valueType: KClass, namespace: String): Cache } @InternalReadiumApi -val PublicationServicesHolder.cacheService: CacheService? +public val PublicationServicesHolder.cacheService: CacheService? get() = findService(CacheService::class) /** Factory to build a [CacheService]. */ @InternalReadiumApi -var Publication.ServicesBuilder.cacheServiceFactory: ServiceFactory? +public var Publication.ServicesBuilder.cacheServiceFactory: ServiceFactory? get() = get(CacheService::class) set(value) = set(CacheService::class, value) @@ -47,10 +47,10 @@ var Publication.ServicesBuilder.cacheServiceFactory: ServiceFactory? * A basic [CacheService] implementation keeping the cached objects in memory. */ @InternalReadiumApi -class InMemoryCacheService(context: Context?) : CacheService, MemoryObserver { +public class InMemoryCacheService(context: Context?) : CacheService, MemoryObserver { - companion object { - fun createFactory(context: Context?): (Publication.Service.Context) -> InMemoryCacheService = { _ -> + public companion object { + public fun createFactory(context: Context?): (Publication.Service.Context) -> InMemoryCacheService = { _ -> InMemoryCacheService(context) } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/ContentProtectionService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/ContentProtectionService.kt index 86fc8feba8..e8ce551179 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/ContentProtectionService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/ContentProtectionService.kt @@ -28,39 +28,39 @@ import org.readium.r2.shared.resource.Resource /** * Provides information about a publication's content protection and manages user rights. */ -interface ContentProtectionService : Publication.Service { +public interface ContentProtectionService : Publication.Service { /** * Whether the [Publication] has a restricted access to its resources, and can't be rendered in * a Navigator. */ - val isRestricted: Boolean + public val isRestricted: Boolean /** * The error raised when trying to unlock the [Publication], if any. */ - val error: UserException? + public val error: UserException? /** * Credentials used to unlock this [Publication]. */ - val credentials: String? + public val credentials: String? /** * Manages consumption of user rights and permissions. */ - val rights: UserRights + public val rights: UserRights /** * Known technology for this type of Content Protection. */ - val scheme: ContentProtection.Scheme? get() = null + public val scheme: ContentProtection.Scheme? get() = null /** * User-facing name for this Content Protection, e.g. "Readium LCP". * It could be used in a sentence such as "Protected by {name}" */ - val name: LocalizedString? get() = null + public val name: LocalizedString? get() = null override val links: List get() = RouteHandler.links @@ -73,7 +73,7 @@ interface ContentProtectionService : Publication.Service { /** * Manages consumption of user rights and permissions. */ - interface UserRights { + public interface UserRights { /** * Returns whether the user is currently allowed to copy content to the pasteboard. @@ -82,7 +82,7 @@ interface ContentProtectionService : Publication.Service { * out or not. This should be called every time the "Copy" action will be displayed, * because the value might change during runtime. */ - val canCopy: Boolean + public val canCopy: Boolean /** * Returns whether the user is allowed to copy the given text to the pasteboard. @@ -93,14 +93,14 @@ interface ContentProtectionService : Publication.Service { * To be used before presenting, for example, a pop-up to share a selected portion of * content. */ - fun canCopy(text: String): Boolean + public fun canCopy(text: String): Boolean /** * Consumes the given text with the copy right. * * Returns whether the user is allowed to copy the given text. */ - fun copy(text: String): Boolean + public fun copy(text: String): Boolean /** * Returns whether the user is currently allowed to print the content. @@ -108,7 +108,7 @@ interface ContentProtectionService : Publication.Service { * Navigators and reading apps can use this to know if the "Print" action should be greyed * out or not. */ - val canPrint: Boolean + public val canPrint: Boolean /** * Returns whether the user is allowed to print the given amount of pages. @@ -118,19 +118,19 @@ interface ContentProtectionService : Publication.Service { * * To be used before attempting to launch a print job, for example. */ - fun canPrint(pageCount: Int): Boolean + public fun canPrint(pageCount: Int): Boolean /** * Consumes the given amount of pages with the print right. * * Returns whether the user is allowed to print the given amount of pages. */ - fun print(pageCount: Int): Boolean + public fun print(pageCount: Int): Boolean /** * A [UserRights] without any restriction. */ - object Unrestricted : UserRights { + public object Unrestricted : UserRights { override val canCopy: Boolean = true override fun canCopy(text: String): Boolean = true @@ -147,7 +147,7 @@ interface ContentProtectionService : Publication.Service { /** * A [UserRights] which forbids any right. */ - object AllRestricted : UserRights { + public object AllRestricted : UserRights { override val canCopy: Boolean = false override fun canCopy(text: String): Boolean = false @@ -173,61 +173,61 @@ private val PublicationServicesHolder.protectionService: ContentProtectionServic } /** Factory to build a [ContentProtectionService]. */ -var Publication.ServicesBuilder.contentProtectionServiceFactory: ServiceFactory? +public var Publication.ServicesBuilder.contentProtectionServiceFactory: ServiceFactory? get() = get(ContentProtectionService::class) set(value) = set(ContentProtectionService::class, value) /** * Returns whether this Publication is protected by a Content Protection technology. */ -val Publication.isProtected: Boolean +public val Publication.isProtected: Boolean get() = protectionService != null /** * Whether the [Publication] has a restricted access to its resources, and can't be rendered in * a Navigator. */ -val Publication.isRestricted: Boolean +public val Publication.isRestricted: Boolean get() = protectionService?.isRestricted ?: false /** * The error raised when trying to unlock the [Publication], if any. */ -val Publication.protectionError: UserException? +public val Publication.protectionError: UserException? get() = protectionService?.error /** * Credentials used to unlock this [Publication]. */ -val Publication.credentials: String? +public val Publication.credentials: String? get() = protectionService?.credentials /** * Manages consumption of user rights and permissions. */ -val Publication.rights: ContentProtectionService.UserRights +public val Publication.rights: ContentProtectionService.UserRights get() = protectionService?.rights ?: ContentProtectionService.UserRights.Unrestricted /** * Known technology for this type of Content Protection. */ -val Publication.protectionScheme: ContentProtection.Scheme? +public val Publication.protectionScheme: ContentProtection.Scheme? get() = protectionService?.scheme /** * User-facing localized name for this Content Protection, e.g. "Readium LCP". * It could be used in a sentence such as "Protected by {name}". */ -val Publication.protectionLocalizedName: LocalizedString? +public val Publication.protectionLocalizedName: LocalizedString? get() = protectionService?.name /** * User-facing name for this Content Protection, e.g. "Readium LCP". * It could be used in a sentence such as "Protected by {name}". */ -val Publication.protectionName: String? +public val Publication.protectionName: String? get() = protectionLocalizedName?.string private sealed class RouteHandler { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CoverService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CoverService.kt index 6fb569e0d6..89038aa276 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CoverService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/CoverService.kt @@ -39,19 +39,19 @@ import org.readium.r2.shared.publication.ServiceFactory * - generating a bitmap from scratch using the publication's title * - using a cover selected by the user. */ -interface CoverService : Publication.Service { +public interface CoverService : Publication.Service { /** * Returns the publication cover as a [Bitmap] at its maximum size. * * If the cover is not a bitmap format (e.g. SVG), it should be scaled down to fit the screen. */ - suspend fun cover(): Bitmap? + public suspend fun cover(): Bitmap? /** * Returns the publication cover as a [Bitmap], scaled down to fit the given [maxSize]. */ - suspend fun coverFitting(maxSize: Size): Bitmap? = cover()?.scaleToFit(maxSize) + public suspend fun coverFitting(maxSize: Size): Bitmap? = cover()?.scaleToFit(maxSize) } private suspend fun Publication.coverFromManifest(): Bitmap? { @@ -65,7 +65,7 @@ private suspend fun Publication.coverFromManifest(): Bitmap? { /** * Returns the publication cover as a [Bitmap] at its maximum size. */ -suspend fun Publication.cover(): Bitmap? { +public suspend fun Publication.cover(): Bitmap? { findService(CoverService::class)?.cover()?.let { return it } return coverFromManifest() } @@ -73,20 +73,20 @@ suspend fun Publication.cover(): Bitmap? { /** * Returns the publication cover as a [Bitmap], scaled down to fit the given [maxSize]. */ -suspend fun Publication.coverFitting(maxSize: Size): Bitmap? { +public suspend fun Publication.coverFitting(maxSize: Size): Bitmap? { findService(CoverService::class)?.coverFitting(maxSize)?.let { return it } return coverFromManifest()?.scaleToFit(maxSize) } /** Factory to build a [CoverService]. */ -var Publication.ServicesBuilder.coverServiceFactory: ServiceFactory? +public var Publication.ServicesBuilder.coverServiceFactory: ServiceFactory? get() = get(CoverService::class) set(value) = set(CoverService::class, value) /** * A [CoverService] which provides a unique cover for each Publication. */ -abstract class GeneratedCoverService : CoverService { +public abstract class GeneratedCoverService : CoverService { private val coverLink = Link( href = "/~readium/cover", @@ -121,10 +121,10 @@ abstract class GeneratedCoverService : CoverService { /** * A [CoverService] which uses a provided in-memory bitmap. */ -class InMemoryCoverService internal constructor(private val cover: Bitmap) : GeneratedCoverService() { +public class InMemoryCoverService internal constructor(private val cover: Bitmap) : GeneratedCoverService() { - companion object { - fun createFactory(cover: Bitmap?): ServiceFactory? = { cover?.let { InMemoryCoverService(it) } } + public companion object { + public fun createFactory(cover: Bitmap?): ServiceFactory = { cover?.let { InMemoryCoverService(it) } } } override suspend fun cover(): Bitmap = cover diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/LocatorService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/LocatorService.kt index 4b5ef8741e..b79fcfb62d 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/LocatorService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/LocatorService.kt @@ -18,34 +18,34 @@ import timber.log.Timber * - Converting a [Locator] which was created from an alternate manifest with a different reading * order. For example, when downloading a streamed manifest or offloading a package. */ -interface LocatorService : Publication.Service { +public interface LocatorService : Publication.Service { /** Locates the target of the given [locator]. */ - suspend fun locate(locator: Locator): Locator? + public suspend fun locate(locator: Locator): Locator? /** Locates the target at the given [totalProgression] relative to the whole publication. */ - suspend fun locateProgression(totalProgression: Double): Locator? + public suspend fun locateProgression(totalProgression: Double): Locator? } /** Locates the target of the given [locator]. */ -suspend fun Publication.locate(locator: Locator): Locator? = +public suspend fun Publication.locate(locator: Locator): Locator? = findService(LocatorService::class)?.locate(locator) -/** Locates the target at the given [progression] relative to the whole publication. */ -suspend fun Publication.locateProgression(totalProgression: Double): Locator? = +/** Locates the target at the given progression relative to the whole publication. */ +public suspend fun Publication.locateProgression(totalProgression: Double): Locator? = findService(LocatorService::class)?.locateProgression(totalProgression) /** Factory to build a [LocatorService] */ -var Publication.ServicesBuilder.locatorServiceFactory: ServiceFactory? +public var Publication.ServicesBuilder.locatorServiceFactory: ServiceFactory? get() = get(LocatorService::class) set(value) = set(LocatorService::class, value) -open class DefaultLocatorService( - val readingOrder: List, - val positionsByReadingOrder: suspend () -> List> +public open class DefaultLocatorService( + public val readingOrder: List, + public val positionsByReadingOrder: suspend () -> List> ) : LocatorService { - constructor(readingOrder: List, services: PublicationServicesHolder) : + public constructor(readingOrder: List, services: PublicationServicesHolder) : this(readingOrder, positionsByReadingOrder = { services.findService(PositionsService::class)?.positionsByReadingOrder() ?: emptyList() }) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/PositionsService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/PositionsService.kt index 143585e2f0..8db28c716f 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/PositionsService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/PositionsService.kt @@ -27,19 +27,19 @@ private val positionsLink = Link( /** * Provides a list of discrete locations in the publication, no matter what the original format is. */ -interface PositionsService : Publication.Service { +public interface PositionsService : Publication.Service { /** * Returns the list of all the positions in the publication, grouped by the resource reading order index. */ - suspend fun positionsByReadingOrder(): List> + public suspend fun positionsByReadingOrder(): List> /** * Returns the list of all the positions in the publication. */ - suspend fun positions(): List = positionsByReadingOrder().flatten() + public suspend fun positions(): List = positionsByReadingOrder().flatten() - override val links get() = listOf(positionsLink) + override val links: List get() = listOf(positionsLink) override fun get(link: Link): Fetcher.Resource? { if (link.href != positionsLink.href) @@ -58,7 +58,7 @@ interface PositionsService : Publication.Service { /** * Returns the list of all the positions in the publication, grouped by the resource reading order index. */ -suspend fun PublicationServicesHolder.positionsByReadingOrder(): List> { +public suspend fun PublicationServicesHolder.positionsByReadingOrder(): List> { checkNotNull(findService(PositionsService::class)) { "No position service found." } .let { return it.positionsByReadingOrder() } } @@ -66,7 +66,7 @@ suspend fun PublicationServicesHolder.positionsByReadingOrder(): List { +public suspend fun PublicationServicesHolder.positions(): List { checkNotNull(findService(PositionsService::class)) { "No position service found." } .let { return it.positions() } } @@ -75,11 +75,11 @@ suspend fun PublicationServicesHolder.positions(): List { * List of all the positions in each resource, indexed by their href. */ @Deprecated("Use [positionsByReadingOrder] instead", ReplaceWith("positionsByReadingOrder")) -val Publication.positionsByResource: Map> +public val Publication.positionsByResource: Map> get() = runBlocking { positions().groupBy { it.href } } /** Factory to build a [PositionsService] */ -var Publication.ServicesBuilder.positionsServiceFactory: ServiceFactory? +public var Publication.ServicesBuilder.positionsServiceFactory: ServiceFactory? get() = get(PositionsService::class) set(value) = set(PositionsService::class, value) @@ -90,7 +90,7 @@ var Publication.ServicesBuilder.positionsServiceFactory: ServiceFactory? * @param fallbackMediaType Media type that will be used as a fallback if the Link doesn't specify * any. */ -class PerResourcePositionsService( +public class PerResourcePositionsService( private val readingOrder: List, private val fallbackMediaType: String ) : PositionsService { @@ -113,9 +113,9 @@ class PerResourcePositionsService( } } - companion object { + public companion object { - fun createFactory(fallbackMediaType: String): (Publication.Service.Context) -> PerResourcePositionsService = { + public fun createFactory(fallbackMediaType: String): (Publication.Service.Context) -> PerResourcePositionsService = { PerResourcePositionsService( readingOrder = it.manifest.readingOrder, fallbackMediaType = fallbackMediaType diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/Content.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/Content.kt index d28ce9328d..6c32329506 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/Content.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/Content.kt @@ -17,17 +17,17 @@ import org.readium.r2.shared.util.Language * Provides an iterable list of content [Element]s. */ @ExperimentalReadiumApi -interface Content { +public interface Content { /** * Represents a single semantic content element part of a publication. */ @ExperimentalReadiumApi - interface Element : AttributesHolder { + public interface Element : AttributesHolder { /** * Locator targeting this element in the Publication. */ - val locator: Locator + public val locator: Locator } /** @@ -35,26 +35,26 @@ interface Content { * * The default implementation returns the first accessibility label associated to the element. */ - interface TextualElement : Element { + public interface TextualElement : Element { /** Human-readable text representation for this element. */ - val text: String? get() = accessibilityLabel + public val text: String? get() = accessibilityLabel } /** An element referencing an embedded external resource. */ - interface EmbeddedElement : Element { + public interface EmbeddedElement : Element { /** Referenced resource in the publication. */ - val embeddedLink: Link + public val embeddedLink: Link } /** An audio clip. */ - data class AudioElement( + public data class AudioElement( override val locator: Locator, override val embeddedLink: Link, override val attributes: List> = emptyList(), ) : EmbeddedElement, TextualElement /** A video clip. */ - data class VideoElement( + public data class VideoElement( override val locator: Locator, override val embeddedLink: Link, override val attributes: List> = emptyList(), @@ -65,7 +65,7 @@ interface Content { * * @param caption Short piece of text associated with the image. */ - data class ImageElement( + public data class ImageElement( override val locator: Locator, override val embeddedLink: Link, val caption: String?, @@ -85,7 +85,7 @@ interface Content { * @param role Purpose of this element in the broader context of the document. * @param segments Ranged portions of text with associated attributes. */ - data class TextElement( + public data class TextElement( override val locator: Locator, val role: Role, val segments: List, @@ -98,23 +98,23 @@ interface Content { /** * Represents a purpose of an element in the broader context of the document. */ - interface Role { + public interface Role { /** * Title of a section. * * @param level Heading importance, 1 being the highest. */ - data class Heading(val level: Int) : Role + public data class Heading(val level: Int) : Role /** * Normal body of content. */ - object Body : Role + public object Body : Role /** * A footnote at the bottom of a document. */ - object Footnote : Role + public object Footnote : Role /** * A quotation. @@ -122,7 +122,7 @@ interface Content { * @param referenceUrl URL to the source for this quote. * @param referenceTitle Name of the source for this quote. */ - data class Quote( + public data class Quote( val referenceUrl: URL?, val referenceTitle: String? ) : Role @@ -135,7 +135,7 @@ interface Content { * @param text Text in the segment. * @param attributes Attributes associated with this segment, e.g. language. */ - data class Segment( + public data class Segment( val locator: Locator, val text: String, override val attributes: List>, @@ -145,7 +145,7 @@ interface Content { /** * An attribute is an arbitrary key-value metadata pair. */ - data class Attribute( + public data class Attribute( val key: AttributeKey, val value: V ) @@ -155,41 +155,41 @@ interface Content { * * The [V] phantom type is there to perform static type checking when requesting an attribute. */ - data class AttributeKey(val id: String) { - companion object { - val ACCESSIBILITY_LABEL = AttributeKey("accessibilityLabel") - val LANGUAGE = AttributeKey("language") + public data class AttributeKey(val id: String) { + public companion object { + public val ACCESSIBILITY_LABEL: AttributeKey = AttributeKey("accessibilityLabel") + public val LANGUAGE: AttributeKey = AttributeKey("language") } } /** * An object associated with a list of attributes. */ - interface AttributesHolder { + public interface AttributesHolder { /** * Associated list of attributes. */ - val attributes: List> + public val attributes: List> - val language: Language? + public val language: Language? get() = attribute(AttributeKey.LANGUAGE) - val accessibilityLabel: String? + public val accessibilityLabel: String? get() = attribute(AttributeKey.ACCESSIBILITY_LABEL) /** * Gets the first attribute with the given [key]. */ @Suppress("UNCHECKED_CAST") - fun attribute(key: AttributeKey): V? = + public fun attribute(key: AttributeKey): V? = attributes.firstOrNull { it.key == key }?.value as V /** * Gets all the attributes with the given [key]. */ @Suppress("UNCHECKED_CAST") - fun attributes(key: AttributeKey): List = + public fun attributes(key: AttributeKey): List = attributes .filter { it.key == key } .map { it.value as V } @@ -202,44 +202,44 @@ interface Content { * to any of both methods. */ @ExperimentalReadiumApi - interface Iterator { + public interface Iterator { /** * Returns true if the iterator has a next element, suspending the caller while processing * it. */ - suspend operator fun hasNext(): Boolean + public suspend operator fun hasNext(): Boolean /** * Retrieves the element computed by a preceding call to [hasNext], or throws an * [IllegalStateException] if [hasNext] was not invoked. This method should only be used in * pair with [hasNext]. */ - operator fun next(): Element + public operator fun next(): Element /** * Advances to the next item and returns it, or null if we reached the end. */ - suspend fun nextOrNull(): Element? = + public suspend fun nextOrNull(): Element? = if (hasNext()) next() else null /** * Returns true if the iterator has a previous element, suspending the caller while processing * it. */ - suspend fun hasPrevious(): Boolean + public suspend fun hasPrevious(): Boolean /** * Retrieves the element computed by a preceding call to [hasPrevious], or throws an * [IllegalStateException] if [hasPrevious] was not invoked. This method should only be used in * pair with [hasPrevious]. */ - fun previous(): Element + public fun previous(): Element /** * Advances to the previous item and returns it, or null if we reached the beginning. */ - suspend fun previousOrNull(): Element? = + public suspend fun previousOrNull(): Element? = if (hasPrevious()) previous() else null } @@ -247,7 +247,7 @@ interface Content { * Extracts the full raw text, or returns null if no text content can be found. * @param separator Separator to use between individual elements. Defaults to newline. */ - suspend fun text(separator: String = "\n"): String? = + public suspend fun text(separator: String = "\n"): String? = elements() .mapNotNull { (it as? TextualElement)?.text } .joinToString(separator = separator) @@ -256,12 +256,12 @@ interface Content { /** * Creates a new iterator for this content. */ - operator fun iterator(): Iterator + public operator fun iterator(): Iterator /** * Returns all the elements as a list. */ - suspend fun elements(): List = + public suspend fun elements(): List = buildList { for (element in this@Content) { add(element) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentService.kt index ee0cbc5836..2391fcbcab 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentService.kt @@ -17,14 +17,14 @@ import org.readium.r2.shared.publication.services.content.iterators.ResourceCont * Provides a way to extract the raw [Content] of a [Publication]. */ @ExperimentalReadiumApi -interface ContentService : Publication.Service { +public interface ContentService : Publication.Service { /** * Creates a [Content] starting from the given [start] location. * * The implementation must be fast and non-blocking. Do the actual extraction inside the * [Content] implementation. */ - fun content(start: Locator?): Content + public fun content(start: Locator?): Content } /** @@ -32,7 +32,7 @@ interface ContentService : Publication.Service { * publication when missing. */ @ExperimentalReadiumApi -fun Publication.content(start: Locator? = null): Content? = +public fun Publication.content(start: Locator? = null): Content? = contentService?.content(start) @ExperimentalReadiumApi @@ -41,7 +41,7 @@ private val Publication.contentService: ContentService? /** Factory to build a [ContentService] */ @ExperimentalReadiumApi -var Publication.ServicesBuilder.contentServiceFactory: ServiceFactory? +public var Publication.ServicesBuilder.contentServiceFactory: ServiceFactory? get() = get(ContentService::class) set(value) = set(ContentService::class, value) @@ -50,15 +50,15 @@ var Publication.ServicesBuilder.contentServiceFactory: ServiceFactory? * [ResourceContentIteratorFactory]. */ @ExperimentalReadiumApi -class DefaultContentService( +public class DefaultContentService( private val manifest: Manifest, private val fetcher: Fetcher, private val services: PublicationServicesHolder, private val resourceContentIteratorFactories: List ) : ContentService { - companion object { - fun createFactory( + public companion object { + public fun createFactory( resourceContentIteratorFactories: List ): (Publication.Service.Context) -> DefaultContentService = { context -> DefaultContentService(context.manifest, context.fetcher, context.services, resourceContentIteratorFactories) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentTokenizer.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentTokenizer.kt index 0603894ba8..76761d21c5 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentTokenizer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/ContentTokenizer.kt @@ -16,7 +16,7 @@ import org.readium.r2.shared.util.tokenizer.Tokenizer /** A tokenizer splitting a [Content.Element] into smaller pieces. */ @ExperimentalReadiumApi -fun interface ContentTokenizer : Tokenizer +public fun interface ContentTokenizer : Tokenizer /** * A [ContentTokenizer] using a [TextTokenizer] to split the text of the [Content.Element] into smaller @@ -27,7 +27,7 @@ fun interface ContentTokenizer : Tokenizer * content. If false, [language] will be used only as a default when there is no data-specific information. */ @ExperimentalReadiumApi -class TextContentTokenizer( +public class TextContentTokenizer( private val language: Language?, private val overrideContentLanguage: Boolean = false, private val contextSnippetLength: Int = 50, @@ -37,7 +37,11 @@ class TextContentTokenizer( /** * A [ContentTokenizer] using the default [TextTokenizer] to split the text of the [Content.Element]. */ - constructor(language: Language?, unit: TextUnit, overrideContentLanguage: Boolean = false) : this( + public constructor( + language: Language?, + unit: TextUnit, + overrideContentLanguage: Boolean = false + ) : this( language = language, textTokenizerFactory = { contentLanguage -> DefaultTextContentTokenizer(unit, contentLanguage) }, overrideContentLanguage = overrideContentLanguage diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/HtmlResourceContentIterator.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/HtmlResourceContentIterator.kt index eecbdb4606..0b35680ab2 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/HtmlResourceContentIterator.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/HtmlResourceContentIterator.kt @@ -42,14 +42,14 @@ import org.readium.r2.shared.util.use * Locators will contain a `before` context of up to `beforeMaxLength` characters. */ @ExperimentalReadiumApi -class HtmlResourceContentIterator internal constructor( +public class HtmlResourceContentIterator internal constructor( private val resource: Fetcher.Resource, private val totalProgressionRange: ClosedRange?, private val locator: Locator, private val beforeMaxLength: Int = 50 ) : Content.Iterator { - class Factory : ResourceContentIteratorFactory { + public class Factory : ResourceContentIteratorFactory { override suspend fun create( manifest: Manifest, servicesHolder: PublicationServicesHolder, @@ -196,7 +196,7 @@ class HtmlResourceContentIterator internal constructor( * The [startIndex] will be calculated from the element matched by the base [locator], if * possible. Defaults to 0. */ - data class ParsedElements( + public data class ParsedElements( val elements: List, val startIndex: Int, ) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/PublicationContentIterator.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/PublicationContentIterator.kt index 691542f59a..463c7cc620 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/PublicationContentIterator.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/content/iterators/PublicationContentIterator.kt @@ -18,14 +18,14 @@ import org.readium.r2.shared.util.Either * Returns null if the resource media type is not supported. */ @ExperimentalReadiumApi -fun interface ResourceContentIteratorFactory { +public fun interface ResourceContentIteratorFactory { /** * Creates a [Content.Iterator] instance for the [resource], starting from the given [locator]. * * Returns null if the resource media type is not supported. */ - suspend fun create( + public suspend fun create( manifest: Manifest, servicesHolder: PublicationServicesHolder, readingOrderIndex: Int, @@ -35,17 +35,17 @@ fun interface ResourceContentIteratorFactory { } /** - * A composite [Content.Iterator] which iterates through a whole [publication] and delegates the + * A composite [Content.Iterator] which iterates through a whole [manifest] and delegates the * iteration inside a given resource to media type-specific iterators. * - * @param publication The [Publication] which will be iterated through. + * @param manifest The [Manifest] of the publication which will be iterated through. * @param startLocator Starting [Locator] in the publication. * @param resourceContentIteratorFactories List of [ResourceContentIteratorFactory] which will be * used to create the iterator for each resource. The factories are tried in order until there's a * match. */ @ExperimentalReadiumApi -class PublicationContentIterator( +public class PublicationContentIterator( private val manifest: Manifest, private val fetcher: Fetcher, private val services: PublicationServicesHolder, @@ -105,7 +105,7 @@ class PublicationContentIterator( } /** - * Returns the [Content.Iterator] for the current [Resource] in the reading order. + * Returns the [Content.Iterator] for the current resource in the reading order. */ private suspend fun currentIterator(): IndexedIterator? { if (_currentIterator == null) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/SearchService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/SearchService.kt index 5cc6ecf468..7b2332381a 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/SearchService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/SearchService.kt @@ -9,8 +9,8 @@ package org.readium.r2.shared.publication.services.search import android.os.Parcelable import androidx.annotation.StringRes import kotlinx.parcelize.Parcelize +import org.readium.r2.shared.ExperimentalReadiumApi import org.readium.r2.shared.R -import org.readium.r2.shared.Search import org.readium.r2.shared.UserException import org.readium.r2.shared.error.Try import org.readium.r2.shared.publication.LocatorCollection @@ -20,51 +20,51 @@ import org.readium.r2.shared.resource.Resource import org.readium.r2.shared.util.SuspendingCloseable import org.readium.r2.shared.util.http.HttpException -@Search -typealias SearchTry = Try +@ExperimentalReadiumApi +public typealias SearchTry = Try /** * Represents an error which might occur during a search activity. */ -@Search -sealed class SearchException(content: Content, cause: Throwable? = null) : UserException(content, cause) { - constructor(@StringRes userMessageId: Int, vararg args: Any, cause: Throwable? = null) : +@ExperimentalReadiumApi +public sealed class SearchException(content: Content, cause: Throwable? = null) : UserException(content, cause) { + protected constructor(@StringRes userMessageId: Int, vararg args: Any, cause: Throwable? = null) : this(Content(userMessageId, *args), cause) - constructor(cause: UserException) : + protected constructor(cause: UserException) : this(Content(cause), cause) /** * The publication is not searchable. */ - object PublicationNotSearchable : SearchException(R.string.readium_shared_search_exception_publication_not_searchable) + public object PublicationNotSearchable : SearchException(R.string.readium_shared_search_exception_publication_not_searchable) /** * The provided search query cannot be handled by the service. */ - class BadQuery(cause: UserException) : SearchException(cause) + public class BadQuery(cause: UserException) : SearchException(cause) /** * An error occurred while accessing one of the publication's resources. */ - class ResourceError(cause: Resource.Exception) : SearchException(cause) + public class ResourceError(cause: Resource.Exception) : SearchException(cause) /** * An error occurred while performing an HTTP request. */ - class NetworkError(cause: HttpException) : SearchException(cause) + public class NetworkError(cause: HttpException) : SearchException(cause) /** * The search was cancelled by the caller. * * For example, when a coroutine or a network request is cancelled. */ - object Cancelled : SearchException(R.string.readium_shared_search_exception_cancelled) + public object Cancelled : SearchException(R.string.readium_shared_search_exception_cancelled) /** For any other custom service error. */ - class Other(cause: Throwable) : SearchException(R.string.readium_shared_search_exception_other, cause = cause) + public class Other(cause: Throwable) : SearchException(R.string.readium_shared_search_exception_other, cause = cause) - companion object { - fun wrap(e: Throwable): SearchException = + public companion object { + public fun wrap(e: Throwable): SearchException = when (e) { is SearchException -> e is Resource.Exception -> ResourceError(e) @@ -82,8 +82,8 @@ sealed class SearchException(content: Content, cause: Throwable? = null) : UserE /** * Provides a way to search terms in a publication. */ -@Search -interface SearchService : Publication.Service { +@ExperimentalReadiumApi +public interface SearchService : Publication.Service { /** * Holds the available search options and their current values. @@ -102,7 +102,7 @@ interface SearchService : Publication.Service { * officially recognized by Readium. */ @Parcelize - data class Options( + public data class Options( val caseSensitive: Boolean? = null, val diacriticSensitive: Boolean? = null, val wholeWord: Boolean? = null, @@ -114,7 +114,7 @@ interface SearchService : Publication.Service { /** * Syntactic sugar to access the [otherOptions] values by subscripting [Options] directly. */ - operator fun get(key: String): String? = otherOptions[key] + public operator fun get(key: String): String? = otherOptions[key] } /** @@ -122,28 +122,28 @@ interface SearchService : Publication.Service { * * If an option does not have a value, it is not supported by the service. */ - val options: Options + public val options: Options /** * Starts a new search through the publication content, with the given [query]. * * If an option is nil when calling search(), its value is assumed to be the default one. */ - suspend fun search(query: String, options: Options? = null): SearchTry + public suspend fun search(query: String, options: Options? = null): SearchTry } /** * Indicates whether the content of this publication can be searched. */ -@Search -val Publication.isSearchable get() = - findService(SearchService::class) != null +@ExperimentalReadiumApi +public val Publication.isSearchable: Boolean + get() = findService(SearchService::class) != null /** * Default value for the search options of this publication. */ -@Search -val Publication.searchOptions: SearchService.Options get() = +@ExperimentalReadiumApi +public val Publication.searchOptions: SearchService.Options get() = findService(SearchService::class)?.options ?: SearchService.Options() /** @@ -152,22 +152,22 @@ val Publication.searchOptions: SearchService.Options get() = * If an option is nil when calling [search], its value is assumed to be the default one for the * search service. */ -@Search -suspend fun Publication.search(query: String, options: SearchService.Options? = null): SearchTry = +@ExperimentalReadiumApi +public suspend fun Publication.search(query: String, options: SearchService.Options? = null): SearchTry = findService(SearchService::class)?.search(query, options) ?: Try.failure(SearchException.PublicationNotSearchable) /** Factory to build a [SearchService] */ -@Search -var Publication.ServicesBuilder.searchServiceFactory: ServiceFactory? +@ExperimentalReadiumApi +public var Publication.ServicesBuilder.searchServiceFactory: ServiceFactory? get() = get(SearchService::class) set(value) = set(SearchService::class, value) /** * Iterates through search results. */ -@Search -interface SearchIterator : SuspendingCloseable { +@ExperimentalReadiumApi +public interface SearchIterator : SuspendingCloseable { /** * Number of matches for this search, if known. @@ -177,14 +177,14 @@ interface SearchIterator : SuspendingCloseable { * * The count might be updated after each call to [next]. */ - val resultCount: Int? get() = null + public val resultCount: Int? get() = null /** * Retrieves the next page of results. * * @return Null when reaching the end of the publication, or an error in case of failure. */ - suspend fun next(): SearchTry + public suspend fun next(): SearchTry /** * Closes any resources allocated for the search query, such as a cursor. @@ -195,7 +195,7 @@ interface SearchIterator : SuspendingCloseable { /** * Performs the given operation on each result page of this [SearchIterator]. */ - suspend fun forEach(action: (LocatorCollection) -> Unit): SearchTry { + public suspend fun forEach(action: (LocatorCollection) -> Unit): SearchTry { while (true) { val res = next() res diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/StringSearchService.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/StringSearchService.kt index fce72879c2..c10c1359bf 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/StringSearchService.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/services/search/StringSearchService.kt @@ -16,7 +16,7 @@ import java.text.StringCharacterIterator import java.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.readium.r2.shared.Search +import org.readium.r2.shared.ExperimentalReadiumApi import org.readium.r2.shared.error.Try import org.readium.r2.shared.error.getOrThrow import org.readium.r2.shared.fetcher.DefaultResourceContentExtractorFactory @@ -37,19 +37,19 @@ import timber.log.Timber * * The actual search is implemented by the provided [searchAlgorithm]. */ -@Search -class StringSearchService( +@ExperimentalReadiumApi +public class StringSearchService( private val manifest: Manifest, private val fetcher: Fetcher, private val services: PublicationServicesHolder, - val language: String?, + private val language: String?, private val snippetLength: Int, private val searchAlgorithm: Algorithm, private val extractorFactory: ResourceContentExtractor.Factory, ) : SearchService { - companion object { - fun createDefaultFactory( + public companion object { + public fun createDefaultFactory( snippetLength: Int = 200, searchAlgorithm: Algorithm? = null, extractorFactory: ResourceContentExtractor.Factory = DefaultResourceContentExtractorFactory(), @@ -224,18 +224,18 @@ class StringSearchService( } /** Implements the actual search algorithm in sanitized text content. */ - interface Algorithm { + public interface Algorithm { /** * Default value for the search options available with this algorithm. * If an option does not have a value, it is not supported by the algorithm. */ - val options: Options + public val options: Options /** * Finds all the ranges of occurrences of the given [query] in the [text]. */ - suspend fun findRanges(query: String, options: Options, text: String, locale: Locale): List + public suspend fun findRanges(query: String, options: Options, text: String, locale: Locale): List } /** @@ -243,7 +243,7 @@ class StringSearchService( * while taking into account languages specificities. */ @RequiresApi(Build.VERSION_CODES.N) - class IcuAlgorithm : Algorithm { + public class IcuAlgorithm : Algorithm { override val options: Options = Options( caseSensitive = false, @@ -313,7 +313,7 @@ class StringSearchService( * all languages, so this [Algorithm] does not have any options. Use [IcuAlgorithm] for * better results. */ - class NaiveAlgorithm : Algorithm { + public class NaiveAlgorithm : Algorithm { override val options: Options get() = Options() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/BytesResource.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/BytesResource.kt index 7366b6255f..ae912c46fa 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/BytesResource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/BytesResource.kt @@ -11,8 +11,8 @@ import org.readium.r2.shared.error.Try import org.readium.r2.shared.extensions.coerceIn import org.readium.r2.shared.extensions.requireLengthFitInt -sealed class BaseBytesResource( - val bytes: suspend () -> Try +public sealed class BaseBytesResource( + public val bytes: suspend () -> Try ) : Resource { private lateinit var _bytes: Try @@ -43,20 +43,20 @@ sealed class BaseBytesResource( } /** Creates a Resource serving a [ByteArray]. */ -class BytesResource(bytes: suspend () -> Try) : BaseBytesResource(bytes) { +public class BytesResource(bytes: suspend () -> Try) : BaseBytesResource(bytes) { - constructor(bytes: ByteArray) : this({ Try.success(bytes) }) + public constructor(bytes: ByteArray) : this({ Try.success(bytes) }) override fun toString(): String = "${javaClass.simpleName}(${runBlocking { length() }} bytes)" } /** Creates a Resource serving a [String]. */ -class StringResource( +public class StringResource( string: suspend () -> ResourceTry ) : BaseBytesResource({ string().map { it.toByteArray() } }) { - constructor(string: String) : this({ Try.success(string) }) + public constructor(string: String) : this({ Try.success(string) }) override fun toString(): String = "${javaClass.simpleName}(${runBlocking { readAsString() }})" diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/Container.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/Container.kt index fb3e578585..c6efd588d5 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/Container.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/Container.kt @@ -12,34 +12,34 @@ import org.readium.r2.shared.util.SuspendingCloseable /** * A resource container as an archive or a directory. */ -interface Container : SuspendingCloseable { +public interface Container : SuspendingCloseable { /** * Holds a container entry's. */ - interface Entry : Resource { + public interface Entry : Resource { /** * Absolute path to the entry in the archive. * It MUST start with /. */ - val path: String + public val path: String } /** * Direct file to this container, when available. */ - val file: File? get() = null + public val file: File? get() = null /** * Gets the container name if any. */ - suspend fun name(): ResourceTry + public suspend fun name(): ResourceTry /** * List of all the container entries of null if such a list is not available. */ - suspend fun entries(): Iterable? + public suspend fun entries(): Iterable? /** * Returns the [Entry] at the given [path]. @@ -47,5 +47,5 @@ interface Container : SuspendingCloseable { * A [Entry] is always returned, since for some cases we can't know if it exists before * actually fetching it, such as HTTP. Therefore, errors are handled at the Entry level. */ - suspend fun entry(path: String): Entry + public suspend fun entry(path: String): Entry } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/ContentResource.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/ContentResource.kt index 493a39ac18..1f4bca7c8b 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/ContentResource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/ContentResource.kt @@ -25,7 +25,7 @@ import org.readium.r2.shared.util.toUri /** * Creates [ContentResource]s. */ -class ContentResourceFactory( +public class ContentResourceFactory( private val contentResolver: ContentResolver ) : ResourceFactory { @@ -43,7 +43,7 @@ class ContentResourceFactory( /** * A [Resource] to access content [uri] thanks to a [ContentResolver]. */ -class ContentResource( +public class ContentResource( private val uri: Uri, private val contentResolver: ContentResolver, ) : Resource { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/DefaultArchiveFactory.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/DefaultArchiveFactory.kt index a61e2cadd0..657f1c092a 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/DefaultArchiveFactory.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/DefaultArchiveFactory.kt @@ -14,7 +14,7 @@ import kotlinx.coroutines.withContext import org.readium.r2.shared.error.MessageError import org.readium.r2.shared.error.Try -class DefaultArchiveFactory : ArchiveFactory { +public class DefaultArchiveFactory : ArchiveFactory { override suspend fun create(resource: Resource, password: String?): Try { if (password != null) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/DirectoryContainer.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/DirectoryContainer.kt index 1d14ea7171..d39285da35 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/DirectoryContainer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/DirectoryContainer.kt @@ -59,7 +59,7 @@ internal class DirectoryContainer( override suspend fun close() {} } -class DirectoryContainerFactory : ContainerFactory { +public class DirectoryContainerFactory : ContainerFactory { override suspend fun create(url: Url): Try { if (url.scheme != ContentResolver.SCHEME_FILE) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt index 0f86cd81b1..bb387e964e 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt @@ -17,44 +17,44 @@ import org.readium.r2.shared.util.Url * An exception must be returned if the url scheme is not supported or * the resource cannot be found. */ -fun interface ResourceFactory { +public fun interface ResourceFactory { - sealed class Error : org.readium.r2.shared.error.Error { + public sealed class Error : org.readium.r2.shared.error.Error { - class SchemeNotSupported( - val scheme: String, + public class SchemeNotSupported( + public val scheme: String, override val cause: org.readium.r2.shared.error.Error? = null ) : Error() { - constructor(scheme: String, exception: Exception) : this(scheme, ThrowableError(exception)) + public constructor(scheme: String, exception: Exception) : this(scheme, ThrowableError(exception)) override val message: String = "Url scheme $scheme is not supported." } - class NotAResource( - val url: Url, + public class NotAResource( + public val url: Url, override val cause: org.readium.r2.shared.error.Error? = null ) : Error() { - constructor(url: Url, exception: Exception) : this(url, ThrowableError(exception)) + public constructor(url: Url, exception: Exception) : this(url, ThrowableError(exception)) override val message: String = "No resource found at url $url." } - class Forbidden( + public class Forbidden( override val cause: org.readium.r2.shared.error.Error ) : Error() { - constructor(exception: Exception) : this(ThrowableError(exception)) + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Access to the container is forbidden." } } - suspend fun create(url: Url): Try + public suspend fun create(url: Url): Try } /** @@ -63,44 +63,44 @@ fun interface ResourceFactory { * An exception must be returned if the url scheme is not supported or * the url doesn't seem to point to a container. */ -fun interface ContainerFactory { +public fun interface ContainerFactory { - sealed class Error : org.readium.r2.shared.error.Error { + public sealed class Error : org.readium.r2.shared.error.Error { - class SchemeNotSupported( - val scheme: String, + public class SchemeNotSupported( + public val scheme: String, override val cause: org.readium.r2.shared.error.Error? = null ) : Error() { - constructor(scheme: String, exception: Exception) : this(scheme, ThrowableError(exception)) + public constructor(scheme: String, exception: Exception) : this(scheme, ThrowableError(exception)) override val message: String = "Url scheme $scheme is not supported." } - class NotAContainer( - val url: Url, + public class NotAContainer( + public val url: Url, override val cause: org.readium.r2.shared.error.Error? = null ) : Error() { - constructor(url: Url, exception: Exception) : this(url, ThrowableError(exception)) + public constructor(url: Url, exception: Exception) : this(url, ThrowableError(exception)) override val message: String = "No container found at url $url." } - class Forbidden( + public class Forbidden( override val cause: org.readium.r2.shared.error.Error ) : Error() { - constructor(exception: Exception) : this(ThrowableError(exception)) + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Access to the container is forbidden." } } - suspend fun create(url: Url): Try + public suspend fun create(url: Url): Try } /** @@ -108,50 +108,50 @@ fun interface ContainerFactory { * * An exception must be returned if the resource type, password or media type is not supported. */ -fun interface ArchiveFactory { +public fun interface ArchiveFactory { - sealed class Error : org.readium.r2.shared.error.Error { + public sealed class Error : org.readium.r2.shared.error.Error { - class FormatNotSupported( + public class FormatNotSupported( override val cause: org.readium.r2.shared.error.Error? = null ) : Error() { - constructor(exception: Exception) : this(ThrowableError(exception)) + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Archive format not supported." } - class PasswordsNotSupported( + public class PasswordsNotSupported( override val cause: org.readium.r2.shared.error.Error? = null ) : Error() { - constructor(exception: Exception) : this(ThrowableError(exception)) + public constructor(exception: Exception) : this(ThrowableError(exception)) override val message: String = "Password feature is not supported." } - class ResourceReading( + public class ResourceReading( override val cause: org.readium.r2.shared.error.Error?, - val resourceException: Resource.Exception + public val resourceException: Resource.Exception ) : Error() { - constructor(exception: Resource.Exception) : this(ThrowableError(exception), exception) + public constructor(exception: Resource.Exception) : this(ThrowableError(exception), exception) override val message: String = "An error occurred while attempting to read the resource." } } - suspend fun create(resource: Resource, password: String?): Try + public suspend fun create(resource: Resource, password: String?): Try } /** * A composite archive factory which first tries [primaryFactory] * and falls back on [fallbackFactory] if it doesn't support the resource. */ -class CompositeArchiveFactory( +public class CompositeArchiveFactory( private val primaryFactory: ArchiveFactory, private val fallbackFactory: ArchiveFactory ) : ArchiveFactory { @@ -171,7 +171,7 @@ class CompositeArchiveFactory( * A composite resource factory which first tries [primaryFactory] * and falls back on [fallbackFactory] if it doesn't support the scheme. */ -class CompositeResourceFactory( +public class CompositeResourceFactory( private val primaryFactory: ResourceFactory, private val fallbackFactory: ResourceFactory ) : ResourceFactory { @@ -191,7 +191,7 @@ class CompositeResourceFactory( * A composite container factory which first tries [primaryFactory] * and falls back on [fallbackFactory] if it doesn't support the scheme. */ -class CompositeContainerFactory( +public class CompositeContainerFactory( private val primaryFactory: ContainerFactory, private val fallbackFactory: ContainerFactory ) : ContainerFactory { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/FileResource.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/FileResource.kt index 244bbc837f..f0cb278714 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/FileResource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/FileResource.kt @@ -23,7 +23,7 @@ import org.readium.r2.shared.util.isLazyInitialized /** * A [Resource] to access a [file]. */ -class FileResource(override val file: File) : Resource { +public class FileResource(override val file: File) : Resource { private val randomAccessFile by lazy { ResourceTry.catching { @@ -34,10 +34,12 @@ class FileResource(override val file: File) : Resource { override suspend fun name(): ResourceTry = ResourceTry.success(file.name) - override suspend fun close() = withContext(Dispatchers.IO) { - if (::randomAccessFile.isLazyInitialized) { - randomAccessFile.onSuccess { - tryOrLog { it.close() } + override suspend fun close() { + withContext(Dispatchers.IO) { + if (::randomAccessFile.isLazyInitialized) { + randomAccessFile.onSuccess { + tryOrLog { it.close() } + } } } } @@ -104,7 +106,7 @@ class FileResource(override val file: File) : Resource { "${javaClass.simpleName}(${file.path})" } -class FileResourceFactory : ResourceFactory { +public class FileResourceFactory : ResourceFactory { override suspend fun create(url: Url): Try { if (url.scheme != ContentResolver.SCHEME_FILE) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/Resource.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/Resource.kt index 98535ff0a9..35a8fbd590 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/Resource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/Resource.kt @@ -21,12 +21,12 @@ import org.readium.r2.shared.parser.xml.ElementNode import org.readium.r2.shared.parser.xml.XmlParser import org.readium.r2.shared.util.SuspendingCloseable -typealias ResourceTry = Try +public typealias ResourceTry = Try /** * Acts as a proxy to an actual resource by handling read access. */ -interface Resource : SuspendingCloseable { +public interface Resource : SuspendingCloseable { /** * Direct file to this resource, when available. @@ -36,17 +36,17 @@ interface Resource : SuspendingCloseable { * underwent transformations or is being read from an archive. Therefore, consumers should * always fallback on regular stream reading, using [read] or [ResourceInputStream]. */ - val file: File? get() = null + public val file: File? get() = null /** * Returns the resource media type if known. */ - suspend fun mediaType(): ResourceTry = ResourceTry.success(null) + public suspend fun mediaType(): ResourceTry = ResourceTry.success(null) /** * Returns the name of the resource if any. */ - suspend fun name(): ResourceTry = ResourceTry.success(null) + public suspend fun name(): ResourceTry = ResourceTry.success(null) /** * Returns data length from metadata if available, or calculated from reading the bytes otherwise. @@ -54,7 +54,7 @@ interface Resource : SuspendingCloseable { * This value must be treated as a hint, as it might not reflect the actual bytes length. To get * the real length, you need to read the whole resource. */ - suspend fun length(): ResourceTry + public suspend fun length(): ResourceTry /** * Reads the bytes at the given range. @@ -62,19 +62,22 @@ interface Resource : SuspendingCloseable { * When [range] is null, the whole content is returned. Out-of-range indexes are clamped to the * available length automatically. */ - suspend fun read(range: LongRange? = null): ResourceTry + public suspend fun read(range: LongRange? = null): ResourceTry /** * Errors occurring while accessing a resource. */ - sealed class Exception(@StringRes userMessageId: Int, cause: Throwable? = null) : UserException(userMessageId, cause = cause) { + public sealed class Exception(@StringRes userMessageId: Int, cause: Throwable? = null) : UserException(userMessageId, cause = cause) { /** Equivalent to a 400 HTTP error. */ - class BadRequest(val parameters: Map = emptyMap(), cause: Throwable? = null) : + public class BadRequest( + public val parameters: Map = emptyMap(), + cause: Throwable? = null + ) : Exception(R.string.readium_shared_resource_exception_bad_request, cause) /** Equivalent to a 404 HTTP error. */ - class NotFound(cause: Throwable? = null) : + public class NotFound(cause: Throwable? = null) : Exception(R.string.readium_shared_resource_exception_not_found, cause) /** @@ -83,7 +86,7 @@ interface Resource : SuspendingCloseable { * This can be returned when trying to read a resource protected with a DRM that is not * unlocked. */ - class Forbidden(cause: Throwable? = null) : + public class Forbidden(cause: Throwable? = null) : Exception(R.string.readium_shared_resource_exception_forbidden, cause) /** @@ -92,28 +95,28 @@ interface Resource : SuspendingCloseable { * Used when the source can't be reached, e.g. no Internet connection, or an issue with the * file system. Usually this is a temporary error. */ - class Unavailable(cause: Throwable? = null) : + public class Unavailable(cause: Throwable? = null) : Exception(R.string.readium_shared_resource_exception_unavailable, cause) /** * The Internet connection appears to be offline. */ - object Offline : Exception(R.string.readium_shared_resource_exception_offline) + public object Offline : Exception(R.string.readium_shared_resource_exception_offline) /** * Equivalent to a 507 HTTP error. * * Used when the requested range is too large to be read in memory. */ - class OutOfMemory(override val cause: OutOfMemoryError) : + public class OutOfMemory(override val cause: OutOfMemoryError) : Exception(R.string.readium_shared_resource_exception_out_of_memory) /** For any other error, such as HTTP 500. */ - class Other(cause: Throwable) : Exception(R.string.readium_shared_resource_exception_other, cause) + public class Other(cause: Throwable) : Exception(R.string.readium_shared_resource_exception_other, cause) - companion object { + public companion object { - fun wrap(e: Throwable): Exception = + public fun wrap(e: Throwable): Exception = when (e) { is Exception -> e is OutOfMemoryError -> OutOfMemory(e) @@ -124,7 +127,7 @@ interface Resource : SuspendingCloseable { } /** Creates a Resource that will always return the given [error]. */ -class FailureResource(private val error: Resource.Exception) : Resource { +public class FailureResource(private val error: Resource.Exception) : Resource { internal constructor(cause: Throwable) : this(Resource.Exception.wrap(cause)) @@ -143,7 +146,7 @@ class FailureResource(private val error: Resource.Exception) : Resource { * * If the [transform] throws an [Exception], it is wrapped in a failure with Resource.Exception.Other. */ -inline fun ResourceTry.mapCatching(transform: (value: S) -> R): ResourceTry = +public inline fun ResourceTry.mapCatching(transform: (value: S) -> R): ResourceTry = try { map(transform) } catch (e: Exception) { @@ -152,7 +155,7 @@ inline fun ResourceTry.mapCatching(transform: (value: S) -> R): Resour Try.failure(Resource.Exception.wrap(e)) } -inline fun ResourceTry.flatMapCatching(transform: (value: S) -> ResourceTry): ResourceTry = +public inline fun ResourceTry.flatMapCatching(transform: (value: S) -> ResourceTry): ResourceTry = mapCatching(transform).flatMap { it } /** @@ -161,7 +164,7 @@ inline fun ResourceTry.flatMapCatching(transform: (value: S) -> Resour * If [charset] is null, then it is parsed from the `charset` parameter of link().type, * or falls back on UTF-8. */ -suspend fun Resource.readAsString(charset: Charset? = null): ResourceTry = +public suspend fun Resource.readAsString(charset: Charset? = null): ResourceTry = read().mapCatching { String(it, charset = charset ?: Charsets.UTF_8) } @@ -169,19 +172,19 @@ suspend fun Resource.readAsString(charset: Charset? = null): ResourceTry /** * Reads the full content as a JSON object. */ -suspend fun Resource.readAsJson(): ResourceTry = +public suspend fun Resource.readAsJson(): ResourceTry = readAsString(charset = Charsets.UTF_8).mapCatching { JSONObject(it) } /** * Reads the full content as an XML document. */ -suspend fun Resource.readAsXml(): ResourceTry = +public suspend fun Resource.readAsXml(): ResourceTry = read().mapCatching { XmlParser().parse(ByteArrayInputStream(it)) } /** * Reads the full content as a [Bitmap]. */ -suspend fun Resource.readAsBitmap(): ResourceTry = +public suspend fun Resource.readAsBitmap(): ResourceTry = read().mapCatching { BitmapFactory.decodeByteArray(it, 0, it.size) ?: throw kotlin.Exception("Could not decode resource as a bitmap") diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/ResourceInputStream.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/ResourceInputStream.kt index 4bf29c8bb1..51b45148ab 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/ResourceInputStream.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/ResourceInputStream.kt @@ -17,9 +17,9 @@ import org.readium.r2.shared.error.getOrThrow * If you experience bad performances, consider wrapping the stream in a BufferedInputStream. This * is particularly useful when streaming deflated ZIP entries. */ -class ResourceInputStream( +public class ResourceInputStream( private val resource: Resource, - val range: LongRange? = null + public val range: LongRange? = null ) : InputStream() { private var isClosed = false @@ -107,26 +107,32 @@ class ResourceInputStream( override fun markSupported(): Boolean = true @Throws(IOException::class) - override fun mark(readlimit: Int) = synchronized(this) { - checkNotClosed() - mark = position + override fun mark(readlimit: Int) { + synchronized(this) { + checkNotClosed() + mark = position + } } @Throws(IOException::class) - override fun reset() = synchronized(this) { - checkNotClosed() - position = mark + override fun reset() { + synchronized(this) { + checkNotClosed() + position = mark + } } /** * Closes the underlying resource. */ - override fun close() = synchronized(this) { - if (isClosed) - return + override fun close() { + synchronized(this) { + if (isClosed) + return - isClosed = true - runBlocking { resource.close() } + isClosed = true + runBlocking { resource.close() } + } } private fun checkNotClosed() { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/ZipContainer.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/ZipContainer.kt index 7c6d69c2c7..3c29f8cd53 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/ZipContainer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/ZipContainer.kt @@ -21,14 +21,14 @@ import org.readium.r2.shared.util.io.CountingInputStream /** * A [Container] representing a Zip archive. */ -interface ZipContainer : Container { +public interface ZipContainer : Container { - interface Entry : Container.Entry { + public interface Entry : Container.Entry { /** * Compressed data length. */ - val compressedLength: Long? + public val compressedLength: Long? } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/units/Hertz.kt b/readium/shared/src/main/java/org/readium/r2/shared/units/Hertz.kt index e6b5fd9fc8..103a52a67a 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/units/Hertz.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/units/Hertz.kt @@ -7,6 +7,6 @@ package org.readium.r2.shared.units @JvmInline -value class Hz(val value: Double) +public value class Hz(public val value: Double) -val Double.hz get() = Hz(this) +public val Double.hz: Hz get() = Hz(this) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Closeable.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Closeable.kt index 87eba6d466..01bc8566dc 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Closeable.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Closeable.kt @@ -9,31 +9,31 @@ package org.readium.r2.shared.util /** * A [Closeable] is an object holding closeable resources, such as open files or streams. */ -interface Closeable { +public interface Closeable { /** * Closes this object and releases any resources associated with it. * If the object is already closed then invoking this method has no effect. */ - fun close() + public fun close() } /** * A [SuspendingCloseable] is an object holding closeable resources, such as open files or streams. */ -interface SuspendingCloseable { +public interface SuspendingCloseable { /** * Closes this object and releases any resources associated with it. * If the object is already closed then invoking this method has no effect. */ - suspend fun close() + public suspend fun close() } /** * Executes the given block function on this resource and then closes it down correctly whether * an exception is thrown or not. */ -suspend inline fun T.use(block: (T) -> R): R { +public suspend inline fun T.use(block: (T) -> R): R { var exception: Throwable? = null try { return block(this) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/CursorList.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/CursorList.kt index 4a3b9ce77f..19726b7d56 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/CursorList.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/CursorList.kt @@ -19,7 +19,7 @@ import org.readium.r2.shared.InternalReadiumApi * as the last returned element. May be -1 or the size of the list as well. */ @InternalReadiumApi -class CursorList( +public class CursorList( private val list: List = emptyList(), private var index: Int = -1 ) : List by list { @@ -28,14 +28,14 @@ class CursorList( check(index in -1..list.size) } - fun hasPrevious(): Boolean { + public fun hasPrevious(): Boolean { return index > 0 } /** * Moves the cursor backward and returns the element, or null when reaching the beginning. */ - fun previous(): E? { + public fun previous(): E? { if (!hasPrevious()) return null @@ -43,14 +43,14 @@ class CursorList( return list[index] } - fun hasNext(): Boolean { + public fun hasNext(): Boolean { return index + 1 < list.size } /** * Moves the cursor forward and returns the element, or null when reaching the end. */ - fun next(): E? { + public fun next(): E? { if (!hasNext()) return null diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Deprecated.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Deprecated.kt index 7066f6bbdd..66ef1b0c62 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Deprecated.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Deprecated.kt @@ -16,5 +16,5 @@ import org.readium.r2.shared.error.Try */ @Suppress("Unused_parameter") @Deprecated(message = "Use getOrElse instead.", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("getOrElse")) -inline fun Try.recover(transform: (exception: F) -> R): Try = +public inline fun Try.recover(transform: (exception: F) -> R): Try = TODO() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Either.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Either.kt index 2142031e14..df1eed3d27 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Either.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Either.kt @@ -9,12 +9,12 @@ package org.readium.r2.shared.util /** * Generic wrapper to store two mutually exclusive types. */ -sealed class Either { - data class Left(val value: A) : Either() - data class Right(val value: B) : Either() +public sealed class Either { + public data class Left(val value: A) : Either() + public data class Right(val value: B) : Either() - companion object { - inline operator fun invoke(value: Any): Either = + public companion object { + public inline operator fun invoke(value: Any): Either = when (value) { is A -> Left(value) is B -> Right(value) @@ -22,20 +22,20 @@ sealed class Either { } } - val left: A? + public val left: A? get() = (this as? Left)?.value - val right: B? + public val right: B? get() = (this as? Right)?.value - inline fun onLeft(action: (value: A) -> Unit): Either { + public inline fun onLeft(action: (value: A) -> Unit): Either { (this as? Left)?.let { action(it.value) } return this } - inline fun onRight(action: (value: B) -> Unit): Either { + public inline fun onRight(action: (value: B) -> Unit): Either { (this as? Right)?.let { action(it.value) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Href.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Href.kt index 312f704fd2..42202a374f 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Href.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Href.kt @@ -20,17 +20,17 @@ import timber.log.Timber * * This is used to normalize the string representation. */ -class Href( +public class Href( private val href: String, baseHref: String = "/" ) { - data class QueryParameter(val name: String, val value: String?) + public data class QueryParameter(val name: String, val value: String?) private val baseHref = if (baseHref.isEmpty()) "/" else baseHref /** Returns the normalized string representation for this HREF. */ - val string: String get() { + public val string: String get() { val baseHref = baseHref.removePercentEncoding() val href = href.removePercentEncoding() @@ -67,7 +67,7 @@ class Href( * * Taken from https://stackoverflow.com/a/49796882/1474476 */ - val percentEncodedString: String get() { + public val percentEncodedString: String get() { var string = string if (string.startsWith("/")) { string = string.addPrefix("file://") @@ -84,7 +84,7 @@ class Href( } /** Returns the query parameters present in this HREF, in the order they appear. */ - val queryParameters: List get() { + public val queryParameters: List get() { val url = percentEncodedString.substringBefore("#") return UrlQuerySanitizer(url).parameterList .map { p -> QueryParameter(name = p.mParameter, value = p.mValue.takeUnless { it.isBlank() }) } @@ -108,8 +108,8 @@ class Href( .takeIf { !it.contains("\uFFFD") } ?: this } -fun List.firstNamedOrNull(name: String): String? = +public fun List.firstNamedOrNull(name: String): String? = firstOrNull { it.name == name }?.value -fun List.allNamed(name: String): List = +public fun List.allNamed(name: String): List = filter { it.name == name }.mapNotNull { it.value } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Language.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Language.kt index b8393ec153..543cc93c34 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Language.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Language.kt @@ -21,27 +21,27 @@ import kotlinx.serialization.encoding.Encoder * @param code BCP-47 language code */ @Serializable(with = Language.Serializer::class) -class Language(code: String) { +public class Language(code: String) { /** * Creates a [Language] from a Java [Locale]. */ - constructor(locale: Locale) : this(code = locale.toLanguageTag()) + public constructor(locale: Locale) : this(code = locale.toLanguageTag()) /** * BCP-47 language code. */ - val code = code.replace("_", "-") + public val code: String = code.replace("_", "-") - val locale: Locale by lazy { Locale.forLanguageTag(code) } + public val locale: Locale by lazy { Locale.forLanguageTag(code) } /** Indicates whether this language is a regional variant. */ - val isRegional: Boolean by lazy { + public val isRegional: Boolean by lazy { locale.country.isNotEmpty() } /** Returns this [Language] after stripping the region. */ - fun removeRegion(): Language = + public fun removeRegion(): Language = Language(code.split("-", limit = 2).first()) override fun toString(): String = @@ -57,7 +57,7 @@ class Language(code: String) { override fun hashCode(): Int = code.hashCode() - object Serializer : KSerializer { + internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Language", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: Language) { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Lazy.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Lazy.kt index aea45449aa..a2e758d9b5 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Lazy.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Lazy.kt @@ -8,13 +8,15 @@ package org.readium.r2.shared.util import kotlin.reflect.KProperty0 import kotlin.reflect.jvm.isAccessible +import org.readium.r2.shared.InternalReadiumApi /** * Returns true if a lazy property reference has been initialized, or if the property is not lazy. * * Source: https://stackoverflow.com/a/42536189/1474476 */ -val KProperty0<*>.isLazyInitialized: Boolean +@InternalReadiumApi +public val KProperty0<*>.isLazyInitialized: Boolean get() { if (this !is Lazy<*>) return true diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/MapCompanion.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/MapCompanion.kt index 07647ba435..008253d883 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/MapCompanion.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/MapCompanion.kt @@ -24,47 +24,47 @@ package org.readium.r2.shared.util * val layout: Layout? = Layout("reflowable") * ``` */ -open class MapCompanion(protected val map: Map) { +public open class MapCompanion(protected val map: Map) { - constructor(elements: Array, keySelector: (E) -> K) : + public constructor(elements: Array, keySelector: (E) -> K) : this(elements.associateBy(keySelector)) /** * Returns the available [keys]. */ - val keys: Set + public val keys: Set get() = map.keys /** - * Returns the element matching the [key], or [null] if not found. + * Returns the element matching the [key], or null if not found. * * To be overridden in subclasses if custom retrieval is needed – for example, testing lowercase * keys. */ - open fun get(key: K?): E? = + public open fun get(key: K?): E? = key?.let { map[key] } /** * Alias to [get], to be used like `keyMapper("a_key")`. */ - open operator fun invoke(key: K?): E? = get(key) + public open operator fun invoke(key: K?): E? = get(key) @Deprecated("Use `Enum(\"value\")` instead", ReplaceWith("get(key)"), level = DeprecationLevel.ERROR) - open fun from(key: K?): E? = get(key) + public open fun from(key: K?): E? = get(key) } /** * Extends a [MapCompanion] by adding a [default] value as a fallback. */ -open class MapWithDefaultCompanion(map: Map, val default: E) : MapCompanion(map) { +public open class MapWithDefaultCompanion(map: Map, public val default: E) : MapCompanion(map) { - constructor(elements: Array, keySelector: (E) -> K, default: E) : + public constructor(elements: Array, keySelector: (E) -> K, default: E) : this(elements.associateBy(keySelector), default) /** * Returns the element matching the [key], or the [default] value as a fallback. */ - fun getOrDefault(key: K?): E = + public fun getOrDefault(key: K?): E = get(key) ?: default /** diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/MemoryObserver.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/MemoryObserver.kt index 3f83b19610..b839e13264 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/MemoryObserver.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/MemoryObserver.kt @@ -8,16 +8,16 @@ import org.readium.r2.shared.InternalReadiumApi * A memory observer reacts to a device reclaiming memory by releasing unused resources. */ @InternalReadiumApi -interface MemoryObserver { +public interface MemoryObserver { /** * Level of memory trim. */ - enum class Level { + public enum class Level { Moderate, Low, Critical; - companion object { - fun fromLevel(level: Int): Level = + public companion object { + public fun fromLevel(level: Int): Level = when { level <= ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE -> Moderate level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW -> Low @@ -31,13 +31,13 @@ interface MemoryObserver { * * Release unused resources according to the level. */ - fun onTrimMemory(level: Level) + public fun onTrimMemory(level: Level) - companion object { + public companion object { /** - * Wraps the given [observer] into a [ComponentCallbacks2] usable with Android's [Context]. + * Wraps the given [observer] into a [ComponentCallbacks2] usable with Android's Context. */ - fun asComponentCallbacks2(observer: MemoryObserver): ComponentCallbacks2 = + public fun asComponentCallbacks2(observer: MemoryObserver): ComponentCallbacks2 = object : ComponentCallbacks2 { override fun onConfigurationChanged(config: Configuration) {} override fun onLowMemory() {} diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Ref.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Ref.kt index c1249bab97..7fbb0c70ce 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Ref.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Ref.kt @@ -12,7 +12,7 @@ package org.readium.r2.shared.util * Get the reference by calling `ref()` * Conveniently, the reference can be reset by setting the `ref` property. */ -class Ref(var ref: T? = null) { +internal class Ref(var ref: T? = null) { operator fun invoke(): T? = ref } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/URITemplate.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/URITemplate.kt index 18fbfdcb9a..f1440b7012 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/URITemplate.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/URITemplate.kt @@ -9,16 +9,19 @@ package org.readium.r2.shared.util +import org.readium.r2.shared.InternalReadiumApi + /** * A lightweight implementation of URI Template (RFC 6570). * * Only handles simple cases, fitting Readium's use cases. * See https://tools.ietf.org/html/rfc6570 */ -data class URITemplate(val uri: String) { +@InternalReadiumApi +public data class URITemplate(val uri: String) { /** - * List of URI template parameter keys, if the [Link] is templated. + * List of URI template parameter keys, if the Link is templated. */ val parameters: List by lazy { // Escaping the last } is somehow required, otherwise the regex can't be parsed on a Pixel @@ -32,7 +35,7 @@ data class URITemplate(val uri: String) { /** * Expands the HREF by replacing URI template variables by the given parameters. */ - fun expand(parameters: Map): String { + public fun expand(parameters: Map): String { @Suppress("NAME_SHADOWING") // `+` is considered like an encoded space, and will not be properly encoded in parameters. // This is an issue for ISO 8601 date for example. diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Url.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Url.kt index da6dff8597..a041cb8d09 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Url.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Url.kt @@ -14,30 +14,30 @@ import org.readium.r2.shared.extensions.tryOrNull * A Uniform Resource Locator. */ @JvmInline -value class Url private constructor(internal val uri: Uri) { +public value class Url private constructor(internal val uri: Uri) { - val scheme: String + public val scheme: String get() = uri.scheme!! - val authority: String + public val authority: String get() = uri.authority!! - val path: String + public val path: String get() = uri.path!! - val filename: String + public val filename: String get() = File(path).name - val extension: String? + public val extension: String? get() = File(path).extension .takeIf { it.isNotEmpty() } override fun toString(): String = uri.toString() - companion object { + public companion object { - operator fun invoke(url: String): Url? = + public operator fun invoke(url: String): Url? = invoke(Uri.parse(url)) internal operator fun invoke(uri: Uri): Url? = @@ -50,17 +50,17 @@ value class Url private constructor(internal val uri: Uri) { } } -fun Url.isFile(): Boolean = +public fun Url.isFile(): Boolean = scheme == "file" -fun Url.isHttp(): Boolean = +public fun Url.isHttp(): Boolean = scheme == "http" || scheme == "https" -fun File.toUrl(): Url = +public fun File.toUrl(): Url = Url(Uri.fromFile(this))!! -fun Uri.toUrl(): Url? = +public fun Uri.toUrl(): Url? = Url.invoke(this) -fun Url.toUri() = +public fun Url.toUri(): Uri = uri diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/WebLauncher.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/WebLauncher.kt index 563633b1fe..4d478eff6d 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/WebLauncher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/WebLauncher.kt @@ -13,7 +13,7 @@ import org.readium.r2.shared.extensions.tryOrLog * Opens the given [uri] with a Chrome Custom Tab or the system browser as a fallback. */ @InternalReadiumApi -fun launchWebBrowser(context: Context, uri: Uri) { +public fun launchWebBrowser(context: Context, uri: Uri) { var url = uri if (url.scheme == null) { url = url.buildUpon().scheme("http").build() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/archive/channel/ChannelZipContainer.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/archive/channel/ChannelZipContainer.kt index 7c65e9c511..56a0e830fb 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/archive/channel/ChannelZipContainer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/archive/channel/ChannelZipContainer.kt @@ -139,7 +139,7 @@ internal class ChannelZipContainer( /** * An [ArchiveFactory] able to open a ZIP archive served through an HTTP server. */ -class ChannelZipArchiveFactory : ArchiveFactory { +public class ChannelZipArchiveFactory : ArchiveFactory { override suspend fun create( resource: Resource, @@ -180,7 +180,7 @@ class ChannelZipArchiveFactory : ArchiveFactory { } } - companion object { + public companion object { private const val CACHE_ALL_MAX_SIZE = 5242880 diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/cache/Cache.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/cache/Cache.kt index 511d3bc25f..23faaa45f0 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/cache/Cache.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/cache/Cache.kt @@ -22,32 +22,32 @@ import org.readium.r2.shared.util.SuspendingCloseable * It implements [MemoryObserver] to flush unused in-memory objects when necessary. */ @InternalReadiumApi -interface Cache : SuspendingCloseable, MemoryObserver { +public interface Cache : SuspendingCloseable, MemoryObserver { /** * Performs an atomic [block] transaction on this cache. */ - suspend fun transaction(block: suspend CacheTransaction.() -> T): T + public suspend fun transaction(block: suspend CacheTransaction.() -> T): T } /** * An atomic transaction run on a cache for objects of type [V]. */ @InternalReadiumApi -interface CacheTransaction { +public interface CacheTransaction { /** * Gets the current cached value for the given [key]. */ - suspend fun get(key: String): V? + public suspend fun get(key: String): V? /** * Writes the cached [value] for the given [key]. */ - suspend fun put(key: String, value: V?) + public suspend fun put(key: String, value: V?) /** * Gets the current cached value for the given [key] or creates and caches a new one. */ - suspend fun CacheTransaction.getOrPut(key: String, defaultValue: suspend () -> V): V = + public suspend fun CacheTransaction.getOrPut(key: String, defaultValue: suspend () -> V): V = get(key) ?: defaultValue().also { put(key, it) } @@ -56,19 +56,19 @@ interface CacheTransaction { * * @return The cached value if any. */ - suspend fun remove(key: String): V? + public suspend fun remove(key: String): V? /** * Clears all cached values. */ - suspend fun clear() + public suspend fun clear() } /** * A basic in-memory cache. */ @InternalReadiumApi -class InMemoryCache : Cache { +public class InMemoryCache : Cache { private val values = mutableMapOf() private val mutex = Mutex() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/DefaultHttpClient.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/DefaultHttpClient.kt index fcfdfc62d4..429c3fc25f 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/DefaultHttpClient.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/DefaultHttpClient.kt @@ -32,24 +32,24 @@ import timber.log.Timber * @param readTimeout Timeout used when reading the input stream. A null timeout is interpreted * as the default value, while a timeout of zero as an infinite timeout. */ -class DefaultHttpClient( +public class DefaultHttpClient( private val userAgent: String? = null, private val additionalHeaders: Map = mapOf(), private val connectTimeout: Duration? = null, private val readTimeout: Duration? = null, - var callback: Callback = object : Callback {}, + public var callback: Callback = object : Callback {}, ) : HttpClient { - companion object { + public companion object { /** * [HttpRequest.extras] key for the number of redirections performed for a request. */ - const val EXTRA_REDIRECT_COUNT = "redirectCount" + private const val EXTRA_REDIRECT_COUNT: String = "redirectCount" } /** * Callbacks allowing to override some behavior of the [DefaultHttpClient]. */ - interface Callback { + public interface Callback { /** * Called when the HTTP client will start a new [request]. @@ -57,7 +57,7 @@ class DefaultHttpClient( * You can modify the [request], for example by adding additional HTTP headers or * redirecting to a different URL, before returning it. */ - suspend fun onStartRequest(request: HttpRequest): HttpTry = + public suspend fun onStartRequest(request: HttpRequest): HttpTry = Try.success(request) /** @@ -69,7 +69,7 @@ class DefaultHttpClient( * - the [error] argument, if you cannot recover from it * - a new [HttpException] to provide additional information */ - suspend fun onRecoverRequest(request: HttpRequest, error: HttpException): HttpTry = + public suspend fun onRecoverRequest(request: HttpRequest, error: HttpException): HttpTry = Try.failure(error) /** @@ -85,7 +85,7 @@ class DefaultHttpClient( * - a different redirection request * - a [HttpException.CANCELLED] error to abort the redirection */ - suspend fun onFollowUnsafeRedirect( + public suspend fun onFollowUnsafeRedirect( request: HttpRequest, response: HttpResponse, newRequest: HttpRequest @@ -99,7 +99,7 @@ class DefaultHttpClient( * This is merely for informational purposes. For example, you could implement this to * confirm that request credentials were successful. */ - suspend fun onResponseReceived(request: HttpRequest, response: HttpResponse) {} + public suspend fun onResponseReceived(request: HttpRequest, response: HttpResponse) {} /** * Called when the HTTP client received an [error] for the given [request]. @@ -109,14 +109,13 @@ class DefaultHttpClient( * * This will be called only if [onRecoverRequest] is not implemented, or returns an error. */ - suspend fun onRequestFailed(request: HttpRequest, error: HttpException) {} + public suspend fun onRequestFailed(request: HttpRequest, error: HttpException) {} } private val mediaTypeRetriever: MediaTypeRetriever = MediaTypeRetriever() // We are using Dispatchers.IO but we still get this warning... - @Suppress("BlockingMethodInNonBlockingContext", "NAME_SHADOWING") override suspend fun stream(request: HttpRequest): HttpTry { suspend fun tryStream(request: HttpRequest): HttpTry = diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpClient.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpClient.kt index ff64416f70..a3b450750b 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpClient.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpClient.kt @@ -21,17 +21,17 @@ import org.readium.r2.shared.util.mediatype.MediaType * You may provide a custom implementation, or use the [DefaultHttpClient] one which relies on * native APIs. */ -interface HttpClient { +public interface HttpClient { /** * Streams the resource from the given [request]. */ - suspend fun stream(request: HttpRequest): HttpTry + public suspend fun stream(request: HttpRequest): HttpTry /** * Fetches the resource from the given [request]. */ - suspend fun fetch(request: HttpRequest): HttpTry = + public suspend fun fetch(request: HttpRequest): HttpTry = stream(request) .flatMap { response -> try { @@ -46,7 +46,7 @@ interface HttpClient { // Declare a companion object to allow reading apps to extend it. For example, by adding a // HttpClient.get(Context) constructor. - companion object + public companion object } /** @@ -54,7 +54,10 @@ interface HttpClient { * * If the decoder fails, a MalformedResponse error is returned. */ -suspend fun HttpClient.fetchWithDecoder(request: HttpRequest, decoder: (HttpFetchResponse) -> T): HttpTry = +public suspend fun HttpClient.fetchWithDecoder( + request: HttpRequest, + decoder: (HttpFetchResponse) -> T +): HttpTry = fetch(request) .flatMap { try { @@ -67,7 +70,7 @@ suspend fun HttpClient.fetchWithDecoder(request: HttpRequest, decoder: (Http /** * Fetches the resource from the given [request] as a [String]. */ -suspend fun HttpClient.fetchString(request: HttpRequest, charset: Charset = Charsets.UTF_8): HttpTry = +public suspend fun HttpClient.fetchString(request: HttpRequest, charset: Charset = Charsets.UTF_8): HttpTry = fetchWithDecoder(request) { response -> String(response.body, charset) } @@ -75,19 +78,19 @@ suspend fun HttpClient.fetchString(request: HttpRequest, charset: Charset = Char /** * Fetches the resource from the given [request] as a [JSONObject]. */ -suspend fun HttpClient.fetchJSONObject(request: HttpRequest): HttpTry = +public suspend fun HttpClient.fetchJSONObject(request: HttpRequest): HttpTry = fetchWithDecoder(request) { response -> JSONObject(String(response.body)) } -class HttpStreamResponse( - val response: HttpResponse, - val body: InputStream, +public class HttpStreamResponse( + public val response: HttpResponse, + public val body: InputStream, ) -class HttpFetchResponse( - val response: HttpResponse, - val body: ByteArray, +public class HttpFetchResponse( + public val response: HttpResponse, + public val body: ByteArray, ) /** @@ -100,7 +103,7 @@ class HttpFetchResponse( * @param mediaType Media type sniffed from the `Content-Type` header and response body. Falls back * on `application/octet-stream`. */ -data class HttpResponse( +public data class HttpResponse( val request: HttpRequest, val url: String, val statusCode: Int, @@ -114,13 +117,13 @@ data class HttpResponse( * Finds the first value of the first header matching the given name. * In keeping with the HTTP RFC, HTTP header field names are case-insensitive. */ - fun valueForHeader(name: String): String? = httpHeaders[name] + public fun valueForHeader(name: String): String? = httpHeaders[name] /** * Finds all the values of the first header matching the given name. * In keeping with the HTTP RFC, HTTP header field names are case-insensitive. */ - fun valuesForHeader(name: String): List = httpHeaders.getAll(name) + public fun valuesForHeader(name: String): List = httpHeaders.getAll(name) /** * Indicates whether this server supports byte range requests. diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpException.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpException.kt index ebb6ed6919..e65a5e0c97 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpException.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpException.kt @@ -18,7 +18,7 @@ import org.readium.r2.shared.error.Try import org.readium.r2.shared.extensions.tryOrLog import org.readium.r2.shared.util.mediatype.MediaType -typealias HttpTry = Try +public typealias HttpTry = Try /** * Represents an error occurring during an HTTP activity. @@ -28,14 +28,14 @@ typealias HttpTry = Try * @param body Response body. * @param cause Underlying error, if any. */ -class HttpException( - val kind: Kind, - val mediaType: MediaType? = null, - val body: ByteArray? = null, +public class HttpException( + public val kind: Kind, + public val mediaType: MediaType? = null, + public val body: ByteArray? = null, cause: Throwable? = null, ) : UserException(kind.userMessageId, cause = cause) { - enum class Kind(@StringRes val userMessageId: Int) { + public enum class Kind(@StringRes public val userMessageId: Int) { /** The provided request was not valid. */ MalformedRequest(R.string.readium_shared_http_exception_malformed_request), /** The received response couldn't be decoded. */ @@ -61,10 +61,10 @@ class HttpException( /** An error whose kind is not recognized. */ Other(R.string.readium_shared_http_exception_other); - companion object { + public companion object { /** Resolves the kind of the HTTP error associated with the given [statusCode]. */ - fun ofStatusCode(statusCode: Int): Kind? = + public fun ofStatusCode(statusCode: Int): Kind? = when (statusCode) { in 200..399 -> null 400 -> BadRequest @@ -91,7 +91,7 @@ class HttpException( return super.getUserMessage(context, includesCauses) } - override fun getLocalizedMessage(): String? { + override fun getLocalizedMessage(): String { var message = "HTTP error: ${kind.name}" problemDetails?.let { details -> message += ": ${details.title} ${details.detail}" @@ -100,7 +100,7 @@ class HttpException( } /** Response body parsed as a JSON problem details. */ - val problemDetails: ProblemDetails? by lazy { + public val problemDetails: ProblemDetails? by lazy { if (body == null || mediaType?.matches(MediaType.JSON_PROBLEM_DETAILS) != true) { return@lazy null } @@ -108,19 +108,23 @@ class HttpException( tryOrLog { ProblemDetails.fromJSON(JSONObject(String(body))) } } - companion object { + public companion object { /** * Shortcut for a cancelled HTTP error. */ - val CANCELLED = HttpException(kind = Kind.Cancelled) + public val CANCELLED: HttpException = HttpException(kind = Kind.Cancelled) /** * Creates an HTTP error from a status code. * * Returns null if the status code is a success. */ - operator fun invoke(statusCode: Int, mediaType: MediaType? = null, body: ByteArray? = null): HttpException? = + public operator fun invoke( + statusCode: Int, + mediaType: MediaType? = null, + body: ByteArray? = null + ): HttpException? = Kind.ofStatusCode(statusCode)?.let { kind -> HttpException(kind, mediaType, body) } @@ -128,7 +132,7 @@ class HttpException( /** * Creates an HTTP error from a generic exception. */ - fun wrap(cause: Throwable): HttpException { + public fun wrap(cause: Throwable): HttpException { val kind = when (cause) { is HttpException -> return cause is MalformedURLException -> Kind.MalformedRequest diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpFetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpFetcher.kt index 996745b6ad..40d03c226c 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpFetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpFetcher.kt @@ -24,7 +24,7 @@ import timber.log.Timber * @param baseUrl Base URL from which relative HREF are served. * @param links A set of links that are known to be available through this fetcher. */ -class HttpFetcher( +public class HttpFetcher( private val client: HttpClient, private val baseUrl: String? = null, private val links: List = emptyList(), @@ -47,14 +47,14 @@ class HttpFetcher( override suspend fun close() {} /** Provides access to an external URL. */ - class HttpResource( + public class HttpResource( private val link: Link, private val resource: org.readium.r2.shared.util.http.HttpResource ) : Resource by resource, Fetcher.Resource { - companion object { + public companion object { - operator fun invoke( + public operator fun invoke( link: Link, url: String, client: HttpClient, diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpHeaders.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpHeaders.kt index 954a4dfcd7..48c65fef04 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpHeaders.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpHeaders.kt @@ -12,10 +12,10 @@ import org.readium.r2.shared.InternalReadiumApi * Helper to parse HTTP request/response headers. */ @InternalReadiumApi -data class HttpHeaders(val headers: Map>) { +public data class HttpHeaders(val headers: Map>) { - companion object { - operator fun invoke(headers: Map): HttpHeaders = + public companion object { + public operator fun invoke(headers: Map): HttpHeaders = HttpHeaders(headers.mapValues { (_, value) -> listOf(value) }) } @@ -23,7 +23,7 @@ data class HttpHeaders(val headers: Map>) { * Finds the first value of the first header matching the given name. * In keeping with the HTTP RFC, HTTP header field names are case-insensitive. */ - operator fun get(name: String): String? { + public operator fun get(name: String): String? { val n = name.lowercase() return headers.firstNotNullOfOrNull { (key, value) -> if (key.lowercase() == n) value.firstOrNull() @@ -35,7 +35,7 @@ data class HttpHeaders(val headers: Map>) { * Finds all the values of the first header matching the given name. * In keeping with the HTTP RFC, HTTP header field names are case-insensitive. */ - fun getAll(name: String): List { + public fun getAll(name: String): List { val n = name.lowercase() return headers .mapNotNull { (key, value) -> @@ -92,10 +92,10 @@ data class HttpHeaders(val headers: Map>) { * * [end] is inclusive. */ -data class HttpRange( +public data class HttpRange( val start: Long, val end: Long? ) { - fun toLongRange(contentLength: Long): LongRange = + public fun toLongRange(contentLength: Long): LongRange = start..(end ?: (contentLength - 1)) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpRequest.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpRequest.kt index a85e5c0ccf..fa8c8f14f2 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpRequest.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpRequest.kt @@ -22,29 +22,29 @@ import kotlin.time.Duration * @param allowUserInteraction If true, the user might be presented with interactive dialogs, such * as popping up an authentication dialog. */ -class HttpRequest( - val url: String, - val method: Method = Method.GET, - val headers: Map = mapOf(), - val body: Body? = null, - val extras: Bundle = Bundle(), - val connectTimeout: Duration? = null, - val readTimeout: Duration? = null, - val allowUserInteraction: Boolean = false, +public class HttpRequest( + public val url: String, + public val method: Method = Method.GET, + public val headers: Map = mapOf(), + public val body: Body? = null, + public val extras: Bundle = Bundle(), + public val connectTimeout: Duration? = null, + public val readTimeout: Duration? = null, + public val allowUserInteraction: Boolean = false, ) : Serializable { /** Supported HTTP methods. */ - enum class Method : Serializable { + public enum class Method : Serializable { DELETE, GET, HEAD, PATCH, POST, PUT; } /** Supported body values. */ - sealed class Body : Serializable { - class Bytes(val bytes: ByteArray) : Body() - class File(val file: java.io.File) : Body() + public sealed class Body : Serializable { + public class Bytes(public val bytes: ByteArray) : Body() + public class File(public val file: java.io.File) : Body() } - fun buildUpon() = Builder( + public fun buildUpon(): Builder = Builder( url = url, method = method, headers = headers.toMutableMap(), @@ -55,43 +55,43 @@ class HttpRequest( allowUserInteraction = allowUserInteraction ) - companion object { - operator fun invoke(url: String, build: Builder.() -> Unit): HttpRequest = + public companion object { + public operator fun invoke(url: String, build: Builder.() -> Unit): HttpRequest = Builder(url).apply(build).build() } - class Builder( + public class Builder( url: String, - var method: Method = Method.GET, - var headers: MutableMap = mutableMapOf(), - var body: Body? = null, - var extras: Bundle = Bundle(), - var connectTimeout: Duration? = null, - var readTimeout: Duration? = null, - var allowUserInteraction: Boolean = false, + public var method: Method = Method.GET, + public var headers: MutableMap = mutableMapOf(), + public var body: Body? = null, + public var extras: Bundle = Bundle(), + public var connectTimeout: Duration? = null, + public var readTimeout: Duration? = null, + public var allowUserInteraction: Boolean = false, ) { - var url: String + public var url: String get() = uriBuilder.build().toString() set(value) { uriBuilder = Uri.parse(value).buildUpon() } private var uriBuilder: Uri.Builder = Uri.parse(url).buildUpon() - fun appendQueryParameter(key: String, value: String?): Builder { + public fun appendQueryParameter(key: String, value: String?): Builder { if (value != null) { uriBuilder.appendQueryParameter(key, value) } return this } - fun appendQueryParameters(params: Map): Builder { + public fun appendQueryParameters(params: Map): Builder { for ((key, value) in params) { appendQueryParameter(key, value) } return this } - fun setHeader(key: String, value: String): Builder { + public fun setHeader(key: String, value: String): Builder { headers[key] = value return this } @@ -99,7 +99,7 @@ class HttpRequest( /** * Issue a byte range request. Use -1 to download until the end. */ - fun setRange(range: LongRange): Builder { + public fun setRange(range: LongRange): Builder { val start = range.first.coerceAtLeast(0) var value = "$start-" if (range.last >= start) { @@ -112,7 +112,7 @@ class HttpRequest( /** * Initializes a POST request with the given form data. */ - fun setPostForm(form: Map): Builder { + public fun setPostForm(form: Map): Builder { method = Method.POST setHeader("Content-Type", "application/x-www-form-urlencoded") @@ -128,7 +128,7 @@ class HttpRequest( return this } - fun build(): HttpRequest = HttpRequest( + public fun build(): HttpRequest = HttpRequest( url = url, method = method, headers = headers.toMap(), diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResource.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResource.kt index 6d6dc4ad35..49733e7ec1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResource.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResource.kt @@ -13,15 +13,15 @@ import org.readium.r2.shared.resource.ResourceTry import org.readium.r2.shared.util.io.CountingInputStream /** Provides access to an external URL. */ -class HttpResource( +public class HttpResource( private val client: HttpClient, private val url: String, private val maxSkipBytes: Long = MAX_SKIP_BYTES ) : Resource { override suspend fun name(): ResourceTry = - headResponse().map { - it.valuesForHeader("Content-Disposition") + headResponse().map { r -> + r.valuesForHeader("Content-Disposition") .flatMap { it.split(";") } .map { it.trim() } .firstOrNull { it.startsWith("filename=") } @@ -137,7 +137,7 @@ class HttpResource( Resource.Exception.Other(e) } - companion object { + public companion object { private const val MAX_SKIP_BYTES: Long = 8192 } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResourceFactory.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResourceFactory.kt index 0b4042fc89..37386ce2f4 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResourceFactory.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/HttpResourceFactory.kt @@ -12,7 +12,7 @@ import org.readium.r2.shared.resource.ResourceFactory import org.readium.r2.shared.util.Url import org.readium.r2.shared.util.isHttp -class HttpResourceFactory( +public class HttpResourceFactory( private val httpClient: HttpClient ) : ResourceFactory { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/MediaType.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/MediaType.kt index 3d05d51d22..b9dd67f1fe 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/MediaType.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/MediaType.kt @@ -17,7 +17,7 @@ import org.readium.r2.shared.util.mediatype.MediaTypeRetriever * Resolves the format for this [HttpURLConnection], with optional extra file extension and media type * hints. */ -suspend fun MediaTypeRetriever.retrieve( +public suspend fun MediaTypeRetriever.retrieve( connection: HttpURLConnection, bytes: (() -> ByteArray)?, mediaTypes: List, @@ -56,9 +56,9 @@ suspend fun MediaTypeRetriever.retrieve( * Resolves the format for this [HttpURLConnection], with optional extra file extension and media type * hints. */ -suspend fun MediaTypeRetriever.retrieve( +public suspend fun MediaTypeRetriever.retrieve( connection: HttpURLConnection, bytes: (() -> ByteArray)? = null, mediaType: String? = null, fileExtension: String? = null -) = retrieve(connection, bytes, listOfNotNull(mediaType), listOfNotNull(fileExtension)) +): MediaType? = retrieve(connection, bytes, listOfNotNull(mediaType), listOfNotNull(fileExtension)) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/http/ProblemDetails.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/http/ProblemDetails.kt index b290c212da..36a219c4c8 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/http/ProblemDetails.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/http/ProblemDetails.kt @@ -20,17 +20,17 @@ import org.readium.r2.shared.util.logging.log * https://tools.ietf.org/html/rfc7807 * * @param title A short, human-readable summary of the problem type. - * @param type A URI reference [RFC3986] that identifies the problem type. This specification + * @param type A URI reference RFC3986 that identifies the problem type. This specification * encourages that, when dereferenced, it provide human-readable documentation for the * problem type. - * @param status The HTTP status code ([RFC7231], Section 6) generated by the origin server for this + * @param status The HTTP status code (RFC7231, Section 6) generated by the origin server for this * occurrence of the problem. * @param detail A human-readable explanation specific to this occurrence of the problem. * @param instance A URI reference that identifies the specific occurrence of the problem. It may or * may not yield further information if dereferenced. */ @Parcelize -data class ProblemDetails( +public data class ProblemDetails( val title: String, val type: String? = null, val status: Int? = null, @@ -38,12 +38,12 @@ data class ProblemDetails( val instance: String? = null ) : Parcelable { - companion object { + public companion object { /** * Creates a [ProblemDetails] from its JSON representation. */ - fun fromJSON(json: JSONObject, warnings: WarningLogger? = null): ProblemDetails? { + public fun fromJSON(json: JSONObject, warnings: WarningLogger? = null): ProblemDetails? { val title = json.optNullableString("title") if (title == null) { warnings?.log(ProblemDetails::class.java, "[title] is required", json) diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/io/CountingInputStream.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/io/CountingInputStream.kt index 10ca73061e..6a7c046ea8 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/io/CountingInputStream.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/io/CountingInputStream.kt @@ -18,12 +18,12 @@ import org.readium.r2.shared.extensions.requireLengthFitInt * An [InputStream] counting the number of bytes read from a wrapped [inputStream]. */ @InternalReadiumApi -class CountingInputStream( +public class CountingInputStream( inputStream: InputStream, initialCount: Long = 0 ) : FilterInputStream(inputStream) { - var count: Long = initialCount + public var count: Long = initialCount private set private var mark: Long = -1 @@ -65,7 +65,7 @@ class CountingInputStream( count = mark.coerceAtLeast(0) } - fun readRange(range: LongRange): ByteArray { + public fun readRange(range: LongRange): ByteArray { @Suppress("NAME_SHADOWING") val range = range .coerceFirstNonNegative() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/logging/WarningLogger.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/logging/WarningLogger.kt index d982714722..2ab5366573 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/logging/WarningLogger.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/logging/WarningLogger.kt @@ -13,27 +13,26 @@ import org.json.JSONObject import org.readium.r2.shared.util.logging.Warning.SeverityLevel.* import timber.log.Timber -// FIXME: Mark this interface as functional to benefit from the SAM-conversion in Kotlin 1.4 https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-4-m1-released/#new-type-inference /** * Interface to be implemented by third-party apps if they want to observe warnings raised, for - * example, during the parsing of a [Publication]. + * example, during the parsing of a publication. */ -interface WarningLogger { +public fun interface WarningLogger { /** Notifies that a warning occurred. */ - fun log(warning: Warning) + public fun log(warning: Warning) } /** * Implementation of a [WarningLogger] that accumulates the warnings in a list, to be used as a * convenience by third-party apps. */ -class ListWarningLogger : WarningLogger { +public class ListWarningLogger : WarningLogger { /** * The list of accumulated [Warning]s. */ - val warnings: List get() = _warnings + public val warnings: List get() = _warnings private val _warnings = mutableListOf() override fun log(warning: Warning) { @@ -44,7 +43,7 @@ class ListWarningLogger : WarningLogger { /** * Implementation of a [WarningLogger] printing the warnings to the console. */ -class ConsoleWarningLogger : WarningLogger { +public class ConsoleWarningLogger : WarningLogger { override fun log(warning: Warning) { val message = "[${warning.tag}] ${warning.message}" @@ -61,7 +60,7 @@ class ConsoleWarningLogger : WarningLogger { * For example, while parsing an EPUB we, might want to report issues in the publication without * failing the whole parsing. */ -interface Warning { +public interface Warning { /** * Indicates how the user experience might be affected by a warning. @@ -70,7 +69,7 @@ interface Warning { * @property MODERATE The user experience might be affected, but it shouldn't prevent the user from enjoying the publication. * @property MAJOR The user experience will most likely be disturbed, for example with rendering issues. */ - enum class SeverityLevel { + public enum class SeverityLevel { MINOR, MODERATE, MAJOR @@ -81,17 +80,17 @@ interface Warning { * * For example json, metadata, etc. */ - val tag: String + public val tag: String /** * Localized user-facing message describing the issue. */ - val message: String + public val message: String /** * Indicates the severity level of this warning. */ - val severity: SeverityLevel + public val severity: SeverityLevel } /** @@ -101,7 +100,7 @@ interface Warning { * @param reason Details about the failure. * @param json Source [JSONObject]. */ -data class JsonWarning( +public data class JsonWarning( val modelClass: Class<*>, val reason: String, override val severity: Warning.SeverityLevel, @@ -121,7 +120,7 @@ data class JsonWarning( * @param severity The severity level of this warning. * @param json Source [JSONObject]. */ -fun WarningLogger.log( +public fun WarningLogger.log( modelClass: Class<*>, reason: String, json: JSONObject? = null, diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Extensions.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Extensions.kt index 4a6afc0242..de9fee044e 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Extensions.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Extensions.kt @@ -23,7 +23,7 @@ import org.readium.r2.shared.resource.DefaultArchiveFactory ), level = DeprecationLevel.ERROR ) -suspend fun HttpURLConnection.sniffMediaType( +public suspend fun HttpURLConnection.sniffMediaType( bytes: (() -> ByteArray)? = null, mediaTypes: List = emptyList(), fileExtensions: List = emptyList(), @@ -70,5 +70,5 @@ suspend fun HttpURLConnection.sniffMediaType( replaceWith = ReplaceWith("mediaTypeRetriever.retrieve(mediaType = mediaTypeHint)"), level = DeprecationLevel.ERROR ) -suspend fun File.mediaType(mediaTypeHint: String? = null): MediaType = +public suspend fun File.mediaType(mediaTypeHint: String? = null): MediaType = MediaTypeRetriever().retrieve(this, mediaType = mediaTypeHint) ?: MediaType.BINARY diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaType.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaType.kt index efea8bbdcb..70a7757163 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaType.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaType.kt @@ -33,20 +33,20 @@ import org.readium.r2.shared.extensions.tryOrNull * @param name A human readable name identifying the media type, which may be presented to the user. * @param fileExtension The default file extension to use for this media type. */ -class MediaType( +public class MediaType( string: String, - val name: String? = null, - val fileExtension: String? = null + public val name: String? = null, + public val fileExtension: String? = null ) { /** The type component, e.g. `application` in `application/epub+zip`. */ - val type: String + public val type: String /** The subtype component, e.g. `epub+zip` in `application/epub+zip`. */ - val subtype: String + public val subtype: String /** The parameters in the media type, such as `charset=utf-8`. */ - val parameters: Map + public val parameters: Map init { if (string.isEmpty()) { @@ -98,7 +98,7 @@ class MediaType( * Gives a hint on the underlying structure of this media type. * See. https://tools.ietf.org/html/rfc6838#section-4.2.8 */ - val structuredSyntaxSuffix: String? get() { + public val structuredSyntaxSuffix: String? get() { val parts = subtype.split("+") return if (parts.size > 1) "+${parts.last()}" else null } @@ -106,7 +106,7 @@ class MediaType( /** * Encoding as declared in the `charset` parameter, if there's any. */ - val charset: Charset? get() = + public val charset: Charset? get() = parameters["charset"]?.let { Charset.forName(it) } /** @@ -119,7 +119,7 @@ class MediaType( * Non-significant parameters are also discarded. */ @Deprecated("Use MediaTypeRetriever instead", replaceWith = ReplaceWith("mediaTypeRetriever.canonicalMediaType()"), level = DeprecationLevel.ERROR) - suspend fun canonicalMediaType(): MediaType { + public fun canonicalMediaType(): MediaType { TODO() } @@ -165,7 +165,7 @@ class MediaType( * - Wildcards are supported, meaning that `image/*` contains `image/png` and `*/*` contains * everything. */ - fun contains(other: MediaType?): Boolean { + public fun contains(other: MediaType?): Boolean { if (other == null || (type != "*" && type != other.type) || (subtype != "*" && subtype != other.subtype)) { return false } @@ -177,7 +177,7 @@ class MediaType( /** * Returns whether the given [other] media type is included in this media type. */ - fun contains(other: String?): Boolean { + public fun contains(other: String?): Boolean { val mediaType = other?.let { parse(it) } ?: return false @@ -191,72 +191,72 @@ class MediaType( * For example, `text/html` matches `text/html;charset=utf-8`, but `text/html;charset=ascii` * doesn't. This is basically like `contains`, but working in both direction. */ - fun matches(other: MediaType?): Boolean = + public fun matches(other: MediaType?): Boolean = contains(other) || (other?.contains(this) == true) /** * Returns whether this media type and `other` are the same, ignoring parameters that are not * in both media types. */ - fun matches(other: String?): Boolean = + public fun matches(other: String?): Boolean = matches(other?.let { parse(it) }) /** * Returns whether this media type matches any of the `others` media types. */ - fun matchesAny(vararg others: MediaType?): Boolean = + public fun matchesAny(vararg others: MediaType?): Boolean = others.any { matches(it) } /** * Returns whether this media type matches any of the `others` media types. */ - fun matchesAny(vararg others: String?): Boolean = + public fun matchesAny(vararg others: String?): Boolean = others.any { matches(it) } /** Returns whether this media type is structured as a ZIP archive. */ - val isZip: Boolean get() = + public val isZip: Boolean get() = matchesAny(ZIP, LCP_PROTECTED_AUDIOBOOK, LCP_PROTECTED_PDF) || structuredSyntaxSuffix == "+zip" /** Returns whether this media type is structured as a JSON file. */ - val isJson: Boolean get() = + public val isJson: Boolean get() = matches(JSON) || structuredSyntaxSuffix == "+json" /** Returns whether this media type is of an OPDS feed. */ - val isOpds: Boolean get() = + public val isOpds: Boolean get() = matchesAny(OPDS1, OPDS1_ENTRY, OPDS2, OPDS2_PUBLICATION, OPDS_AUTHENTICATION) /** Returns whether this media type is of an HTML document. */ - val isHtml: Boolean get() = + public val isHtml: Boolean get() = matchesAny(HTML, XHTML) /** Returns whether this media type is of a bitmap image, so excluding vectorial formats. */ - val isBitmap: Boolean get() = + public val isBitmap: Boolean get() = matchesAny(BMP, GIF, JPEG, PNG, TIFF, WEBP) /** Returns whether this media type is of an audio clip. */ - val isAudio: Boolean get() = + public val isAudio: Boolean get() = type == "audio" /** Returns whether this media type is of a video clip. */ - val isVideo: Boolean get() = + public val isVideo: Boolean get() = type == "video" /** Returns whether this media type is of a Readium Web Publication Manifest. */ - val isRwpm: Boolean get() = + public val isRwpm: Boolean get() = matchesAny(READIUM_AUDIOBOOK_MANIFEST, DIVINA_MANIFEST, READIUM_WEBPUB_MANIFEST) /** Returns whether this media type is of a publication file. */ - val isPublication: Boolean get() = matchesAny( + public val isPublication: Boolean get() = matchesAny( READIUM_AUDIOBOOK, READIUM_AUDIOBOOK_MANIFEST, CBZ, DIVINA, DIVINA_MANIFEST, EPUB, LCP_PROTECTED_AUDIOBOOK, LCP_PROTECTED_PDF, LPF, PDF, W3C_WPUB_MANIFEST, READIUM_WEBPUB, READIUM_WEBPUB_MANIFEST, ZAB ) @Deprecated("Format and MediaType got merged together", replaceWith = ReplaceWith(""), level = DeprecationLevel.ERROR) - val mediaType: MediaType + public val mediaType: MediaType get() = this - companion object { + public companion object { /** * Creates a [MediaType] from its RFC 6838 string representation. @@ -264,72 +264,72 @@ class MediaType( * @param name A human readable name identifying the media type, which may be presented to the user. * @param fileExtension The default file extension to use for this media type. */ - fun parse(string: String, name: String? = null, fileExtension: String? = null): MediaType? = + public fun parse(string: String, name: String? = null, fileExtension: String? = null): MediaType? = tryOrNull { MediaType(string = string, name = name, fileExtension = fileExtension) } // Known Media Types // // Reading apps are welcome to extend the static constants with additional media types. - val AAC = MediaType("audio/aac", fileExtension = "aac") - val ACSM = MediaType("application/vnd.adobe.adept+xml", name = "Adobe Content Server Message", fileExtension = "acsm") - val AIFF = MediaType("audio/aiff", fileExtension = "aiff") - val AVI = MediaType("video/x-msvideo", fileExtension = "avi") - val AVIF = MediaType("image/avif", fileExtension = "avif") - val BINARY = MediaType("application/octet-stream") - val BMP = MediaType("image/bmp", fileExtension = "bmp") - val CBZ = MediaType("application/vnd.comicbook+zip", name = "Comic Book Archive", fileExtension = "cbz") - val CSS = MediaType("text/css", fileExtension = "css") - val DIVINA = MediaType("application/divina+zip", name = "Digital Visual Narratives", fileExtension = "divina") - val DIVINA_MANIFEST = MediaType("application/divina+json", name = "Digital Visual Narratives", fileExtension = "json") - val EPUB = MediaType("application/epub+zip", name = "EPUB", fileExtension = "epub") - val GIF = MediaType("image/gif", fileExtension = "gif") - val GZ = MediaType("application/gzip", fileExtension = "gz") - val HTML = MediaType("text/html", fileExtension = "html") - val JAVASCRIPT = MediaType("text/javascript", fileExtension = "js") - val JPEG = MediaType("image/jpeg", fileExtension = "jpeg") - val JSON = MediaType("application/json") - val JSON_PROBLEM_DETAILS = MediaType("application/problem+json", name = "HTTP Problem Details", fileExtension = "json") - val JXL = MediaType("image/jxl", fileExtension = "jxl") - val LCP_LICENSE_DOCUMENT = MediaType("application/vnd.readium.lcp.license.v1.0+json", name = "LCP License", fileExtension = "lcpl") - val LCP_PROTECTED_AUDIOBOOK = MediaType("application/audiobook+lcp", name = "LCP Protected Audiobook", fileExtension = "lcpa") - val LCP_PROTECTED_PDF = MediaType("application/pdf+lcp", name = "LCP Protected PDF", fileExtension = "lcpdf") - val LCP_STATUS_DOCUMENT = MediaType("application/vnd.readium.license.status.v1.0+json") - val LPF = MediaType("application/lpf+zip", fileExtension = "lpf") - val MP3 = MediaType("audio/mpeg", fileExtension = "mp3") - val MPEG = MediaType("video/mpeg", fileExtension = "mpeg") - val NCX = MediaType("application/x-dtbncx+xml", fileExtension = "ncx") - val OGG = MediaType("audio/ogg", fileExtension = "oga") - val OGV = MediaType("video/ogg", fileExtension = "ogv") - val OPDS1 = MediaType("application/atom+xml;profile=opds-catalog") - val OPDS1_ENTRY = MediaType("application/atom+xml;type=entry;profile=opds-catalog") - val OPDS2 = MediaType("application/opds+json") - val OPDS2_PUBLICATION = MediaType("application/opds-publication+json") - val OPDS_AUTHENTICATION = MediaType("application/opds-authentication+json") - val OPUS = MediaType("audio/opus", fileExtension = "opus") - val OTF = MediaType("font/otf", fileExtension = "otf") - val PDF = MediaType("application/pdf", name = "PDF", fileExtension = "pdf") - val PNG = MediaType("image/png", fileExtension = "png") - val READIUM_AUDIOBOOK = MediaType("application/audiobook+zip", name = "Readium Audiobook", fileExtension = "audiobook") - val READIUM_AUDIOBOOK_MANIFEST = MediaType("application/audiobook+json", name = "Readium Audiobook", fileExtension = "json") - val READIUM_WEBPUB = MediaType("application/webpub+zip", name = "Readium Web Publication", fileExtension = "webpub") - val READIUM_WEBPUB_MANIFEST = MediaType("application/webpub+json", name = "Readium Web Publication", fileExtension = "json") - val SMIL = MediaType("application/smil+xml", fileExtension = "smil") - val SVG = MediaType("image/svg+xml", fileExtension = "svg") - val TEXT = MediaType("text/plain", fileExtension = "txt") - val TIFF = MediaType("image/tiff", fileExtension = "tiff") - val TTF = MediaType("font/ttf", fileExtension = "ttf") - val W3C_WPUB_MANIFEST = MediaType("application/x.readium.w3c.wpub+json", name = "Web Publication", fileExtension = "json") // non-existent - val WAV = MediaType("audio/wav", fileExtension = "wav") - val WEBM_AUDIO = MediaType("audio/webm", fileExtension = "webm") - val WEBM_VIDEO = MediaType("video/webm", fileExtension = "webm") - val WEBP = MediaType("image/webp", fileExtension = "webp") - val WOFF = MediaType("font/woff", fileExtension = "woff") - val WOFF2 = MediaType("font/woff2", fileExtension = "woff2") - val XHTML = MediaType("application/xhtml+xml", fileExtension = "xhtml") - val XML = MediaType("application/xml", fileExtension = "xml") - val ZAB = MediaType("application/x.readium.zab+zip", name = "Zipped Audio Book", fileExtension = "zab") // non-existent - val ZIP = MediaType("application/zip", fileExtension = "zip") + public val AAC: MediaType = MediaType("audio/aac", fileExtension = "aac") + public val ACSM: MediaType = MediaType("application/vnd.adobe.adept+xml", name = "Adobe Content Server Message", fileExtension = "acsm") + public val AIFF: MediaType = MediaType("audio/aiff", fileExtension = "aiff") + public val AVI: MediaType = MediaType("video/x-msvideo", fileExtension = "avi") + public val AVIF: MediaType = MediaType("image/avif", fileExtension = "avif") + public val BINARY: MediaType = MediaType("application/octet-stream") + public val BMP: MediaType = MediaType("image/bmp", fileExtension = "bmp") + public val CBZ: MediaType = MediaType("application/vnd.comicbook+zip", name = "Comic Book Archive", fileExtension = "cbz") + public val CSS: MediaType = MediaType("text/css", fileExtension = "css") + public val DIVINA: MediaType = MediaType("application/divina+zip", name = "Digital Visual Narratives", fileExtension = "divina") + public val DIVINA_MANIFEST: MediaType = MediaType("application/divina+json", name = "Digital Visual Narratives", fileExtension = "json") + public val EPUB: MediaType = MediaType("application/epub+zip", name = "EPUB", fileExtension = "epub") + public val GIF: MediaType = MediaType("image/gif", fileExtension = "gif") + public val GZ: MediaType = MediaType("application/gzip", fileExtension = "gz") + public val HTML: MediaType = MediaType("text/html", fileExtension = "html") + public val JAVASCRIPT: MediaType = MediaType("text/javascript", fileExtension = "js") + public val JPEG: MediaType = MediaType("image/jpeg", fileExtension = "jpeg") + public val JSON: MediaType = MediaType("application/json") + public val JSON_PROBLEM_DETAILS: MediaType = MediaType("application/problem+json", name = "HTTP Problem Details", fileExtension = "json") + public val JXL: MediaType = MediaType("image/jxl", fileExtension = "jxl") + public val LCP_LICENSE_DOCUMENT: MediaType = MediaType("application/vnd.readium.lcp.license.v1.0+json", name = "LCP License", fileExtension = "lcpl") + public val LCP_PROTECTED_AUDIOBOOK: MediaType = MediaType("application/audiobook+lcp", name = "LCP Protected Audiobook", fileExtension = "lcpa") + public val LCP_PROTECTED_PDF: MediaType = MediaType("application/pdf+lcp", name = "LCP Protected PDF", fileExtension = "lcpdf") + public val LCP_STATUS_DOCUMENT: MediaType = MediaType("application/vnd.readium.license.status.v1.0+json") + public val LPF: MediaType = MediaType("application/lpf+zip", fileExtension = "lpf") + public val MP3: MediaType = MediaType("audio/mpeg", fileExtension = "mp3") + public val MPEG: MediaType = MediaType("video/mpeg", fileExtension = "mpeg") + public val NCX: MediaType = MediaType("application/x-dtbncx+xml", fileExtension = "ncx") + public val OGG: MediaType = MediaType("audio/ogg", fileExtension = "oga") + public val OGV: MediaType = MediaType("video/ogg", fileExtension = "ogv") + public val OPDS1: MediaType = MediaType("application/atom+xml;profile=opds-catalog") + public val OPDS1_ENTRY: MediaType = MediaType("application/atom+xml;type=entry;profile=opds-catalog") + public val OPDS2: MediaType = MediaType("application/opds+json") + public val OPDS2_PUBLICATION: MediaType = MediaType("application/opds-publication+json") + public val OPDS_AUTHENTICATION: MediaType = MediaType("application/opds-authentication+json") + public val OPUS: MediaType = MediaType("audio/opus", fileExtension = "opus") + public val OTF: MediaType = MediaType("font/otf", fileExtension = "otf") + public val PDF: MediaType = MediaType("application/pdf", name = "PDF", fileExtension = "pdf") + public val PNG: MediaType = MediaType("image/png", fileExtension = "png") + public val READIUM_AUDIOBOOK: MediaType = MediaType("application/audiobook+zip", name = "Readium Audiobook", fileExtension = "audiobook") + public val READIUM_AUDIOBOOK_MANIFEST: MediaType = MediaType("application/audiobook+json", name = "Readium Audiobook", fileExtension = "json") + public val READIUM_WEBPUB: MediaType = MediaType("application/webpub+zip", name = "Readium Web Publication", fileExtension = "webpub") + public val READIUM_WEBPUB_MANIFEST: MediaType = MediaType("application/webpub+json", name = "Readium Web Publication", fileExtension = "json") + public val SMIL: MediaType = MediaType("application/smil+xml", fileExtension = "smil") + public val SVG: MediaType = MediaType("image/svg+xml", fileExtension = "svg") + public val TEXT: MediaType = MediaType("text/plain", fileExtension = "txt") + public val TIFF: MediaType = MediaType("image/tiff", fileExtension = "tiff") + public val TTF: MediaType = MediaType("font/ttf", fileExtension = "ttf") + public val W3C_WPUB_MANIFEST: MediaType = MediaType("application/x.readium.w3c.wpub+json", name = "Web Publication", fileExtension = "json") // non-existent + public val WAV: MediaType = MediaType("audio/wav", fileExtension = "wav") + public val WEBM_AUDIO: MediaType = MediaType("audio/webm", fileExtension = "webm") + public val WEBM_VIDEO: MediaType = MediaType("video/webm", fileExtension = "webm") + public val WEBP: MediaType = MediaType("image/webp", fileExtension = "webp") + public val WOFF: MediaType = MediaType("font/woff", fileExtension = "woff") + public val WOFF2: MediaType = MediaType("font/woff2", fileExtension = "woff2") + public val XHTML: MediaType = MediaType("application/xhtml+xml", fileExtension = "xhtml") + public val XML: MediaType = MediaType("application/xml", fileExtension = "xml") + public val ZAB: MediaType = MediaType("application/x.readium.zab+zip", name = "Zipped Audio Book", fileExtension = "zab") // non-existent + public val ZIP: MediaType = MediaType("application/zip", fileExtension = "zip") // Sniffing @@ -338,15 +338,15 @@ class MediaType( * You can register additional sniffers globally by modifying this list. * The sniffers order is important, because some formats are subsets of other formats. */ - val sniffers = Sniffers.all.toMutableList() + public val sniffers: MutableList = Sniffers.all.toMutableList() /** * Resolves a format from a single file extension and media type hint, without checking the actual * content. */ - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(mediaType = mediaType, fileExtension = fileExtension)"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - suspend fun of( + public fun of( mediaType: String? = null, fileExtension: String? = null, sniffers: List = MediaType.sniffers @@ -358,9 +358,9 @@ class MediaType( * Resolves a format from file extension and media type hints, without checking the actual * content. */ - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(mediaTypes = mediaTypes, fileExtensions = fileExtensions)"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - suspend fun of( + public fun of( mediaTypes: List, fileExtensions: List, sniffers: List = MediaType.sniffers @@ -372,8 +372,8 @@ class MediaType( * Resolves a format from a local file path. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofFile( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(file)"), level = DeprecationLevel.ERROR) + public fun ofFile( file: File, mediaType: String? = null, fileExtension: String? = null, @@ -385,9 +385,9 @@ class MediaType( /** * Resolves a format from a local file path. */ - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(file, mediaTypes = mediaTypes, fileExtensions = fileExtensions)"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") - suspend fun ofFile( + public fun ofFile( file: File, mediaTypes: List, fileExtensions: List, @@ -400,8 +400,8 @@ class MediaType( * Resolves a format from a local file path. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofFile( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(File(path))"), level = DeprecationLevel.ERROR) + public fun ofFile( path: String, mediaType: String? = null, fileExtension: String? = null, @@ -414,8 +414,8 @@ class MediaType( * Resolves a format from a local file path. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofFile( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(File(path), mediaTypes = mediaTypes, fileExtensions = fileExtensions)"), level = DeprecationLevel.ERROR) + public fun ofFile( path: String, mediaTypes: List, fileExtensions: List, @@ -428,8 +428,8 @@ class MediaType( * Resolves a format from bytes, e.g. from an HTTP response. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofBytes( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(bytes)"), level = DeprecationLevel.ERROR) + public fun ofBytes( bytes: () -> ByteArray, mediaType: String? = null, fileExtension: String? = null, @@ -442,8 +442,8 @@ class MediaType( * Resolves a format from bytes, e.g. from an HTTP response. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofBytes( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever().retrieve(bytes, mediaTypes = mediaTypes, fileExtensions = fileExtensions)"), level = DeprecationLevel.ERROR) + public fun ofBytes( bytes: () -> ByteArray, mediaTypes: List, fileExtensions: List, @@ -457,8 +457,8 @@ class MediaType( * Accepts the following URI schemes: content, android.resource, file. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofUri( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever(contentResolver = contentResolver).retrieve(uri)"), level = DeprecationLevel.ERROR) + public fun ofUri( uri: Uri, contentResolver: ContentResolver, mediaType: String? = null, @@ -473,8 +473,8 @@ class MediaType( * Accepts the following URI schemes: content, android.resource, file. */ @Suppress("UNUSED_PARAMETER") - @Deprecated(message = "Use MediaTypeRetriever instead", level = DeprecationLevel.ERROR) - suspend fun ofUri( + @Deprecated(message = "Use MediaTypeRetriever instead", replaceWith = ReplaceWith("MediaTypeRetriever(contentResolver = contentResolver).retrieve(uri, mediaTypes = mediaTypes, fileExtensions = fileExtensions)"), level = DeprecationLevel.ERROR) + public fun ofUri( uri: Uri, contentResolver: ContentResolver, mediaTypes: List, @@ -487,23 +487,23 @@ class MediaType( /* Deprecated */ @Deprecated("Use [READIUM_AUDIOBOOK] instead", ReplaceWith("MediaType.READIUM_AUDIOBOOK"), level = DeprecationLevel.ERROR) - val AUDIOBOOK: MediaType get() = READIUM_AUDIOBOOK + public val AUDIOBOOK: MediaType get() = READIUM_AUDIOBOOK @Deprecated("Use [READIUM_AUDIOBOOK_MANIFEST] instead", ReplaceWith("MediaType.READIUM_AUDIOBOOK_MANIFEST"), level = DeprecationLevel.ERROR) - val AUDIOBOOK_MANIFEST: MediaType get() = READIUM_AUDIOBOOK_MANIFEST + public val AUDIOBOOK_MANIFEST: MediaType get() = READIUM_AUDIOBOOK_MANIFEST @Deprecated("Use [READIUM_WEBPUB] instead", ReplaceWith("MediaType.READIUM_WEBPUB"), level = DeprecationLevel.ERROR) - val WEBPUB: MediaType get() = READIUM_WEBPUB + public val WEBPUB: MediaType get() = READIUM_WEBPUB @Deprecated("Use [READIUM_WEBPUB_MANIFEST] instead", ReplaceWith("MediaType.READIUM_WEBPUB_MANIFEST"), level = DeprecationLevel.ERROR) - val WEBPUB_MANIFEST: MediaType get() = READIUM_WEBPUB_MANIFEST + public val WEBPUB_MANIFEST: MediaType get() = READIUM_WEBPUB_MANIFEST @Deprecated("Use [OPDS1] instead", ReplaceWith("MediaType.OPDS1"), level = DeprecationLevel.ERROR) - val OPDS1_FEED: MediaType get() = OPDS1 + public val OPDS1_FEED: MediaType get() = OPDS1 @Deprecated("Use [OPDS2] instead", ReplaceWith("MediaType.OPDS2"), level = DeprecationLevel.ERROR) - val OPDS2_FEED: MediaType get() = OPDS2 + public val OPDS2_FEED: MediaType get() = OPDS2 @Deprecated("Use [LCP_LICENSE_DOCUMENT] instead", ReplaceWith("MediaType.LCP_LICENSE_DOCUMENT"), level = DeprecationLevel.ERROR) - val LCP_LICENSE: MediaType get() = LCP_LICENSE_DOCUMENT + public val LCP_LICENSE: MediaType get() = LCP_LICENSE_DOCUMENT @Suppress("UNUSED_PARAMETER") - @Deprecated("Renamed to [ofFile()]", ReplaceWith("MediaType.ofFile(file, mediaType, fileExtension, sniffers)"), level = DeprecationLevel.ERROR) - fun of( + @Deprecated("Use `MediaTypeRetriever` instead", level = DeprecationLevel.ERROR) + public fun of( file: File, mediaType: String? = null, fileExtension: String? = null, @@ -511,8 +511,8 @@ class MediaType( ): MediaType? = null @Suppress("UNUSED_PARAMETER") - @Deprecated("Renamed to [ofFile()]", ReplaceWith("MediaType.ofFile(file, mediaTypes, fileExtensions, sniffers)"), level = DeprecationLevel.ERROR) - fun of( + @Deprecated("Use `MediaTypeRetriever` instead", level = DeprecationLevel.ERROR) + public fun of( file: File, mediaTypes: List, fileExtensions: List, @@ -520,8 +520,8 @@ class MediaType( ): MediaType? = null @Suppress("UNUSED_PARAMETER") - @Deprecated("Renamed to [ofBytes()]", ReplaceWith("MediaType.ofBytes(bytes, mediaType, fileExtension, sniffers)"), level = DeprecationLevel.ERROR) - fun of( + @Deprecated("Use `MediaTypeRetriever` instead", level = DeprecationLevel.ERROR) + public fun of( bytes: () -> ByteArray, mediaType: String? = null, fileExtension: String? = null, @@ -529,8 +529,8 @@ class MediaType( ): MediaType? = null @Suppress("UNUSED_PARAMETER") - @Deprecated("Renamed to [ofBytes()]", ReplaceWith("MediaType.ofBytes(bytes, mediaTypes, fileExtensions, sniffers)"), level = DeprecationLevel.ERROR) - fun of( + @Deprecated("Use `MediaTypeRetriever` instead", level = DeprecationLevel.ERROR) + public fun of( bytes: () -> ByteArray, mediaTypes: List, fileExtensions: List, @@ -538,8 +538,8 @@ class MediaType( ): MediaType? = null @Suppress("UNUSED_PARAMETER") - @Deprecated("Renamed to [ofUri()]", ReplaceWith("MediaType.ofUri(uri, contentResolver, mediaType, fileExtension, sniffers)"), level = DeprecationLevel.ERROR) - fun of( + @Deprecated("Use `MediaTypeRetriever` instead", level = DeprecationLevel.ERROR) + public fun of( uri: Uri, contentResolver: ContentResolver, mediaType: String? = null, @@ -548,8 +548,8 @@ class MediaType( ): MediaType? = null @Suppress("UNUSED_PARAMETER") - @Deprecated("Renamed to [ofUri()]", ReplaceWith("MediaType.ofUri(uri, contentResolver, mediaTypes, fileExtensions, sniffers)"), level = DeprecationLevel.ERROR) - fun of( + @Deprecated("Use `MediaTypeRetriever` instead", level = DeprecationLevel.ERROR) + public fun of( uri: Uri, contentResolver: ContentResolver, mediaTypes: List, diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaTypeRetriever.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaTypeRetriever.kt index 881714e077..212d793bd2 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaTypeRetriever.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/MediaTypeRetriever.kt @@ -17,7 +17,7 @@ import org.readium.r2.shared.util.Either import org.readium.r2.shared.util.Url import org.readium.r2.shared.util.toUrl -class MediaTypeRetriever( +public class MediaTypeRetriever( resourceFactory: ResourceFactory = FileResourceFactory(), containerFactory: ContainerFactory = DirectoryContainerFactory(), archiveFactory: ArchiveFactory = DefaultArchiveFactory(), @@ -30,14 +30,14 @@ class MediaTypeRetriever( private val bytesSnifferContextFactory: BytesSnifferContextFactory = BytesSnifferContextFactory(archiveFactory) - suspend fun canonicalMediaType(mediaType: MediaType): MediaType = + public suspend fun canonicalMediaType(mediaType: MediaType): MediaType = retrieve(mediaType = mediaType.toString()) ?: mediaType /** * Resolves a media type from a single file extension and media type hint, without checking the actual * content. */ - suspend fun retrieve( + public suspend fun retrieve( mediaType: String? = null, fileExtension: String? = null, ): MediaType? { @@ -51,7 +51,7 @@ class MediaTypeRetriever( * Resolves a media type from file extension and media type hints without checking the actual * content. */ - suspend fun retrieve( + public suspend fun retrieve( mediaTypes: List, fileExtensions: List ): MediaType? { @@ -61,7 +61,7 @@ class MediaTypeRetriever( /** * Resolves a media type from a local file. */ - suspend fun retrieve( + public suspend fun retrieve( file: File, mediaType: String? = null, fileExtension: String? = null, @@ -72,7 +72,7 @@ class MediaTypeRetriever( /** * Resolves a media type from a local file. */ - suspend fun retrieve( + public suspend fun retrieve( file: File, mediaTypes: List, fileExtensions: List, @@ -83,7 +83,7 @@ class MediaTypeRetriever( /** * Resolves a media type from bytes, e.g. from an HTTP response. */ - suspend fun retrieve( + public suspend fun retrieve( bytes: () -> ByteArray, mediaType: String? = null, fileExtension: String? = null, @@ -94,7 +94,7 @@ class MediaTypeRetriever( /** * Resolves a media type from bytes, e.g. from an HTTP response. */ - suspend fun retrieve( + public suspend fun retrieve( bytes: () -> ByteArray, mediaTypes: List, fileExtensions: List, @@ -105,7 +105,7 @@ class MediaTypeRetriever( /** * Resolves a media type from a Uri. */ - suspend fun retrieve( + public suspend fun retrieve( uri: Uri, mediaType: String? = null, fileExtension: String? = null, @@ -116,7 +116,7 @@ class MediaTypeRetriever( /** * Resolves a media type from a Uri. */ - suspend fun retrieve( + public suspend fun retrieve( uri: Uri, mediaTypes: List, fileExtensions: List, diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Sniffer.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Sniffer.kt index 1ca69f1ac6..374d4cbba7 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Sniffer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/Sniffer.kt @@ -19,20 +19,20 @@ import org.readium.r2.shared.publication.* /** * Determines if the provided content matches a known media type. * - * @param context Holds the file metadata and cached content, which are shared among the sniffers. + * The context holds the file metadata and cached content, which are shared among the sniffers. */ -typealias Sniffer = suspend (context: SnifferContext) -> MediaType? +public typealias Sniffer = suspend (context: SnifferContext) -> MediaType? /** * Default media type sniffers provided by Readium. */ -object Sniffers { +public object Sniffers { /** * The default sniffers provided by Readium 2 to resolve a [MediaType]. * The sniffers order is important, because some formats are subsets of other formats. */ - val all: List = listOf( + public val all: List = listOf( ::xhtml, ::html, ::opds, ::lcpLicense, ::bitmap, ::webpubManifest, ::webpub, ::w3cWPUB, ::epub, ::lpf, ::archive, ::pdf, ::json ) @@ -42,7 +42,7 @@ object Sniffers { * * Must precede the HTML sniffer. */ - suspend fun xhtml(context: SnifferContext): MediaType? { + public suspend fun xhtml(context: SnifferContext): MediaType? { if (context.hasFileExtension("xht", "xhtml") || context.hasMediaType("application/xhtml+xml")) { return MediaType.XHTML } @@ -60,7 +60,7 @@ object Sniffers { } /** Sniffs an HTML document. */ - suspend fun html(context: SnifferContext): MediaType? { + public suspend fun html(context: SnifferContext): MediaType? { if (context.hasFileExtension("htm", "html") || context.hasMediaType("text/html")) { return MediaType.HTML } @@ -80,7 +80,7 @@ object Sniffers { } /** Sniffs an OPDS document. */ - suspend fun opds(context: SnifferContext): MediaType? { + public suspend fun opds(context: SnifferContext): MediaType? { // OPDS 1 if (context.hasMediaType("application/atom+xml;type=entry;profile=opds-catalog")) { return MediaType.OPDS1_ENTRY @@ -136,7 +136,7 @@ object Sniffers { } /** Sniffs an LCP License Document. */ - suspend fun lcpLicense(context: SnifferContext): MediaType? { + public suspend fun lcpLicense(context: SnifferContext): MediaType? { if (context.hasFileExtension("lcpl") || context.hasMediaType("application/vnd.readium.lcp.license.v1.0+json")) { return MediaType.LCP_LICENSE_DOCUMENT } @@ -153,7 +153,7 @@ object Sniffers { /** Sniffs a bitmap image. */ @Suppress("RedundantSuspendModifier") - suspend fun bitmap(context: SnifferContext): MediaType? { + public suspend fun bitmap(context: SnifferContext): MediaType? { if (context.hasFileExtension("avif") || context.hasMediaType("image/avif")) { return MediaType.AVIF } @@ -182,7 +182,7 @@ object Sniffers { } /** Sniffs a Readium Web Manifest. */ - suspend fun webpubManifest(context: SnifferContext): MediaType? { + public suspend fun webpubManifest(context: SnifferContext): MediaType? { if (context.hasMediaType("application/audiobook+json")) { return MediaType.READIUM_AUDIOBOOK_MANIFEST } @@ -217,7 +217,7 @@ object Sniffers { } /** Sniffs a Readium Web Publication, protected or not by LCP. */ - suspend fun webpub(context: SnifferContext): MediaType? { + public suspend fun webpub(context: SnifferContext): MediaType? { if (context.hasFileExtension("audiobook") || context.hasMediaType("application/audiobook+zip")) { return MediaType.READIUM_AUDIOBOOK } @@ -271,7 +271,7 @@ object Sniffers { } /** Sniffs a W3C Web Publication Manifest. */ - suspend fun w3cWPUB(context: SnifferContext): MediaType? { + public suspend fun w3cWPUB(context: SnifferContext): MediaType? { if (context !is ResourceSnifferContext) { return null } @@ -290,7 +290,7 @@ object Sniffers { * * Reference: https://www.w3.org/publishing/epub3/epub-ocf.html#sec-zip-container-mime */ - suspend fun epub(context: SnifferContext): MediaType? { + public suspend fun epub(context: SnifferContext): MediaType? { if (context.hasFileExtension("epub") || context.hasMediaType("application/epub+zip")) { return MediaType.EPUB } @@ -315,7 +315,7 @@ object Sniffers { * - https://www.w3.org/TR/lpf/ * - https://www.w3.org/TR/pub-manifest/ */ - suspend fun lpf(context: SnifferContext): MediaType? { + public suspend fun lpf(context: SnifferContext): MediaType? { if (context.hasFileExtension("lpf") || context.hasMediaType("application/lpf+zip")) { return MediaType.LPF } @@ -366,7 +366,7 @@ object Sniffers { * * Reference: https://wiki.mobileread.com/wiki/CBR_and_CBZ */ - suspend fun archive(context: SnifferContext): MediaType? { + public suspend fun archive(context: SnifferContext): MediaType? { if (context.hasFileExtension("cbz") || context.hasMediaType("application/vnd.comicbook+zip", "application/x-cbz", "application/x-cbr")) { return MediaType.CBZ } @@ -402,7 +402,7 @@ object Sniffers { * * Reference: https://www.loc.gov/preservation/digital/formats/fdd/fdd000123.shtml */ - suspend fun pdf(context: SnifferContext): MediaType? { + public suspend fun pdf(context: SnifferContext): MediaType? { if (context.hasFileExtension("pdf") || context.hasMediaType("application/pdf")) { return MediaType.PDF } @@ -419,7 +419,7 @@ object Sniffers { } /** Sniffs a JSON document. */ - suspend fun json(context: SnifferContext): MediaType? { + public suspend fun json(context: SnifferContext): MediaType? { if (context.hasMediaType("application/problem+json")) { return MediaType.JSON_PROBLEM_DETAILS } @@ -438,7 +438,7 @@ object Sniffers { * Sniffs the system-wide registered media types using [MimeTypeMap] and * [URLConnection.guessContentTypeFromStream]. */ - suspend fun system(context: SnifferContext): MediaType? { + public suspend fun system(context: SnifferContext): MediaType? { val mimetypes = tryOrNull { MimeTypeMap.getSingleton() } ?: return null @@ -472,7 +472,7 @@ object Sniffers { return withContext(Dispatchers.IO) { context.contentAsStream() - ?.let { URLConnection.guessContentTypeFromStream(it) } + .let { URLConnection.guessContentTypeFromStream(it) } ?.let { sniffType(it) } } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/SnifferContext.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/SnifferContext.kt index 2d0bed7eee..435f0fe339 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/SnifferContext.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/mediatype/SnifferContext.kt @@ -20,24 +20,24 @@ import org.readium.r2.shared.resource.* import org.readium.r2.shared.util.Url import timber.log.Timber -sealed class SnifferContext( +public sealed class SnifferContext( mediaTypes: List = emptyList(), fileExtensions: List = emptyList() ) { /** Media type hints. */ - val mediaTypes: List = mediaTypes + public val mediaTypes: List = mediaTypes .mapNotNull { MediaType.parse(it) } /** File extension hints. */ - val fileExtensions: List = fileExtensions + public val fileExtensions: List = fileExtensions .map { it.lowercase(Locale.ROOT) } /** Finds the first [Charset] declared in the media types' `charset` parameter. */ - val charset: Charset? get() = + public val charset: Charset? get() = this.mediaTypes.firstNotNullOfOrNull { it.charset } /** Returns whether this context has any of the given file extensions, ignoring case. */ - fun hasFileExtension(vararg fileExtensions: String): Boolean { + public fun hasFileExtension(vararg fileExtensions: String): Boolean { for (fileExtension in fileExtensions) { if (this.fileExtensions.contains(fileExtension.lowercase(Locale.ROOT))) { return true @@ -52,7 +52,7 @@ sealed class SnifferContext( * * Implementation note: Use [MediaType] to handle the comparison to avoid edge cases. */ - fun hasMediaType(vararg mediaTypes: String): Boolean { + public fun hasMediaType(vararg mediaTypes: String): Boolean { @Suppress("NAME_SHADOWING") val mediaTypes = mediaTypes.mapNotNull { MediaType.parse(it) } for (mediaType in mediaTypes) { @@ -63,10 +63,10 @@ sealed class SnifferContext( return false } - abstract suspend fun release() + public abstract suspend fun release() } -class HintSnifferContext( +public class HintSnifferContext( mediaTypes: List = emptyList(), fileExtensions: List = emptyList() ) : SnifferContext(mediaTypes, fileExtensions) { @@ -74,7 +74,7 @@ class HintSnifferContext( override suspend fun release() {} } -sealed class ContentAwareSnifferContext( +public sealed class ContentAwareSnifferContext( mediaTypes: List = emptyList(), fileExtensions: List = emptyList() ) : SnifferContext(mediaTypes, fileExtensions) @@ -87,8 +87,8 @@ sealed class ContentAwareSnifferContext( * @param mediaTypes Media type hints. * @param fileExtensions File extension hints. */ -class ResourceSnifferContext internal constructor( - val resource: Resource, +public class ResourceSnifferContext internal constructor( + public val resource: Resource, mediaTypes: List = emptyList(), fileExtensions: List = emptyList() ) : ContentAwareSnifferContext(mediaTypes, fileExtensions) { @@ -99,7 +99,7 @@ class ResourceSnifferContext internal constructor( * It will extract the charset parameter from the media type hints to figure out an encoding. * Otherwise, fallback on UTF-8. */ - suspend fun contentAsString(): String? = + public suspend fun contentAsString(): String? = try { if (!loadedContentAsString) { loadedContentAsString = true @@ -117,7 +117,7 @@ class ResourceSnifferContext internal constructor( private var _contentAsString: String? = null /** Content as an XML document. */ - suspend fun contentAsXml(): ElementNode? { + public suspend fun contentAsXml(): ElementNode? { if (!loadedContentAsXml) { loadedContentAsXml = true _contentAsXml = withContext(Dispatchers.IO) { @@ -138,7 +138,7 @@ class ResourceSnifferContext internal constructor( /** * Content parsed from JSON. */ - suspend fun contentAsJson(): JSONObject? = + public suspend fun contentAsJson(): JSONObject? = try { contentAsString()?.let { JSONObject(it) } } catch (e: Exception) { @@ -146,7 +146,7 @@ class ResourceSnifferContext internal constructor( } /** Readium Web Publication Manifest parsed from the content. */ - suspend fun contentAsRwpm(): Manifest? = + public suspend fun contentAsRwpm(): Manifest? = Manifest.fromJSON(contentAsJson()) /** @@ -155,7 +155,7 @@ class ResourceSnifferContext internal constructor( * A byte stream can be useful when sniffers only need to read a few bytes at the beginning of * the file. */ - suspend fun contentAsStream(): InputStream? = + public suspend fun contentAsStream(): InputStream = ResourceInputStream(resource) /** @@ -164,7 +164,7 @@ class ResourceSnifferContext internal constructor( * It can be used to check a file signature, aka magic number. * See https://en.wikipedia.org/wiki/List_of_file_signatures */ - suspend fun read(range: LongRange? = null): ByteArray? = + public suspend fun read(range: LongRange? = null): ByteArray? = resource.read(range).getOrNull() /** @@ -184,13 +184,13 @@ class ResourceSnifferContext internal constructor( * A companion type of [Sniffer] holding the type hints (file extensions, media types) and * providing an access to the file content. * - * @param resource Underlying content holder. + * @param container Underlying content holder. * @param mediaTypes Media type hints. * @param fileExtensions File extension hints. */ -class ContainerSnifferContext internal constructor( - val container: Container, - val isExploded: Boolean, +public class ContainerSnifferContext internal constructor( + public val container: Container, + public val isExploded: Boolean, mediaTypes: List = emptyList(), fileExtensions: List = emptyList() ) : ContentAwareSnifferContext(mediaTypes, fileExtensions) { @@ -301,7 +301,7 @@ internal class BytesSnifferContextFactory( bytes: ByteArray, mediaTypes: List = emptyList(), fileExtensions: List = emptyList(), - ): ContentAwareSnifferContext? { + ): ContentAwareSnifferContext { val resource: Resource = BytesResource(bytes) return archiveFactory.create(resource, password = null) .fold( diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/pdf/PdfDocument.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/pdf/PdfDocument.kt index 3012ccf98f..f283fa3bf0 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/pdf/PdfDocument.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/pdf/PdfDocument.kt @@ -24,16 +24,16 @@ import org.readium.r2.shared.util.SuspendingCloseable import org.readium.r2.shared.util.cache.Cache import org.readium.r2.shared.util.mediatype.MediaType -interface PdfDocumentFactory { +public interface PdfDocumentFactory { /** Class for the type of document this factory produces. */ - val documentType: KClass + public val documentType: KClass /** Opens a PDF from a [file]. */ - suspend fun open(file: File, password: String?): T + public suspend fun open(file: File, password: String?): T /** Opens a PDF from a Fetcher resource. */ - suspend fun open(resource: Fetcher.Resource, password: String?): T + public suspend fun open(resource: Fetcher.Resource, password: String?): T } /** @@ -44,7 +44,9 @@ interface PdfDocumentFactory { * around. */ @ExperimentalReadiumApi -suspend fun PdfDocumentFactory.cachedIn(holder: PublicationServicesHolder): PdfDocumentFactory { +public suspend fun PdfDocumentFactory.cachedIn( + holder: PublicationServicesHolder +): PdfDocumentFactory { val namespace = requireNotNull(documentType.qualifiedName) val cache = holder.cacheService?.cacheOf(documentType, namespace) ?: return this return CachingPdfDocumentFactory(this, cache) @@ -73,64 +75,64 @@ private class CachingPdfDocumentFactory( /** * Represents a PDF document. */ -interface PdfDocument : SuspendingCloseable { +public interface PdfDocument : SuspendingCloseable { /** * Permanent identifier based on the contents of the file at the time it was originally * created. */ - val identifier: String? get() = null + public val identifier: String? get() = null /** * Number of pages in the document. */ - val pageCount: Int + public val pageCount: Int /** * Default reading progression of the document. */ - val readingProgression: ReadingProgression? get() = null + public val readingProgression: ReadingProgression? get() = null /** * The first page rendered as a cover. */ - suspend fun cover(context: Context): Bitmap? = null + public suspend fun cover(context: Context): Bitmap? = null // Values extracted from the document information dictionary, defined in PDF specification. /** * The document's title. */ - val title: String? get() = null + public val title: String? get() = null /** * The name of the person who created the document. */ - val author: String? get() = null + public val author: String? get() = null /** * The subject of the document. */ - val subject: String? get() = null + public val subject: String? get() = null /** * Keywords associated with the document. */ - val keywords: List get() = emptyList() + public val keywords: List get() = emptyList() /** * Outline to build the table of contents. */ - val outline: List get() = emptyList() + public val outline: List get() = emptyList() - data class OutlineNode( + public data class OutlineNode( val title: String?, val pageNumber: Int?, // Starts from 1. val children: List ) // To allow extensions on the Companion object. - companion object + public companion object } /** @@ -140,11 +142,11 @@ interface PdfDocument : SuspendingCloseable { * relative to. */ @ExperimentalReadiumApi -fun List.toLinks(documentHref: String): List = +public fun List.toLinks(documentHref: String): List = map { it.toLink(documentHref) } @ExperimentalReadiumApi -fun PdfDocument.OutlineNode.toLink(documentHref: String): Link = +public fun PdfDocument.OutlineNode.toLink(documentHref: String): Link = Link( href = "$documentHref#page=$pageNumber", type = MediaType.PDF.toString(), diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/TextTokenizer.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/TextTokenizer.kt index 99cd9b95de..f6ceeb16e1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/TextTokenizer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/TextTokenizer.kt @@ -15,11 +15,11 @@ import org.readium.r2.shared.util.Language /** A tokenizer splitting a String into range tokens (e.g. words, sentences, etc.). */ @ExperimentalReadiumApi -typealias TextTokenizer = Tokenizer +public typealias TextTokenizer = Tokenizer /** A text token unit which can be used with a [TextTokenizer]. */ @ExperimentalReadiumApi -enum class TextUnit { +public enum class TextUnit { Word, Sentence, Paragraph } @@ -28,10 +28,10 @@ enum class TextUnit { * version. */ @ExperimentalReadiumApi -class DefaultTextContentTokenizer private constructor( +public class DefaultTextContentTokenizer private constructor( private val tokenizer: TextTokenizer ) : TextTokenizer by tokenizer { - constructor(unit: TextUnit, language: Language?) : this( + public constructor(unit: TextUnit, language: Language?) : this( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) IcuTextTokenizer(language = language, unit = unit) else @@ -45,7 +45,7 @@ class DefaultTextContentTokenizer private constructor( */ @ExperimentalReadiumApi @RequiresApi(Build.VERSION_CODES.N) -class IcuTextTokenizer(language: Language?, unit: TextUnit) : TextTokenizer { +public class IcuTextTokenizer(language: Language?, unit: TextUnit) : TextTokenizer { private val iterator: BreakIterator @@ -80,7 +80,7 @@ class IcuTextTokenizer(language: Language?, unit: TextUnit) : TextTokenizer { * Use [IcuTextTokenizer] for better results. */ @ExperimentalReadiumApi -class NaiveTextTokenizer(unit: TextUnit) : TextTokenizer { +public class NaiveTextTokenizer(unit: TextUnit) : TextTokenizer { private val iterator: java.text.BreakIterator = when (unit) { TextUnit.Word -> java.text.BreakIterator.getWordInstance() TextUnit.Sentence -> java.text.BreakIterator.getSentenceInstance() diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/Tokenizer.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/Tokenizer.kt index f15b864e54..5d6398993a 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/Tokenizer.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/tokenizer/Tokenizer.kt @@ -10,6 +10,6 @@ import org.readium.r2.shared.ExperimentalReadiumApi /** A tokenizer splits a piece of data [D] into a list of [T] tokens. */ @ExperimentalReadiumApi -fun interface Tokenizer { - fun tokenize(data: D): List +public fun interface Tokenizer { + public fun tokenize(data: D): List } diff --git a/readium/shared/src/test/java/org/readium/r2/shared/publication/PublicationTest.kt b/readium/shared/src/test/java/org/readium/r2/shared/publication/PublicationTest.kt index 754e38c6fa..10df7b011a 100644 --- a/readium/shared/src/test/java/org/readium/r2/shared/publication/PublicationTest.kt +++ b/readium/shared/src/test/java/org/readium/r2/shared/publication/PublicationTest.kt @@ -101,28 +101,6 @@ class PublicationTest { ) } - @Test fun `set {self} link`() { - val publication = createPublication() - publication.setSelfLink("http://manifest.json") - - assertEquals( - "http://manifest.json", - publication.linkWithRel("self")?.href - ) - } - - @Test fun `set {self} link replaces existing {self} link`() { - val publication = createPublication( - links = listOf(Link(href = "previous", rels = setOf("self"))) - ) - publication.setSelfLink("http://manifest.json") - - assertEquals( - "http://manifest.json", - publication.linkWithRel("self")?.href - ) - } - @Test fun `get {baseUrl} computes the URL from the {self} link`() { val publication = createPublication( links = listOf(Link(href = "http://domain.com/path/manifest.json", rels = setOf("self"))) diff --git a/readium/streamer/build.gradle.kts b/readium/streamer/build.gradle.kts index 2d9a1df15b..863a49d9ca 100644 --- a/readium/streamer/build.gradle.kts +++ b/readium/streamer/build.gradle.kts @@ -42,6 +42,10 @@ android { namespace = "org.readium.r2.streamer" } +kotlin { + explicitApi() +} + rootProject.ext["publish.artifactId"] = "readium-streamer" apply(from = "$rootDir/scripts/publish-module.gradle") diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt index b05c7245c2..999380e135 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt @@ -11,7 +11,6 @@ import org.readium.r2.shared.PdfSupport import org.readium.r2.shared.asset.Asset import org.readium.r2.shared.error.Try import org.readium.r2.shared.error.getOrElse -import org.readium.r2.shared.fetcher.Fetcher import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.protection.AdeptFallbackContentProtection import org.readium.r2.shared.publication.protection.ContentProtection @@ -34,10 +33,10 @@ internal typealias PublicationTry = Try = Try = emptyList(), ignoreDefaultParsers: Boolean = false, @@ -109,12 +108,12 @@ class PublicationFactory constructor( * @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 + * 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 A [Publication] or a [Publication.OpeningException] in case of failure. */ - suspend fun open( + public suspend fun open( asset: Asset, contentProtectionScheme: ContentProtection.Scheme? = null, credentials: String? = null, @@ -237,12 +236,4 @@ class PublicationFactory constructor( is PublicationParser.Error.ParsingFailed -> Publication.OpeningException.ParsingFailed(e) } - - @Suppress("UNCHECKED_CAST") - private suspend fun List.lazyMapFirstNotNullOrNull(transform: suspend (T) -> R): R? { - for (it in this) { - return transform(it) ?: continue - } - return null - } } diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/container/Container.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/container/Container.kt index 2ee9f6b3ba..7049c0262e 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/container/Container.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/container/Container.kt @@ -10,8 +10,6 @@ package org.readium.r2.streamer.container import java.io.InputStream -import org.readium.r2.shared.RootFile -import org.readium.r2.shared.drm.DRM /** * Container of a publication @@ -28,23 +26,26 @@ import org.readium.r2.shared.drm.DRM * @func dataInputStream : return the InputStream of content */ @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) -interface Container { - var rootFile: RootFile - var drm: DRM? - - @Deprecated("Use [publication.get()] to access publication content.") - fun data(relativePath: String): ByteArray - @Deprecated("Use [publication.get()] to access publication content.") - fun dataLength(relativePath: String): Long - @Deprecated("Use [publication.get()] to access publication content.") - fun dataInputStream(relativePath: String): InputStream +public interface Container { + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public fun data(relativePath: String): ByteArray + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public fun dataLength(relativePath: String): Long + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public fun dataInputStream(relativePath: String): InputStream } -sealed class ContainerError : Exception() { - object streamInitFailed : ContainerError() - object fileNotFound : ContainerError() - object fileError : ContainerError() - data class missingFile(val path: String) : ContainerError() - data class xmlParse(val underlyingError: Error) : ContainerError() - data class missingLink(val title: String?) : ContainerError() +public sealed class ContainerError : Exception() { + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public object streamInitFailed : ContainerError() + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public object fileNotFound : ContainerError() + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public object fileError : ContainerError() + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public data class missingFile(public val path: String) : ContainerError() + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public data class xmlParse(public val underlyingError: Error) : ContainerError() + @Deprecated("Use [publication.get()] to access publication content.", level = DeprecationLevel.ERROR) + public data class missingLink(public val title: String?) : ContainerError() } diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/fetcher/Fetcher.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/fetcher/Fetcher.kt index 902ef763ae..618629d200 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/fetcher/Fetcher.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/fetcher/Fetcher.kt @@ -14,14 +14,14 @@ import org.readium.r2.shared.publication.Publication @Suppress("UNUSED_PARAMETER", "unused") @Deprecated("Use [publication.get(link)] to access publication content.", level = DeprecationLevel.ERROR) -class Fetcher( - var publication: Publication, +public class Fetcher( + public var publication: Publication, private val userPropertiesPath: String?, ) { - fun data(path: String): ByteArray? = throw NotImplementedError() + public fun data(path: String): ByteArray? = throw NotImplementedError() - fun dataStream(path: String): InputStream = throw NotImplementedError() + public fun dataStream(path: String): InputStream = throw NotImplementedError() - fun dataLength(path: String): Long = throw NotImplementedError() + public fun dataLength(path: String): Long = throw NotImplementedError() } diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/PublicationParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/PublicationParser.kt index ae68261bdd..a3882ffa5f 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/PublicationParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/PublicationParser.kt @@ -18,9 +18,9 @@ import org.readium.r2.shared.util.mediatype.MediaType /** * Parses a Publication from an asset. */ -interface PublicationParser { +public interface PublicationParser { - data class Asset( + public data class Asset( val name: String, val mediaType: MediaType, val fetcher: Fetcher @@ -34,14 +34,14 @@ interface PublicationParser { * mistakes. This is useful to warn users of potential rendering issues or help authors * debug their publications. */ - suspend fun parse( + public suspend fun parse( asset: Asset, warnings: WarningLogger? = null ): Try - sealed class Error : org.readium.r2.shared.error.Error { + public sealed class Error : org.readium.r2.shared.error.Error { - class FormatNotSupported : Error() { + public class FormatNotSupported : Error() { override val message: String = "Asset format not supported." @@ -50,16 +50,16 @@ interface PublicationParser { null } - class ParsingFailed(override val cause: org.readium.r2.shared.error.Error?) : Error() { + public class ParsingFailed(override val cause: org.readium.r2.shared.error.Error?) : Error() { - constructor(message: String) : this(MessageError(message)) + public constructor(message: String) : this(MessageError(message)) override val message: String = "An error occurred while parsing the publication." } - class IO( - val resourceError: Resource.Exception + public class IO( + public val resourceError: Resource.Exception ) : Error() { override val message: String = @@ -69,7 +69,7 @@ interface PublicationParser { ThrowableError(resourceError) } - class OutOfMemory( + public class OutOfMemory( override val cause: org.readium.r2.shared.error.Error? ) : Error() { diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioLocatorService.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioLocatorService.kt index 2251486b21..6250afa947 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioLocatorService.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioLocatorService.kt @@ -14,7 +14,7 @@ import org.readium.r2.shared.publication.services.LocatorService import org.readium.r2.shared.util.mediatype.MediaType /** Locator service for audio publications. */ -class AudioLocatorService(private val readingOrder: List) : LocatorService { +public class AudioLocatorService(private val readingOrder: List) : LocatorService { /** Duration per reading order index. */ private val durations: List = @@ -86,9 +86,9 @@ class AudioLocatorService(private val readingOrder: List) : LocatorService return null } - companion object { + public companion object { - fun createFactory(): (Publication.Service.Context) -> AudioLocatorService = { + public fun createFactory(): (Publication.Service.Context) -> AudioLocatorService = { AudioLocatorService(readingOrder = it.manifest.readingOrder) } } diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioParser.kt index 3878c89855..9bb44f4b52 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/audio/AudioParser.kt @@ -26,7 +26,7 @@ import org.readium.r2.streamer.parser.PublicationParser * * It can also work for a standalone audio file. */ -class AudioParser : PublicationParser { +public class AudioParser : PublicationParser { override suspend fun parse( asset: PublicationParser.Asset, diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EncryptionParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EncryptionParser.kt index c314b1b8b7..d3816e7e63 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EncryptionParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EncryptionParser.kt @@ -6,9 +6,9 @@ package org.readium.r2.streamer.parser.epub -import org.readium.r2.shared.drm.DRM import org.readium.r2.shared.parser.xml.ElementNode import org.readium.r2.shared.publication.encryption.Encryption +import org.readium.r2.shared.publication.protection.ContentProtection import org.readium.r2.shared.util.Href internal object EncryptionParser { @@ -24,7 +24,7 @@ internal object EncryptionParser { val retrievalMethod = node.getFirst("KeyInfo", Namespaces.SIG) ?.getFirst("RetrievalMethod", Namespaces.SIG)?.getAttr("URI") val scheme = if (retrievalMethod == "license.lcpl#/encryption/content_key") - DRM.Scheme.lcp.rawValue else null + ContentProtection.Scheme.Lcp.uri else null val algorithm = node.getFirst("EncryptionMethod", Namespaces.ENC) ?.getAttr("Algorithm") ?: return null diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt index eac71522fc..c370ed7603 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt @@ -7,7 +7,6 @@ package org.readium.r2.streamer.parser.epub import org.readium.r2.shared.ExperimentalReadiumApi -import org.readium.r2.shared.Search import org.readium.r2.shared.error.Try import org.readium.r2.shared.error.getOrElse import org.readium.r2.shared.extensions.addPrefix @@ -33,8 +32,8 @@ import org.readium.r2.streamer.parser.PublicationParser * @param reflowablePositionsStrategy Strategy used to calculate the number of positions in a * reflowable resource. */ -@OptIn(ExperimentalReadiumApi::class, Search::class) -class EpubParser( +@OptIn(ExperimentalReadiumApi::class) +public class EpubParser( private val reflowablePositionsStrategy: EpubPositionsService.ReflowableStrategy = EpubPositionsService.ReflowableStrategy.recommended ) : PublicationParser { @@ -61,7 +60,6 @@ class EpubParser( displayOptions = parseDisplayOptions(asset.fetcher) ).adapt() - @Suppress("NAME_SHADOWING") var fetcher = asset.fetcher manifest.metadata.identifier?.let { fetcher = TransformingFetcher(fetcher, EpubDeobfuscator(it)::transform) diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubPositionsService.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubPositionsService.kt index e191433986..d9d2f07cd6 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubPositionsService.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubPositionsService.kt @@ -29,16 +29,18 @@ import org.readium.r2.shared.util.use * https://github.com/readium/architecture/blob/master/models/locators/best-practices/format.md#epub * https://github.com/readium/architecture/issues/101 */ -class EpubPositionsService( +public class EpubPositionsService( private val readingOrder: List, private val presentation: Presentation, private val fetcher: Fetcher, private val reflowableStrategy: ReflowableStrategy ) : PositionsService { - companion object { + public companion object { - fun createFactory(reflowableStrategy: ReflowableStrategy = ReflowableStrategy.recommended): ( + public fun createFactory( + reflowableStrategy: ReflowableStrategy = ReflowableStrategy.recommended + ): ( Publication.Service.Context ) -> EpubPositionsService = { context -> @@ -56,15 +58,15 @@ class EpubPositionsService( * * Note that a fixed-layout resource always has a single position. */ - sealed class ReflowableStrategy { + public sealed class ReflowableStrategy { /** Returns the number of positions in the given [resource] according to the strategy. */ - abstract suspend fun positionCount(resource: Fetcher.Resource): Int + public abstract suspend fun positionCount(resource: Fetcher.Resource): Int /** * Use the original length of each resource (before compression and encryption) and split it * by the given [pageLength]. */ - data class OriginalLength(val pageLength: Int) : ReflowableStrategy() { + public data class OriginalLength(val pageLength: Int) : ReflowableStrategy() { override suspend fun positionCount(resource: Fetcher.Resource): Int { val length = resource.link().properties.encryption?.originalLength ?: resource.length().getOrNull() @@ -78,7 +80,7 @@ class EpubPositionsService( * Use the archive entry length (whether it is compressed or stored) and split it by the * given [pageLength]. */ - data class ArchiveEntryLength(val pageLength: Int) : ReflowableStrategy() { + public data class ArchiveEntryLength(val pageLength: Int) : ReflowableStrategy() { override suspend fun positionCount(resource: Fetcher.Resource): Int { val length = resource.link().properties.archive?.entryLength ?: resource.length().getOrNull() @@ -88,14 +90,14 @@ class EpubPositionsService( } } - companion object { + public companion object { /** * Recommended historical strategy: archive entry length split by 1024 bytes pages. * * This strategy is used by Adobe RMSDK as well. * See https://github.com/readium/architecture/issues/123 */ - val recommended = ArchiveEntryLength(pageLength = 1024) + public val recommended: ReflowableStrategy = ArchiveEntryLength(pageLength = 1024) } } diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/image/ImageParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/image/ImageParser.kt index 7fff4206f4..ab0bd2f56f 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/image/ImageParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/image/ImageParser.kt @@ -22,7 +22,7 @@ import org.readium.r2.streamer.parser.PublicationParser * * It can also work for a standalone bitmap file. */ -class ImageParser : PublicationParser { +public class ImageParser : PublicationParser { override suspend fun parse( asset: PublicationParser.Asset, diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/pdf/PdfParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/pdf/PdfParser.kt index 68a286f1fe..a5c9af3fcc 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/pdf/PdfParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/pdf/PdfParser.kt @@ -24,7 +24,7 @@ import org.readium.r2.streamer.parser.PublicationParser */ @PdfSupport @OptIn(ExperimentalReadiumApi::class) -class PdfParser( +public class PdfParser( context: Context, private val pdfFactory: PdfDocumentFactory<*> ) : PublicationParser { diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/readium/ReadiumWebPubParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/readium/ReadiumWebPubParser.kt index 521e15815c..fafde70595 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/readium/ReadiumWebPubParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/readium/ReadiumWebPubParser.kt @@ -22,7 +22,7 @@ import org.readium.r2.streamer.parser.audio.AudioLocatorService /** * Parses any Readium Web Publication package or manifest, e.g. WebPub, Audiobook, DiViNa, LCPDF... */ -class ReadiumWebPubParser( +public class ReadiumWebPubParser( private val context: Context? = null, private val pdfFactory: PdfDocumentFactory<*>?, ) : PublicationParser { diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/server/Globals.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/server/Globals.kt index 8a36b30cfb..0ca9f8bc2b 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/server/Globals.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/server/Globals.kt @@ -13,4 +13,4 @@ package org.readium.r2.streamer.server * Created by aferditamuriqi on 10/3/17. */ @Deprecated("Use Publication::localBaseUrlOf() instead", level = DeprecationLevel.ERROR) -const val BASE_URL = "http://127.0.0.1" +public const val BASE_URL: String = "http://127.0.0.1" diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/server/Resources.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/server/Resources.kt index 21396ce60e..6eb6dd4887 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/server/Resources.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/server/Resources.kt @@ -9,23 +9,5 @@ package org.readium.r2.streamer.server -import org.readium.r2.shared.Injectable - @Deprecated("The HTTP server is not needed anymore (see migration guide)", level = DeprecationLevel.ERROR) -class Resources { - val resources: MutableMap = mutableMapOf() - - fun add(key: String, body: String, injectable: Injectable? = null) { - injectable?.let { - resources[key] = Pair(body, injectable.rawValue) - } ?: run { - resources[key] = body - } - } - - fun get(key: String): String? = - when (val resource = resources[key]) { - is Pair<*, *> -> resource.first as? String - else -> resource as? String - } -} +public class Resources diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/server/Server.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/server/Server.kt index 0ce0181dbd..032ae2b666 100755 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/server/Server.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/server/Server.kt @@ -14,7 +14,7 @@ import org.nanohttpd.router.RouterNanoHTTPD @Suppress("Unused_parameter") @Deprecated("The HTTP server is not needed anymore (see migration guide)", level = DeprecationLevel.ERROR) -class Server( +public class Server( port: Int, context: Context, enableReadiumNavigatorSupport: Boolean = true @@ -22,8 +22,8 @@ class Server( @Suppress("Unused_parameter") @Deprecated("The HTTP server is not needed anymore (see migration guide)", level = DeprecationLevel.ERROR) -abstract class AbstractServer( - private var port: Int, - private val context: Context, - private val enableReadiumNavigatorSupport: Boolean = true, +public abstract class AbstractServer( + port: Int, + context: Context, + enableReadiumNavigatorSupport: Boolean = true, ) : RouterNanoHTTPD("127.0.0.1", port) diff --git a/test-app/src/main/java/org/readium/r2/testapp/bookshelf/BookRepository.kt b/test-app/src/main/java/org/readium/r2/testapp/bookshelf/BookRepository.kt index ddda84f49e..d4abc22ca1 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/bookshelf/BookRepository.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/bookshelf/BookRepository.kt @@ -31,8 +31,6 @@ import org.readium.r2.shared.asset.AssetType import org.readium.r2.shared.error.Try import org.readium.r2.shared.error.flatMap import org.readium.r2.shared.error.getOrElse -import org.readium.r2.shared.extensions.tryOrLog -import org.readium.r2.shared.extensions.tryOrNull import org.readium.r2.shared.publication.Locator import org.readium.r2.shared.publication.Publication import org.readium.r2.shared.publication.indexOfFirstWithHref @@ -52,6 +50,8 @@ import org.readium.r2.testapp.domain.model.Highlight import org.readium.r2.testapp.utils.extensions.authorName import org.readium.r2.testapp.utils.extensions.copyToTempFile import org.readium.r2.testapp.utils.extensions.moveTo +import org.readium.r2.testapp.utils.tryOrLog +import org.readium.r2.testapp.utils.tryOrNull import timber.log.Timber class BookRepository( diff --git a/test-app/src/main/java/org/readium/r2/testapp/domain/model/Book.kt b/test-app/src/main/java/org/readium/r2/testapp/domain/model/Book.kt index 818175252d..75ed666f90 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/domain/model/Book.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/domain/model/Book.kt @@ -61,7 +61,7 @@ data class Book( identifier = identifier, progression = progression, rawMediaType = mediaType.toString(), - rawAssetType = assetType.rawValue, + rawAssetType = assetType.value, drm = drm?.uri, cover = cover, ) diff --git a/test-app/src/main/java/org/readium/r2/testapp/drm/LcpManagementViewModel.kt b/test-app/src/main/java/org/readium/r2/testapp/drm/LcpManagementViewModel.kt index 2640c9d7f5..f0bd7295e4 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/drm/LcpManagementViewModel.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/drm/LcpManagementViewModel.kt @@ -31,7 +31,7 @@ class LcpManagementViewModel( override val type: String = "LCP" override val state: String? - get() = lcpLicense.status?.status?.rawValue + get() = lcpLicense.status?.status?.value override val provider: String? get() = lcpLicense.license.provider diff --git a/test-app/src/main/java/org/readium/r2/testapp/reader/preferences/PreferencesManagers.kt b/test-app/src/main/java/org/readium/r2/testapp/reader/preferences/PreferencesManagers.kt index b56ac76cf0..2ef0c025e9 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/reader/preferences/PreferencesManagers.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/reader/preferences/PreferencesManagers.kt @@ -37,8 +37,8 @@ import org.readium.r2.navigator.preferences.Configurable import org.readium.r2.navigator.preferences.PreferencesFilter import org.readium.r2.navigator.preferences.PreferencesSerializer import org.readium.r2.shared.ExperimentalReadiumApi -import org.readium.r2.shared.extensions.tryOrNull import org.readium.r2.testapp.utils.extensions.stateInFirst +import org.readium.r2.testapp.utils.tryOrNull class PreferencesManager

> internal constructor( val preferences: StateFlow

, diff --git a/test-app/src/main/java/org/readium/r2/testapp/utils/Exception.kt b/test-app/src/main/java/org/readium/r2/testapp/utils/Exception.kt new file mode 100644 index 0000000000..b371b79089 --- /dev/null +++ b/test-app/src/main/java/org/readium/r2/testapp/utils/Exception.kt @@ -0,0 +1,25 @@ +package org.readium.r2.testapp.utils + +import timber.log.Timber + +/** + * Returns the result of the given [closure], or null if an [Exception] was raised. + */ +inline fun tryOrNull(closure: () -> T): T? = + tryOr(null, closure) + +/** + * Returns the result of the given [closure], or [default] if an [Exception] was raised. + */ +inline fun tryOr(default: T, closure: () -> T): T = + try { closure() } catch (e: Exception) { default } + +/** + * Returns the result of the given [closure], or null if an [Exception] was raised. + * The [Exception] will be logged. + */ +inline fun tryOrLog(closure: () -> T): T? = + try { closure() } catch (e: Exception) { + Timber.e(e) + null + } diff --git a/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/InputStream.kt b/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/InputStream.kt index 494396f5be..3fe0ba21aa 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/InputStream.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/InputStream.kt @@ -15,7 +15,7 @@ import java.io.InputStream import java.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.readium.r2.shared.extensions.tryOrNull +import org.readium.r2.testapp.utils.tryOrNull suspend fun InputStream.toFile(file: File) { withContext(Dispatchers.IO) { diff --git a/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/URL.kt b/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/URL.kt deleted file mode 100644 index 1c22d80cb0..0000000000 --- a/test-app/src/main/java/org/readium/r2/testapp/utils/extensions/URL.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* Module: r2-testapp-kotlin -* Developers: Quentin Gliosca -* -* Copyright (c) 2020. European Digital Reading Lab. All rights reserved. -* Licensed to the Readium Foundation under one or more contributor license agreements. -* Use of this source code is governed by a BSD-style license which is detailed in the -* LICENSE file present in the project repository where this source code is maintained. -*/ - -package org.readium.r2.testapp.utils.extensions - -import java.io.File -import java.io.FileOutputStream -import java.net.URL -import java.util.* -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.readium.r2.shared.extensions.extension -import org.readium.r2.shared.extensions.tryOr -import org.readium.r2.shared.extensions.tryOrNull - -suspend fun URL.download(path: String): File? = tryOr(null) { - val file = File(path) - withContext(Dispatchers.IO) { - openStream().use { input -> - FileOutputStream(file).use { output -> - input.copyTo(output) - } - } - } - file -} - -suspend fun URL.copyToTempFile(dir: String): File? = tryOrNull { - val filename = UUID.randomUUID().toString() - val path = "$dir$filename.$extension" - download(path) -} diff --git a/test-app/src/main/res/drawable/cnl.png b/test-app/src/main/res/drawable/cnl.png deleted file mode 100644 index 6dfe3affed84f808bb75d707fcc0c03b8d2bed40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20299 zcmd42b980F^B^8OlZiR8ZQHgvvH4;r6I&D8wr$%^CbrGZd~|mA_g$R*>sRNz_xj$h zE_TJsw{laT@cUqJZ9&B4foQ&Cv-U%bAqcnHlL9ql;j=v-V}XkD0S zZ5>SM7&tgM=;#^g7#V54FlYd7HjetPG&TUDe^U@P1{gY++c}!s+Tj1CsBd8F+>R{vmbWJqUhWo&J1;|Tb| zW%v)SotdqpEx^q7e?j^`-TwoFFVo7%{D;SXDT}rBe^>wpR*yDBIdv{o7IU{}vfvNC=-?M&Hof=C2AA|J?v% zVSPtq9>OoLvD45q(=f6tGcs~Ae0h!j>yne6{-3BawnpYAZvPW1hcW{rCkq=V3*-NQ z`ZZ;Y^d0s8kH|)boF=vo*7{!xn_KIf8q?X?m=fau$BdjpwpO+dUyQ$`WBTv!O9%dGRH-9+?^RFeSZ}tC7=kLP&J9jw6 z%>iFtb^F)SQ8KpwSIf#A{~yzZQ{V9KGT-7(S zfF!<22n#5?rk`iHr0a;eb!EB8wt2PHYpRTG3@-od_C4-+M3cnlM-r66e-o4u1d$LY z`VK z)5&$f*5&wX=WSFmCFVaMIGke@e)uo2vyOlf6Mcc9t`SIF>=!W5F#?bL?Mg;Z@iqDj zwjc>lj$&Wx&`AOcBe{QvVuHJauKrJ0mq>iq=PEyZuhOJbZj+#3dMNIwyl0O;ucr;7V)gnX%6u zY5y?0Ez9q_1hfy?e1?)$=EiJI$bAOttmLZ?H%4po$2?somiCMQ$EA1=u@Q5~NuZ;u z%x7sOv!>D4KG*{Sp?FuA1*$E0$tGR863?7o7SXOdPg=ZES;KpUe~Y7jS5!lIgL{=K z$5k`39edE(*0m_D@?mn92RFnPgbvgj^afKla&c( z3}`0Y+ZnI!76>o&_;gD!!f!qmp4uQ29L6u-Q%iUTVB&Nc`QuR70D}u(_urnj)^b0i zV9hKk-ivd1=EZ{$@OGjrj_G`&@nL=@RYp~o0(-|^4uNk}o#4vx=Ij_AnlIr9?m)}k z&J`sX(xz;+85vP?|ARCfE(3gHT_iBBq#&#S?o+o=x503kF~6537`4r2r?v<~E(U!3 zJIN$4xIMl_g`+OV)&Xoxm_uV2?7@nxlqvBR)6^~#<2O-K{2_LbeyBWl6p`!x?>|%O zG&7dias25dhklO6s@IDMUP%D6p@|%0ygl1J*6duYq|H9J zEvx{>(V09Pf85!Dbpy|J({$7M!TP~QW&gm$d?ZGWF~oqZuc^hIIovU9huUJU=i%yA zy}{3zG0i7PEDhrq4lsq!v^2bCV0Wm-A9N#Nc$&9M@7E2uuUB^+iHH2dlLXU+P!0y+ zH_=@eZ3AG85@H1A5S8bo0048cHOTklD`-HzA$k{eglXkEFbqf2W-Z2k>|-gXS5CNz zdcm4kwJz7>(e~a^s^N4^e2XNN;G!90mw{Q=%px?hDcm9EPvR$6l<*Z}8b^azkrZdY zZ0YSu$soar4H*xej_sThWPs2X8ZuS^nM{9gspd(FjfEa&_yt+-cidh4U4E=;dx6wN zvMJzD?kN)XA!ueL$FkC;WD75BkLSv(Joq%36};%FM8&{Rp>k!9hxPIiny}G zqerj?T!z)~_gKXM+FNahD5cwWAfZlrvx>r{1i*%xoBmD3n&-QS7j^c^q<%6c@ zlwGBvKS8NAzhJ)k}<-ab7ZdKk%wmj3i=c&>l%RibYvm7e^) zGK0m8r z9+ZA+leaz7D3!2QH^3@E1}Ko6ZO#JHrlGmR1cL#_T}x>zhKeX$uOTx~hdd;77pKN@ zm3J^N=@SLsp7BDQb+IDG7oa$iY-zrnD@mM&*TWYLB!P4?N((uHDZxoWo0W-U+-2yEDmA5NY-6s| z3_rZ$z!rpmfTy(=EG6k(oM-|*WRWLHq3CEq(nrCliWNz;V<4ytwjX2ZMNA+506ewj z25SVq+z%E^z$p7Z%N*!=r$O+hTpE^BPM$vQ*vu{EwnTitmPK%rHf8aA#R zGgYDShl3}M6s@XoA>h_4&1B4*Y-zu9jJF=~3RGS$ADb)Eg)?>tRCah!IBR15fQJU+ z*a|ovm1kU=;=RI-=B&#--lsyI>bCRsj77}NlD$Sm5psOD6Q>vmI9B5^&HMpSD>sxN z#HV1lKQ6uQe!Y=qkb46fXiVFyafMxhkTp(6RW6~Cr`{7^s|yGazkzDAKZ9_{*lcN| zU-hClg_?bRdKJ`3n@ypZ$hiFAZ6le@!h95J{I*9P`<-4S)P3@g2eJ=Z{^r=4n03Lx zAA+CMF>(`giavW8e2?)y+*~>|MRm8jTh9{i82XrQsj#a-Z)dGBS-5{%V|L9++(A(M zb9vjKBAf5N&-gEC9c|86URruoP%er7ItzEdttqLHT*%MONG#hykI2eg!`S?wT3ak@ zQ?0^w`Ln0)w4^+;aP7DDE?!w&uFGR%&ePfGa<{16;?p1g0%A5&o}`Evk3SRE+;BSY zSo(208-^O&AhI+=g6y$;VPd0I){u^gS(rPFJX-eRv-8YDQ^YV%f`J6C%idDf>C%j~ zbUmyMkoqmnAB6qVHSVnRwq zcTN2?z}GFZ@(V+R;+bOJyoAqiR?^;LI@$M8ylcM;^8CYH;xVy6eHi*2#C9&0q-NjM z$-8yCZi3=HE`B$tZeD06B^*gdDjn!Kfw1W*b@r|`7T#Id$tyXZKUkvnkY3bsccUe} ze_zC6>inj~>INDroeU&4(Ela8nCYf7O?B!PctRuwRcgf~AL>ZYXDd{>K z64IjPF2p>x60sg3qtc8*-8F0A@PqBG%q`2%-l zU6QhHJMr)M6DcP@vDTV_FGqu|i^8DiT|KmHmYS@3P5o5FTC$if(xmy(VtsOvx2cgv ziP{NRT52A#S&9m%Gpx$`1c1x@neLk|$K||E-d4>$+EUPf&!1WY6L$P<#M<~k(g)eG zF^p1i2HfU{H6>LX5t1H3&_PLrz0X|CDUv*NibuNZ8{{x6XuI;uTq2x~`>Rr0deT55 zefliiGn{@5sg!E(VXvSZV(;k;&mXZXp|BTB;}IN7mkTD{Zkhf%7&x!wsxlJ~JA4bm zGb>w!t6u1oQhSKfUA@9em|NE?89K0FdY9B|>u1L;xJX6ZdNe3Xvzq>pOh>Sb#3`|! z!g%YFfW4?sWn~RQYba^5l~%K2O1@s1NDtsHouF_0`z3dbn2r+q1d+B5JY_^x6(gL;e)8Pb@5gnUANmuzpEBli;NKIp~PM*`+F)x+JH|}d}0%3IWdTQU0*nX%^;wH!wn-GIG zYr#JEEalt#>UP1D zKCLcq+*jFV^4m?DN@JdSG3kf~oo~*&}@cJ1{*9w$|BEf8(EseoL z6etbW4Z%2Qz6;6BMt@Vi^=V&+X_J=pXAtR$EZtC&F|9|)WxpotT5LRK{_fxS*ml5b z2Z3931GQ+UMT#$$@^{6f@i+u;Rm65Zn(Ja^{+_ISW{-PJry9DzB$$0bSXy{Wf;YK> zq_baQv$cgzs!ilGK~DqdylJY|a6@IuPszMjCb?HRQ#$1LcmPwIm7g5856;QP(IV2!iFruAZzk4Q0uqxUAux>5fOL^7u~hKOka8LB`c80 z1b>5hqQ27Jp4#>WyF$C7510UBj{`p)i+KJ@-w7Q!n`ZAOjh7*&;5i)nSX?}bUdPR+wCylPsV>)J!t?a2zF`l!#g*Mhy(|SDx5dWG4rJrzjfhGgolV!NRaX13HjOB zOMgdf#Sjq|mZ)gftdJ%&u_DcCCql@wKao%F>_U5XoVDQ+)kBp_wh5Sac0rMPIPHYr znjgM=?(d5qtnw)oB3?y9*u_Ofb1SFRalAMz0vF*mHPIC&Qr`et)i4B7tiV z+efMOn-Z*4pi8a2kd4x(zY)Pk_(FmVtv3Axx|VjYD&z^Ags}Xfh$a(h%CiRb{;d+7 zwTtP%_PJZObw_vCE58_}-FeA}nu^@|*ERBR;5A;q!0RGU`GXp44{MEe*XD<#(z|nD z{t!l0d*4~M301p6>XfV_$y65opSm9jFZH{X7O_M<@r0GwIpyT9^lx!ERQ-8)Ya4eu zF6!_pk`8AR1DEIbJ4sU8ytif9cl|slcSb39Yf*Dssiz*cNcZL-H^kAsyV7=J5=v`b zCM_PjOu)G-hp=i(_`Bj?88sq@lo(W*`)pL@LJ2_O53JDjXg?VR2YMr_4}=6>H7wjPDFy z1oL1OcKytg5=KGREoPEUdsmIDeR?Z=*90`)n#*e^Re8tupmur zj@FrpwWU|sP-M5G7k|(ovJd<_tK`RgQU<^yRlz1a)ObqshY3O+^Bmzq{u3+mLDjHF zqkCYeD~i)%bvVP4GB$)(FYyMT$bHZJ3d5PfJdHWePHKmw4f0(lJxh3f`eG$jbuSAE zTCa;@%j-j4yJHb~1(e&23Vv2Y&ghsr(Gw%Zm73&l4kwMl zgnOTUo=%06b1Df>C^HqVwszu?NM>k77=r^JNly59i&}^mlId= zUMP^b@dHU@!V2?|pZi+G+yH6*T|2VFv0bCp$f?asg=J;nm^yEmcn(gHv@i(+AV>_fnTfQY4Xzwi^McFUvVnl4hfQua7#gUh*7jT6m?G)=<{jUmkl%v(w#q} zklW2TeX*JRi)Ly9b zEND}Y{`8}lXn|)QJb)MEQWJUUgW0<72gdqkYT#?-((jt5zfmAUq=-H~dTNA>;sI)1 z4d#j5nt|_k{?%#j;&&wL?V1c5O|VB8VV4~c=ql4G9UqSHa|fZ@ghrY)pWEM$S}Guj z!YYc_65Kyz=Ujhf4G(}L>(w@_)E#R#t+327sY{5*L#TM#W1!-big`I_64hxazc%bt zSE_JYt2Q`0bxgnQ+RJ)u0W8um+o zJ2?z|1xnk2_oyeA*f+?v$VMZX)^Ds?N)wXzjNqIEK?;lKLW`4wE*>xpkUJ9m4)xhJ znxrapuvzn{++v^B2i#zp*lo zFWik_PL#S+w>kMj010sOek+O!?#3WNIm$_+c(|cnWt_;a{J90ZbY=*BC6}CXph$`w zBVq(WZc(dyB{A)mB#8E%N|3?a%N9@(Sdhj&N^A%2G-}n|4QvYKi^a7(0%v{jHp)WC zCM`?(se`o1R|;Jd#5DlmI{_#qJuFZrEyn%P>5}$vC4DuEAJV5lRw5(r$qOk3!Da9; z9cw&nRvS0iOkB@>Vtw&pweYlTu6ap{uO#PM&UaXPuwzvE`q~q*djFo_CRyw#lVy)Wgk3Qy%!P43c03)a)-Qu#gyCaRm z&eY!!*AR)EFlIpy*aV{jHsETKa2@KuxgU@BiMpT(=T4R$Kbn5H5p$mZA)08{9mO^H zc7cwpnJ)VaMhEH`R5Q^~gWDv;?E6po2y(WA)*w>YK00@^<@=7YqFw9EABpOM@5Y@j zcEo&dvqfNmQYVprBKc~#o@lRl`KGZ)_lx#bC_8E%X=>;Z9}?71Hf;AWDOi8^6Ih1} zLmY;yNh?ihE9bP8DJOf{6I^%kt$(}l#G-i+k%7^9sUBv@G_F^0i`*Ywu6VgvTy>VM zMMSz!SVVi4feyC8N!fJSk7AyZbYRYtY*C!-Xe{WVnUZVLWi>C;{x%P=vz$7P9wGTi zX(}k7qYfvdu*~H5v>8!*Ie89MvysUyTWX@h2Ko8fmgDKj8-*PAH-)^P=(HoO9YfB` z0P5pD!r&%|b$lDKu^YnYMTQ(lu@ zhZ9Ghab-49v%se^0l$~dBw-pFE4tH^ z+uyL{s-q{uJ`}#6^?>%+QMk_PqWh!Ls2-<7-w8<%OkmxAHGBBgO8ITcyrS#AHKo>C zSm*tB^SwDsA#Z|Kr-MiZi&sOrflwv4ov7mHxGZ$%`gv-S6Jm|(qJxk+iPKAoKw5fN zPMPcZ)6={R(?d=zZLt}}YHcT-eU|E5S8Jk}&DE9NtJkC)pF7?NwAkMb%ckUNV1LIr zXYzs2(0=Z``MF19I-{bYFW&l41gV&KV1|0*oXo5D(%Au`0uDoQa35CyggZM{KtQ^1 zK+m-9Ropp%7zTJ`Xea&i9T0!PmF3@&#gk6D64GZ7WeE&zC!8;wAE3^^i!nfwPUO7{ zDv<0wpMtR^VE{~4*$BIDekVm+eB|WkAvss*HAoR@a20ntw|?ku$@P$#fbFVIbADYq zFhX{qbG1;K)$V5Lw6_DDHuu}){z=}OQJMi`w;{I|zpZ00hY%V4nc2JEDV0q-+q_Np zdQ(THjZb~}x9yGLt2v+f3cFE1z-A>Z{rRbC=O%5oS++`cH6VnM^HxQ0vS1=5!ajq~ z^=6fwql*N(fcX>2cta+!@q*-lAf_HDkJ)op<2m^?J$m7JuSTMg=nvs+gr-iIvT}6s z%f*><)1Q9l7N*Uf1?A@j0X#$PP-8r;D@-3>w%=`!BAiBqiVuwaHZLJ2zj6^EeyAnp zF4CbAzK%3Jds$^CrTJ<3$<*;3;$kBT4l;+(aHm8mZcZ6~yrk`}c}^6a&7>)_cZbJDXbh zXP`C`FBb7&9eFPN3#NXA&DzmexSOc|M*)5pT-=dQ@A?xa^7T<+2Q8hcc)nm8F+X8K zDadI9J}SeBNk`K4y1ZyU8%t2nvB^0~>RAE z;$2R+Y$3FMe=4(`7)AN_Lv7lY_IY;Go1}H>_}BA5m<(b+UslVMe12dL|8g98c_#y6 z`cL#czL6Zha%Re|-D%s#(Rg(@t~=?}KdcWTk%whc*MW4{PH9ST@wzvqOQ&H7Rey*# zf`pRucZ&mlbl<8=(773$xF)ypDGyKqtC2wSsj=&5DvSH_^Lyp_3uOpKiqH8k1ojkY};s*dQB!>mm}t^`;BIe)$jOcOOAE%I%d!V zNECXtyyuY03A&1IANzB?SJrJ(36aWLlwKfoMDTc`FvH3$%!WBv_@vXml%o9u_W7xg zxpG$~T{5z*>FdZC%!R+&oezglUD5q2M7cOVjtB_Rw1CM}p`W9sjQHN$TBH*N=F+@} z26Z=jYq`>0uW8LSxjdWAsVkT+lJhM~fx!NS&Y<_P-52|{2}R0KiPKjs0;CV?d$!}; z2rqMrgqCvcrmipwG$ghjm zRx%KEGFSaKE*hU5DN||QgBvmjc#ew>5|4O^PH{SDe;*vkxkoXSbh-j(EPHp49Tlc$ zJ0;Lhz=?1K!Sxsg8X%5X`v@~7BEnPa3Nekhowk*f{+0HOv>i!J*fb;aaS1>e7GfE~ zxuYG$bpjk6=Dw1q9#W5yx2xX)n^cC4o*!^NeOXpvz>eh=j#iX~x4d0Pgl}oR`XnYZ zLtFJdZPQdE2}O|Zv1`!m#89rGw012#volZO(?V~_LB1!nkn1(rT-xP2IX^_qQx7ER z8vpCDhe0mv+!p+{w5b;M{5A3cYpMHBh@%MNLn3_tomj?k3dfrCqwP~3T*m{|Vr;S< z?Dsus^F748`{7U+qDOjML}cni;s;!T#kE<}&*_>t7}u!1ug7dVgSKS{9$UK-caMu2 z!oQRSMP`;Tsiaf4Z}w{@xGV~>5-KZ7%H0BjY$;I_^;+g^4V3M3U0p8i+#XYuB_i2X z{D@!Nn8Z0)G(TQn+wZLN2FbRK?yHbVQHC)@i$J@58O!J-424{nq zvLId$xky=z0X^YUrtlz4E=o};4@%sK6oBU?1(?tEG#j0#^~1jUq_fM- zVBV;13AQgHGc7 zXg$;=c^YNDg^JBJB|2`BMq2pDZGy{ttY^~%9xZYIMg~$;)7LEoZHIckG~~d)sb8QZ z!<`@I^$wR`kuPp5avAc^O*n+)#Wud61WY)~VWq;z?Wk1O@f>{Uuq=1HqY1XI7kaf- z&qC`-hftj$N?O0et)g0e z=w0t-Gn`s~k=?CZvtE)TZG&0^b?IbRdoE;9O4CiT*@3XIvN+gmEUmv-r5L+>>KF1m z;N?`^dR*eGnMgG!|2&U7<|{3Kp$q;vYhMS7b4`fLa8$Fr+*IS>Nv}RHb0J}I_n#e9 zT8r1iF_R-s^DUwum`igKjo;3)x#T>~U|Vwtg2LxcF3SZ$VzprHJS@GYkwd~Giw zL&x2p+86#R_7O44NhgQTMu@xhQvCfN8tw^X8OTOVj^ zWVZe!9wJi$OxDq+wMKq;i0|rxeEc}teF7L{h>fcncuq3}RxuCSp34>LJ+$}B1BLas z23xo1u{Z&+mULhETDZN=gB)A-R>+!6niFLW2Jog!PTDFtK6c}0@W>c@MDTsq$v5qs zk-DVkYqgbH{Wf5V*hDM2sLVUYQ%SuPcNxN@n=~~oU(quzBem<}5uKOgF=ml`dh*W- z3JwQGnw9t2Xwir8`kf#eWU!Z!m|o^mepIFNKPzbOpJiXA8q98|@bks=#Q_o>)>l3I z?ivqSSoS&CJ=5AboFGZXlq1CCUbZX5Mw{7Ed~ts5`7z9&Z&!kc23ujb`H=yNK@9wS zQQ>AM@SQ)XBybai$$%yNx>HRbp5|;@*OPp>*mNjPSG?4Gs0~wt=?AUv6nE?nETpm^ zt}w%tufMOBM`5qyiq)IfeKYwrD)JFTu-L+L$71l{SJ{||7F1{dMr!vP`WZeUEkoX1 zHil?t!L^mP1fZx0`BRw?Lfq|J?@9eYYdup;az#a<9EnlhqMJD9h(nl_3D;$xA$U$_ zM#z?Od3z?4F=)2V@7mqF%fH*=*ln(bm-sn8 zA~0m?mVI*YPwBtX_rHsIy zQ)6>?kW^mAosYYck6g5gEZQTC-ou!M^E5&ms+`0f2;Y}ghQzTFa7Aan8HVnLH?G5%#R1OiNK9Y z@7f-ylwuNgYPVNBBQtEGx!!|;NFa9P=RQqz0sYvv zbyT~S-8x*yG<^OH8~fO8%I~4o5<<0paBX z@S36*gYEp|TdJe<4-9`FHiG@gVM0zB(~zuI_w)qo85$z2$0!(dUqmzvslLq!b-nej#GJZ}%r(R$AjZkLI8s~W39YI2(KtJ+!Ha#^3 z6)YbGqg^TrwR*B7Dx{9(wENGen{Qh)U#j=bD%MsfVOL_V^XkBl|7adqJHk*MG{3^SOws9*K^Q<$#MZ{{3rjm-Q7eG1Q|Rq5 zJ35@WF5mXl^6*tSbxBFbR)PPcTfjh%- z4To+qu9xkyz&AECQVS~U`!Xi=6&t@&4Mt@|dYBIxUygABHSY)eDaGZ-Kp}FZxhe8j zS8}(rj?yjKAHs_GH>G%`BF~>2=yYv1WJ?mL%Ek7Sd3V!Nuk5syN8ddWZF%~vthcUg%=udr5h*fZGe)t3vkhY(;jCU#+2*0YH<;5)*4)zR8?mlyk&fTf= zEV28D2x0kLht>B4(bKgFYlVBe|mYOt-_oV?n6dq*;l$+DMp0e&?l zMP)H3D1OoR@WRh>bNBqI(bVB+GKW6ib;@|~Ri-tB55H~X)Wf(99_)6exxIno>C*e! zyUh?ag~7%C8wQ^Hn^F^+am<$ekS`$Q`b|zH_pZjYQEp-Xj39T?#-Q|(ys7E?0E)5S zrYQj?f3pk=Q(6vUM#J?f*c z`J0Qz#uzFO4+}S$@JPe$7Q99<{$Sj=`T{Kdrb~qZccAdP9KinW;kq%r=smgiAT9Gd z*rZ1u1N&Bt9Q-|}r`r>*lfcB;?jHF0Km_DhGBY5|CG<$d!U&(BLJE~d9CW%M;U2Q6 z?Z z;i-osEZob~N|ZI~7d7RY^C;%#zQbATS}S+{mv}uL6Twy=bOc zc(ktzU3XzpgDm6kZ&?@5^a45~8W6JEp|?ywkGD1)%f;z4 zXKOe{dpxh?{OmbdkMQ`~Jnh8w#$u<{O0`g^O;%W0PDKYC&;oYrGO}{Pr`9X-qDS? z4r|wl*cVd4S$x(qoOy4mbIs!_wwg1_8VgLhFq`6!`Z2(vLdwdX(pG9Kk-@XryqPHE zDq;0*-7h^TK8BANEvr*?Z&ildKoO3Cm*E=` zuC-x%w;R~tt63^39xA_dX5x{W|FMpbdnjeJq{ZFDndeZ@P3Z@SHp(8%`LKjCQ%?pn zneIWuL!(>~@=r4+F0=0pGQ_M%?KcB0erl{~QSN;T^uXphFNK;FAAw;xR0w?=iwHyrQj^ zTwg$`Cz1gbXCU6=v7us+14ZI#m}-9O+y1nI4L(%bPZ`dR~E%m#wPkQxWb9 z8FJw;?^9?nrtG0Ef#)@sO%|^fzRdjCRUx(D<3b4^}aTbECE_bd{R ziHqj-XTj(;EGgwCNOm9IG-I{$Zp1WuI_X|5A~LKy;^Nn4I@Ca>^5W&=?C<`b|If@< zjhuB~h(|P|lE`CXs2K0~O+qUl>8C?{fK)7@a-)c4NEC)1<%E!!l%(hb+ZPwgE~56G z43TzpZmlIOl9!Sz3SW^PBN(5~?I2vI)7gDV!G=B!kPSgop=)N+6 z*YZ|csI5PJpk=4tcnpTOb_au}jzrPDLlaarV~^opWGB@f2dpG*7RrFc6&tX4j%oC4 zPO)kK;oOaJ6acrSjp%%mo<6?!{#O4XShTp}1F8m!2f+%Imtj~BYl040>hNd}`F^&4 zfd{!>$GdIl$d!?*iR<7S=bV@xHY|XmDgb8oYqI4h4Fp0zXaz$agUfqritT?G2E945UjdazXcgi3HE zPE1#Hcg@;MKwr^pyW{Uvi)V%cHYVP{P7KuqQ-NdwR&W0NU?$Iu$?F^6FP28goy zto}u3?CYpu<4XQBB+T1ZycgG8c)7vt2`r&-xj^f6@z^k|YmNk3K^TrLnPuzKmLz`Ia#TxUP z!QuH6_Ku4j2GJjDGtR%>m5>RTg0;62_(tx!)P0R}Gp{}<+PDo&^<5|9pk;7hPxX6` zO9>>m51|DQpZwgo`7vqLuv}1qr#;JTq}TEIU9D<9Lq;H4hGs=+SoU7AJ(-NEL1OVr zO);rBK@vn3i|dps^F_VaG4?1(qGda3WiKvkF%c3uV4Iz|wd$8&@7WZRyqekaWK18? zAL0OW7#Hiwc?b&(Zi^xNh3bgFudSuX-s`dRaNUqg z&o`%-O3!~%hqXE58fj-z^_J3SY)oTRi@I@{F@7Svs&iN-qDS?uHa&K32`MH_r(!c zG3;m??nK~3E@??Bz88=8RnD?V1*Wz179u4T6=m+9gCjz|!B0ncXpv1M<>f7;@N=K% zNu5-c(Cs`3GOZkB5>V&P+=){#qp?GR4_QB`=cRl8Tn)TAQ65Yk8MV@$&EA0z0z*rh z-Pi3HW#wTWTUotirl`I8oIoP$fEz~KTY}&A6wd$}`Zn)t-@|uY*ksdc<^-^rHbk3zwLEO#IM!Vc&m(Z(F#E}zvzfRC=X-^2JJUPWaG#Mm7aaO0z!R&QoK>7dcZBo4<6GV&=tWey}DLk;6gjVhp|w`C0VuS`XQ}+ z`SH1)+veetphUnJWnR_d0E2h=^=J!G!RWjGslTq&;B_AZk{~y)9p`AKs}|Swxr%Pl zY4or&MGPhJ?2D>8jIOiliaZ?B2JtYvDmTdW^*|r8d`frGF-0MLq;n*9`PuOllGtOp z>$NZ{4B<-(juh2?DjM8 znnMFcMMuh1uF??rxZh40c@G$O{cub1tA4$hdz%qPNH7i9;3g$!n4NsZt0n~HDDlFP zqx9`30cU63ES8K4fMmp{gU{mqT|SB9_J?;qvfqq>jWU@7GG~05g>9#lE$eAZ1NSCb zV9BFL<_EQti5p{@3ttuhHX|hzR6bbpVrVU2HvGpPVidJXb{!fw}Az^`p9S5 z?p|s&ZZwl0kOC&JUN-wXULT)7r%dr&bY6QtT(|oSpv`JLYbxn>F^B;AG=#hPtI|j> zv)iwscxT^c7e~Q36q6#zb7>lo)Hlxq*gj0Wj}FVcF4Y##HaJNY*(@A3Y7ImP62u6v z12gZJoZ-4QQ6Jg;Z(U5VcATG`F4s2P8OH_;6BHB`#}T6xIK$uTpXN_=y%&u)Tj+|p zS?VQve&kS5?aF_LvtFepo3inYBWdg<+co=on~N~_Y(VKs>zqPO_g?SkhaG_h`AE4X z1+a?KhAH?TSmgacYbr2Ct_fwSZK}{yFeB6VT`?oht%a)K-~;}(JNUTqqGO4Hc^Q8;r_LQI#~mTI(Er@iA`{<;;? zNXx9gv}csV^4z>u9-{JIc}(q-)!LUECHc*76na zia3RN=*Vm}jiv#s=q*s9RlTQTFQu2}s<4Jr%TGnT#wKEcsc6$muo<(5I1EyD;~@=SQW#OHX_29?f>m?+#VVyq!VL7iw{^7c-~L?}GT z!}Jh)c3n6WdSbF{_XP-+_Gx3xVqX_@dCLrXREalNV~YnVo-i?N zE*;^gdv_hBC1R$E-m_cRtaqaQLBaL=f~=n4IE&&t`GV^u-hTYPXL$S`LxdSF!ll4E z8BgJ0(#;hQ`a{z1;-Jx7IHHq&vxhcsrW)GtK@a0Mfzg^Kx>oZr$iszaFv*mVQw zQ`GyeA^s2{^YtzII@VW2WjjjMXLIq*DU3?ZBFXcapzSdg<<=^g6$^aDnd=vLhP2(g zz-(F=g(ENqt?Io^)`P!W}#S0q@7>@p*h+@5kf)czho3r{oCGGAi*-iTv30Kk$b1J#Y6oL8gs1h@3Zi zOyUzdBy2R_57vq3rwp?K+lTg%#!VFG!P5@rYbT9>yeIofABTo&F&qNg_!$@)B>r z_=IlJ^)XfYySgI5)ue~1gS#GCFFFL=1^?(zP!H`U>opP?{-R<)&I34fk$V!q^%tbY zHebwyYz|14(y50&w&$gLOyeF!_>j7fyKk!{Y-XK#@p;pE4a7toCknJogq0Nv@IiK> ztjr8Ux0(DX&#g2rv-aGg*;9 zD002@XLt^87*pwjS+G4zbX|pqg{N6i($EWs&5w&rQ(CUY4mZ1UqHnUDyU^$%yjx8k z<0J#teN0M)YEKP%!L+<)JL0f@x*>_0UDW09#Rc(7h?wRYRvmwfu>AD;Q~ zpv;*9A4={h{9Wcy@chL718)*@K0?p(-w9|P<@Q@J`6b_z3JC{hSGuEg zd^wNP5NqN#t>5LQZL}4*8ysJx-$GXWv(Z}9$dW#vpd&jvECcG;7tatuBsTU3DLQBW zM((|J*D|X&cZ?x&xCk@)bBVM%xiWjbmWR;IPv#kk&?h_7rY1j&cC6?qj68-FT{#O? z{(cK=Cjb51QYkMC=fvxCf9ssF6>SJ4o}p^ZV+S}Wtf(B?>5g6+t{7>pYq=5^BO4i< z^3l}T1%26}AR?l!uxGG~{gsrWouHTMtgM6hIJTi$P8k@B>&T5;6Lobzcl1dSAO0b# zipQ&8cH@KRl~p2JF+TnKCbPy(i*)vGKpl8v@2=WzR&!6@k!gGRh-0sT5pifc0JeQK zD0?r!meF%i#FQsNM>Qb3e5$_v{>g}pHY7JAUk04xnA}lGH{NIUb*=C5 zxe~*xOK#I%?CtgH=2AnURd->#@UXe@SEdO%4vB_3-K0miR^#)hO#R>T?m5<-b;;wb z^wZC;MLu2gqKsEp@r;{WnQf35^mW?SOpT9c&fE4`1qFMU9k}hpLVnsb99ZrLxI3V9 z=zNkSy{yMpwiMJ`IrOT)fPoh!A@ZDp+nOX+!ovWZK!GmZ~D z7^ncYWl|9dn#d-6ozUYLZdNH(XWxt>7N@DstFiKpu0Bu*Y3RIvA8Ik^tEp@oi=CU4 z1}>mfpV69_N*6kUOaGHf(Rk1F@z@(YfC0a&Cit05SLlFQmQCfXu;qR=b(EIn# z^@4zHg7TYQt1nKEPl?15I=f`ku)$z`Cmwa?yF$C#S1#3;1nG_{}yJe3xlNgI%uf#bb_)bM_GP=SZ572IYGbFtb z9^ipDR?0GPYO{u=nPK>b4{T0+4!Q+COJ!y7q=e;~`P>O)ul4B7a6 zXxXl`1BuRB7AK2GCRx)~x!ZERI(YmLuCd>xm`Ad(pZ_vT>w7dFkJ?Q4Hb)|6*xQNk zO*9jBRNXug0UF)`$F7OVJE#yQA7Netj8eRq&I zaMFLu`)*SMHiyajVB6Ozx7H+h+Ntm5#B%bW;G9f|>wq>z{}T?E^cMx`QnNB6EEby_ zkrfoO-|G9RzhKERtUlkO=cpI&C~2uhNIR97_sI?4!6IhiPE)J@l!2aR&G(cc=a!8%M7$|> ziKuc#N7c<%k)1iedw``wTM2V%I*{p@Oq;`QXZXv$E5NoQSS@B>tR0D&HT+y6h5cIK zo(YMZzs=WP-<{bKJRf$ZYM^Mx8ydWU3I?tmjvIzzr{h+p5_$9Cyc<)Y@!A=BF9-&) z_L$p$!Zq2KZzgX{vni#1*K2X?9AuIs?S^i{@b)El+((teb&HL!gg5+4D_m78(t~ah zS1uG0RRVGVXA;VFuB~6UtX!x}O@9N=b(H}DCs-%gM1Qq|f+;6ar*@d7RtgTJ~&Jrys%5}&y`c)o*JArZocPFvYq+8FC2FyHfnGLL1@AU|p8f9T|CBY>&u%oY{2J|@%<5vNO+_rO@nKY0Lfca#(bz>Vckeq#n^AQ z!LQM^k^Rfg-@@Rb-51_QX23q3_Im00Xk0*>fXCtZ-WD{=pnX~&n5c#`G&XEkHHcjLXCpk}xdZ2PH~ z*=MF)wZ+qMxE&?*4LFeODa`Eqy=<3;GC4Qw*fg=1jnH2kFVF*#7W~y(+oGTU_~Io* zq}9GwmDU5}6}dW(5u! - - diff --git a/test-app/src/main/res/drawable/ic_baseline_fast_rewind_24.xml b/test-app/src/main/res/drawable/ic_baseline_fast_rewind_24.xml deleted file mode 100644 index 81f79b3226..0000000000 --- a/test-app/src/main/res/drawable/ic_baseline_fast_rewind_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_baseline_skip_next_24.xml b/test-app/src/main/res/drawable/ic_baseline_skip_next_24.xml deleted file mode 100644 index 4fff2475bf..0000000000 --- a/test-app/src/main/res/drawable/ic_baseline_skip_next_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_baseline_skip_previous_24.xml b/test-app/src/main/res/drawable/ic_baseline_skip_previous_24.xml deleted file mode 100644 index 1805b7d158..0000000000 --- a/test-app/src/main/res/drawable/ic_baseline_skip_previous_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_dashboard_black_24dp.xml b/test-app/src/main/res/drawable/ic_dashboard_black_24dp.xml deleted file mode 100644 index cf9903c88c..0000000000 --- a/test-app/src/main/res/drawable/ic_dashboard_black_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/test-app/src/main/res/drawable/ic_info_black_24dp.xml b/test-app/src/main/res/drawable/ic_info_black_24dp.xml deleted file mode 100644 index 31ad0cbddd..0000000000 --- a/test-app/src/main/res/drawable/ic_info_black_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/test-app/src/main/res/drawable/ic_outline_add_24.xml b/test-app/src/main/res/drawable/ic_outline_add_24.xml deleted file mode 100644 index fe04f24c34..0000000000 --- a/test-app/src/main/res/drawable/ic_outline_add_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_outline_format_align_justify_24.xml b/test-app/src/main/res/drawable/ic_outline_format_align_justify_24.xml deleted file mode 100644 index e58793292e..0000000000 --- a/test-app/src/main/res/drawable/ic_outline_format_align_justify_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_outline_format_align_left_24.xml b/test-app/src/main/res/drawable/ic_outline_format_align_left_24.xml deleted file mode 100644 index 4ff0c3acd7..0000000000 --- a/test-app/src/main/res/drawable/ic_outline_format_align_left_24.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_outline_light_mode_24.xml b/test-app/src/main/res/drawable/ic_outline_light_mode_24.xml deleted file mode 100644 index 5014eeaf31..0000000000 --- a/test-app/src/main/res/drawable/ic_outline_light_mode_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_outline_remove_24.xml b/test-app/src/main/res/drawable/ic_outline_remove_24.xml deleted file mode 100644 index 86894f7150..0000000000 --- a/test-app/src/main/res/drawable/ic_outline_remove_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/ic_outline_wb_sunny_24.xml b/test-app/src/main/res/drawable/ic_outline_wb_sunny_24.xml deleted file mode 100644 index 7315059812..0000000000 --- a/test-app/src/main/res/drawable/ic_outline_wb_sunny_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/test-app/src/main/res/drawable/icon_font_decrease.png b/test-app/src/main/res/drawable/icon_font_decrease.png deleted file mode 100644 index 7330622b2367d1446b69dee0652961e6b57dd620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmV;V0$crwP)pzR|j>eahS%%{wqVNL{w5u1dMv$-+%?rKAKQR5;g+!)OYj> zFyYxVK-MvJ3JlX2!WTu|KnfwLLVC>mt^tpMXToPZk(MOPQQyhQzjZr+Wv~7<>m;lX z5{B+2uWeGa4Qh)?5z;4w{m}cqBicrkwW!lYcsjoaws`IPaKGtwb6OuF4A~n^d}f7D zpQa$~kUlQ#TTOg!3;U#!7IiYh)Ac)Xbz=oW@OTZc6oL4ss^x$^9l=KmX9O1L}21;#il#;C>;7n>f!x9taDQ-N`I6E3($cqaT8F+=(^ z;URbz_*r0_m%ww+&M4`VQKp9SE!+<0#aN}wt$PUtz9alAr(Jg8?r(q0C`m}HkRB8E z16(>;lzHGu&K!k^m1zwEUp)I}gfXuJ-C_>IFbu;m48t%CLxn%}=G3(qEC3k*0000< KMNUMnLSTZj+B(Ak diff --git a/test-app/src/main/res/drawable/icon_font_increase.png b/test-app/src/main/res/drawable/icon_font_increase.png deleted file mode 100644 index 5192b45195b80125dd472d350062771e11d2023e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 599 zcmV-d0;v6oP)rui$6o%n%92-arv|tOgKnt`$3$}nI#1f!{Sb~%gN{BzqaYER0ve&b_&b~7l6>?$8 z10h79)oQg`EdY22FbUI1T6mhK&8f7$ArE+v7Ori;Z;%H|(~es~tO36S4#c)YzYWLnBD<=ILu#FCeA&6_oOxJT1a!8>6pvCwx3wnLYm`wUHx2l zOz>D#GVQ@}asSb9|1>Z6Pz|Ix&gaEE9W&1~FaK8!q&d!Ci{J07zipN;wh`t%*RAF| zG4nmJE}irN_J09P6<}(jlCwAl5d;Bpt$;s)}_eXUdzkW-&NZ z-mGnkMVk9?;KG?Ip0#um@5-6-VyzYTHBG9CWo=Uo(%Q_jvX(ffnnnO!u05RNOr{Ij z?rY%2IbOGU3XNO;9{i=6WJ#Q3eUW|w45*PCd-ed>?TelA>Po zIIO{$;-1(i);9T)*5FKW7u>cUN7OVpQ`W3grOBDHVr`QTX=zZgIa66#bN`Hzf-@zl zx}+p6ot&q>YJV2Cy-P(}^WAw}7S=g90|1fbzBe0Ekj}}O1}w6+S&s|poSZ3D*4a1% lSbn%*S!+CwR;$%g?FaX9IuqORrYHaa002ovPDHLkV1j4s9tr>e diff --git a/test-app/src/main/res/drawable/rbtn_selector.xml b/test-app/src/main/res/drawable/rbtn_selector.xml deleted file mode 100644 index 031741d0a4..0000000000 --- a/test-app/src/main/res/drawable/rbtn_selector.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test-app/src/main/res/drawable/rbtn_textcolor_selector.xml b/test-app/src/main/res/drawable/rbtn_textcolor_selector.xml deleted file mode 100644 index 372aa08b22..0000000000 --- a/test-app/src/main/res/drawable/rbtn_textcolor_selector.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/test-app/src/main/res/layout/filter_row.xml b/test-app/src/main/res/layout/filter_row.xml deleted file mode 100644 index b45d79e324..0000000000 --- a/test-app/src/main/res/layout/filter_row.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - diff --git a/test-app/src/main/res/layout/filter_window.xml b/test-app/src/main/res/layout/filter_window.xml deleted file mode 100644 index aecbb8a93d..0000000000 --- a/test-app/src/main/res/layout/filter_window.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - diff --git a/test-app/src/main/res/layout/fragment_publication_detail.xml b/test-app/src/main/res/layout/fragment_publication_detail.xml index 8e3490034c..13151bd883 100644 --- a/test-app/src/main/res/layout/fragment_publication_detail.xml +++ b/test-app/src/main/res/layout/fragment_publication_detail.xml @@ -50,6 +50,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:background="@color/white" android:visibility="gone" /> \ No newline at end of file diff --git a/test-app/src/main/res/layout/fragment_screen_reader.xml b/test-app/src/main/res/layout/fragment_screen_reader.xml deleted file mode 100644 index c035f60136..0000000000 --- a/test-app/src/main/res/layout/fragment_screen_reader.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test-app/src/main/res/layout/fragment_search.xml b/test-app/src/main/res/layout/fragment_search.xml index 206920331c..a7f1c4c466 100644 --- a/test-app/src/main/res/layout/fragment_search.xml +++ b/test-app/src/main/res/layout/fragment_search.xml @@ -11,7 +11,7 @@ android:id="@+id/search_overlay" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/readium_colorAccent"> + > - - - diff --git a/test-app/src/main/res/layout/popup_delete.xml b/test-app/src/main/res/layout/popup_delete.xml deleted file mode 100644 index f58a8fb43e..0000000000 --- a/test-app/src/main/res/layout/popup_delete.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -