react-native-readium 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/android/build.gradle +198 -0
- package/android/gradle.properties +3 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/reactnativereadium/ReadiumPackage.kt +17 -0
- package/android/src/main/java/com/reactnativereadium/ReadiumView.kt +84 -0
- package/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt +80 -0
- package/android/src/main/java/com/reactnativereadium/epub/UserSettings.kt +236 -0
- package/android/src/main/java/com/reactnativereadium/reader/BaseReaderFragment.kt +81 -0
- package/android/src/main/java/com/reactnativereadium/reader/EpubReaderFragment.kt +375 -0
- package/android/src/main/java/com/reactnativereadium/reader/ImageReaderFragment.kt +68 -0
- package/android/src/main/java/com/reactnativereadium/reader/PdfReaderFragment.kt +82 -0
- package/android/src/main/java/com/reactnativereadium/reader/ReaderService.kt +116 -0
- package/android/src/main/java/com/reactnativereadium/reader/ReaderViewModel.kt +120 -0
- package/android/src/main/java/com/reactnativereadium/reader/VisualReaderFragment.kt +78 -0
- package/android/src/main/java/com/reactnativereadium/search/SearchFragment.kt +100 -0
- package/android/src/main/java/com/reactnativereadium/search/SearchPagingSource.kt +44 -0
- package/android/src/main/java/com/reactnativereadium/search/SearchResultAdapter.kt +68 -0
- package/android/src/main/java/com/reactnativereadium/utils/ContentResolverUtil.kt +156 -0
- package/android/src/main/java/com/reactnativereadium/utils/Dimensions.kt +6 -0
- package/android/src/main/java/com/reactnativereadium/utils/EventChannel.kt +61 -0
- package/android/src/main/java/com/reactnativereadium/utils/FragmentFactory.kt +46 -0
- package/android/src/main/java/com/reactnativereadium/utils/R2DispatcherActivity.kt +45 -0
- package/android/src/main/java/com/reactnativereadium/utils/SectionDecoration.kt +98 -0
- package/android/src/main/java/com/reactnativereadium/utils/SingleClickListener.kt +32 -0
- package/android/src/main/java/com/reactnativereadium/utils/SystemUiManagement.kt +63 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/Bitmap.kt +23 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/Context.kt +16 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/File.kt +22 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/InputStream.kt +23 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/Link.kt +6 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/Metadata.kt +6 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/URL.kt +29 -0
- package/android/src/main/java/com/reactnativereadium/utils/extensions/Uri.kt +17 -0
- package/android/src/main/res/drawable/background_action_mode.xml +6 -0
- package/android/src/main/res/drawable/cnl.png +0 -0
- package/android/src/main/res/drawable/cover.png +0 -0
- package/android/src/main/res/drawable/ic_add_white_24dp.xml +9 -0
- package/android/src/main/res/drawable/ic_baseline_arrow_forward_24.xml +5 -0
- package/android/src/main/res/drawable/ic_baseline_bookmark_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_delete_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_edit_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_enhanced_encryption_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_fast_forward_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_fast_rewind_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_headphones_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_pause_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_play_arrow_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_search_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_skip_next_24.xml +10 -0
- package/android/src/main/res/drawable/ic_baseline_skip_previous_24.xml +10 -0
- package/android/src/main/res/drawable/ic_dashboard_black_24dp.xml +9 -0
- package/android/src/main/res/drawable/ic_fastforward_30.xml +7 -0
- package/android/src/main/res/drawable/ic_info_black_24dp.xml +9 -0
- package/android/src/main/res/drawable/ic_local_library_black_24dp.xml +9 -0
- package/android/src/main/res/drawable/ic_notch.xml +4 -0
- package/android/src/main/res/drawable/ic_outline_add_24.xml +10 -0
- package/android/src/main/res/drawable/ic_outline_format_align_justify_24.xml +10 -0
- package/android/src/main/res/drawable/ic_outline_format_align_left_24.xml +11 -0
- package/android/src/main/res/drawable/ic_outline_format_size_24.xml +10 -0
- package/android/src/main/res/drawable/ic_outline_light_mode_24.xml +10 -0
- package/android/src/main/res/drawable/ic_outline_menu_24.xml +10 -0
- package/android/src/main/res/drawable/ic_outline_remove_24.xml +10 -0
- package/android/src/main/res/drawable/ic_outline_wb_sunny_24.xml +10 -0
- package/android/src/main/res/drawable/ic_rewind_30.xml +7 -0
- package/android/src/main/res/drawable/icon_font_decrease.png +0 -0
- package/android/src/main/res/drawable/icon_font_increase.png +0 -0
- package/android/src/main/res/drawable/icon_overflow.png +0 -0
- package/android/src/main/res/drawable/rbtn_selector.xml +25 -0
- package/android/src/main/res/drawable/rbtn_textcolor_selector.xml +16 -0
- package/android/src/main/res/drawable/repfr.png +0 -0
- package/android/src/main/res/drawable/selector_blue.xml +42 -0
- package/android/src/main/res/drawable/selector_green.xml +42 -0
- package/android/src/main/res/drawable/selector_purple.xml +42 -0
- package/android/src/main/res/drawable/selector_red.xml +42 -0
- package/android/src/main/res/drawable/selector_yellow.xml +41 -0
- package/android/src/main/res/layout/activity_epub.xml +23 -0
- package/android/src/main/res/layout/activity_main.xml +32 -0
- package/android/src/main/res/layout/activity_reader.xml +6 -0
- package/android/src/main/res/layout/add_catalog_dialog.xml +25 -0
- package/android/src/main/res/layout/filter_row.xml +34 -0
- package/android/src/main/res/layout/filter_window.xml +24 -0
- package/android/src/main/res/layout/fragment_about.xml +150 -0
- package/android/src/main/res/layout/fragment_audiobook.xml +151 -0
- package/android/src/main/res/layout/fragment_bookshelf.xml +35 -0
- package/android/src/main/res/layout/fragment_catalog.xml +56 -0
- package/android/src/main/res/layout/fragment_catalog_feed_list.xml +27 -0
- package/android/src/main/res/layout/fragment_drm_management.xml +284 -0
- package/android/src/main/res/layout/fragment_listview.xml +24 -0
- package/android/src/main/res/layout/fragment_outline.xml +31 -0
- package/android/src/main/res/layout/fragment_publication_detail.xml +55 -0
- package/android/src/main/res/layout/fragment_reader.xml +6 -0
- package/android/src/main/res/layout/fragment_screen_reader.xml +143 -0
- package/android/src/main/res/layout/fragment_search.xml +39 -0
- package/android/src/main/res/layout/item_group_view.xml +22 -0
- package/android/src/main/res/layout/item_recycle_book.xml +55 -0
- package/android/src/main/res/layout/item_recycle_bookmark.xml +72 -0
- package/android/src/main/res/layout/item_recycle_button.xml +23 -0
- package/android/src/main/res/layout/item_recycle_catalog.xml +56 -0
- package/android/src/main/res/layout/item_recycle_highlight.xml +85 -0
- package/android/src/main/res/layout/item_recycle_horizontal.xml +45 -0
- package/android/src/main/res/layout/item_recycle_navigation.xml +34 -0
- package/android/src/main/res/layout/item_recycle_search.xml +14 -0
- package/android/src/main/res/layout/item_spinner_days.xml +19 -0
- package/android/src/main/res/layout/my_fragment.xml +13 -0
- package/android/src/main/res/layout/popup_delete.xml +29 -0
- package/android/src/main/res/layout/popup_note.xml +105 -0
- package/android/src/main/res/layout/popup_passphrase.xml +126 -0
- package/android/src/main/res/layout/popup_window_user_settings.xml +576 -0
- package/android/src/main/res/layout/section_header.xml +25 -0
- package/android/src/main/res/layout/view_action_mode.xml +100 -0
- package/android/src/main/res/layout/view_action_mode_reverse.xml +99 -0
- package/android/src/main/res/menu/bottom_nav_menu.xml +19 -0
- package/android/src/main/res/menu/menu_action_mode.xml +26 -0
- package/android/src/main/res/menu/menu_bookmark.xml +18 -0
- package/android/src/main/res/menu/menu_epub.xml +41 -0
- package/android/src/main/res/menu/menu_filter.xml +21 -0
- package/android/src/main/res/menu/menu_reader.xml +33 -0
- package/android/src/main/res/navigation/navigation.xml +46 -0
- package/android/src/main/res/values/arrays.xml +18 -0
- package/android/src/main/res/values/colors.xml +22 -0
- package/android/src/main/res/values/refs.xml +5 -0
- package/android/src/main/res/values/strings.xml +200 -0
- package/android/src/main/res/values/styles.xml +46 -0
- package/android/src/main/res/xml/network_security_config.xml +38 -0
- package/ios/App/AppModule.swift +62 -0
- package/ios/Common/Paths.swift +52 -0
- package/ios/Common/Publication.swift +15 -0
- package/ios/Common/Toolkit/Extensions/AnyPublisher.swift +14 -0
- package/ios/Common/Toolkit/Extensions/Future.swift +16 -0
- package/ios/Common/Toolkit/Extensions/HTTPClient.swift +65 -0
- package/ios/Common/Toolkit/Extensions/Locator.swift +14 -0
- package/ios/Common/Toolkit/Extensions/String.swift +16 -0
- package/ios/Common/Toolkit/Extensions/UIImage.swift +12 -0
- package/ios/Common/Toolkit/Extensions/UIViewController.swift +19 -0
- package/ios/Common/Toolkit/ScreenOrientation.swift +13 -0
- package/ios/Data/Bookmark.swift +23 -0
- package/ios/Reader/Common/ReaderViewController.swift +309 -0
- package/ios/Reader/EPUB/AssociatedColors.swift +27 -0
- package/ios/Reader/EPUB/EPUBModule.swift +38 -0
- package/ios/Reader/EPUB/EPUBViewController.swift +79 -0
- package/ios/Reader/ReaderError.swift +25 -0
- package/ios/Reader/ReaderFormatModule.swift +27 -0
- package/ios/Reader/ReaderModule.swift +84 -0
- package/ios/Reader/ReaderService.swift +126 -0
- package/ios/Readium-Bridging-Header.h +2 -0
- package/ios/Readium.xcodeproj/project.pbxproj +293 -0
- package/ios/ReadiumView.swift +156 -0
- package/ios/ReadiumViewManager.m +10 -0
- package/ios/ReadiumViewManager.swift +9 -0
- package/lib/commonjs/enums/Appearance.js +16 -0
- package/lib/commonjs/enums/Appearance.js.map +1 -0
- package/lib/commonjs/enums/ColumnCount.js +16 -0
- package/lib/commonjs/enums/ColumnCount.js.map +1 -0
- package/lib/commonjs/enums/FontFamily.js +21 -0
- package/lib/commonjs/enums/FontFamily.js.map +1 -0
- package/lib/commonjs/enums/TextAlignment.js +15 -0
- package/lib/commonjs/enums/TextAlignment.js.map +1 -0
- package/lib/commonjs/enums/index.js +58 -0
- package/lib/commonjs/enums/index.js.map +1 -0
- package/lib/commonjs/index.js +105 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/interfaces/Dimensions.js +2 -0
- package/lib/commonjs/interfaces/Dimensions.js.map +1 -0
- package/lib/commonjs/interfaces/File.js +6 -0
- package/lib/commonjs/interfaces/File.js.map +1 -0
- package/lib/commonjs/interfaces/Locator.js +2 -0
- package/lib/commonjs/interfaces/Locator.js.map +1 -0
- package/lib/commonjs/interfaces/Settings.js +71 -0
- package/lib/commonjs/interfaces/Settings.js.map +1 -0
- package/lib/commonjs/interfaces/index.js +58 -0
- package/lib/commonjs/interfaces/index.js.map +1 -0
- package/lib/commonjs/utils/index.js +30 -0
- package/lib/commonjs/utils/index.js.map +1 -0
- package/lib/module/enums/Appearance.js +9 -0
- package/lib/module/enums/Appearance.js.map +1 -0
- package/lib/module/enums/ColumnCount.js +9 -0
- package/lib/module/enums/ColumnCount.js.map +1 -0
- package/lib/module/enums/FontFamily.js +14 -0
- package/lib/module/enums/FontFamily.js.map +1 -0
- package/lib/module/enums/TextAlignment.js +8 -0
- package/lib/module/enums/TextAlignment.js.map +1 -0
- package/lib/module/enums/index.js +5 -0
- package/lib/module/enums/index.js.map +1 -0
- package/lib/module/index.js +61 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/interfaces/Dimensions.js +2 -0
- package/lib/module/interfaces/Dimensions.js.map +1 -0
- package/lib/module/interfaces/File.js +2 -0
- package/lib/module/interfaces/File.js.map +1 -0
- package/lib/module/interfaces/Locator.js +2 -0
- package/lib/module/interfaces/Locator.js.map +1 -0
- package/lib/module/interfaces/Settings.js +61 -0
- package/lib/module/interfaces/Settings.js.map +1 -0
- package/lib/module/interfaces/index.js +5 -0
- package/lib/module/interfaces/index.js.map +1 -0
- package/lib/module/utils/index.js +17 -0
- package/lib/module/utils/index.js.map +1 -0
- package/lib/typescript/enums/Appearance.d.ts +11 -0
- package/lib/typescript/enums/ColumnCount.d.ts +5 -0
- package/lib/typescript/enums/FontFamily.d.ts +10 -0
- package/lib/typescript/enums/TextAlignment.d.ts +4 -0
- package/lib/typescript/enums/index.d.ts +4 -0
- package/lib/typescript/index.d.ts +17 -0
- package/lib/typescript/interfaces/Dimensions.d.ts +4 -0
- package/lib/typescript/interfaces/File.d.ts +11 -0
- package/lib/typescript/interfaces/Locator.d.ts +14 -0
- package/lib/typescript/interfaces/Settings.d.ts +40 -0
- package/lib/typescript/interfaces/index.d.ts +4 -0
- package/lib/typescript/utils/index.d.ts +10 -0
- package/package.json +160 -0
- package/react-native-readium.podspec +25 -0
- package/src/enums/Appearance.ts +14 -0
- package/src/enums/ColumnCount.ts +6 -0
- package/src/enums/FontFamily.ts +11 -0
- package/src/enums/TextAlignment.ts +5 -0
- package/src/enums/index.ts +4 -0
- package/src/index.tsx +78 -0
- package/src/interfaces/Dimensions.ts +4 -0
- package/src/interfaces/File.ts +14 -0
- package/src/interfaces/Locator.ts +14 -0
- package/src/interfaces/Settings.ts +85 -0
- package/src/interfaces/index.ts +4 -0
- package/src/utils/index.ts +18 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
~ Module: r2-testapp-kotlin
|
|
3
|
+
~ Developers: Aferdita Muriqi, Clément Baumann
|
|
4
|
+
~
|
|
5
|
+
~ Copyright (c) 2018. European Digital Reading Lab. All rights reserved.
|
|
6
|
+
~ Licensed to the Readium Foundation under one or more contributor license agreements.
|
|
7
|
+
~ Use of this source code is governed by a BSD-style license which is detailed in the
|
|
8
|
+
~ LICENSE file present in the project repository where this source code is maintained.
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
<resources>
|
|
12
|
+
<string name="app_name" translatable="false">R2 Reader</string>
|
|
13
|
+
<string name="menu_item_show_epub_list">Show List</string>
|
|
14
|
+
<string name="menu_item_add_epub">Add ePub</string>
|
|
15
|
+
<string name="menu_item_filter">Filter</string>
|
|
16
|
+
<string name="progress_wait_while_searching_book">Please wait.</string>
|
|
17
|
+
<string name="progress_wait">Please wait.</string>
|
|
18
|
+
<string name="progress_wait_while_downloading_book">Please wait while your publication is being downloaded.</string>
|
|
19
|
+
<string name="progress_wait_while_preparing_book">Please wait while your publication is being prepared.</string>
|
|
20
|
+
<string name="progress_wait_while_preparing_audiobook">Please wait while your audiobook is being prepared.</string>
|
|
21
|
+
<string name="progress_wait_while_loading_feed">Please wait while your feed is loading.</string>
|
|
22
|
+
<string name="error_invalid_epub">Invalid Epub</string>
|
|
23
|
+
<string name="fallback_no_description">No description</string>
|
|
24
|
+
<string name="button_dismiss">DISMISS</string>
|
|
25
|
+
|
|
26
|
+
<string name="epubactivity_drm_info">DRM Info</string>
|
|
27
|
+
<string name="epubactivity_set_bookmark">Add a bookmark</string>
|
|
28
|
+
<string name="epubactivity_settings">User Settings</string>
|
|
29
|
+
<string name="epubactivity_book_nav_options">Book navigation menu</string>
|
|
30
|
+
<string name="epubactivity_read_aloud_start">Read Aloud</string>
|
|
31
|
+
<string name="epubactivity_read_aloud_stop">Stop Read Aloud</string>
|
|
32
|
+
<string name="epubactivity_search">Search</string>
|
|
33
|
+
|
|
34
|
+
<string name="epubactivity_accessibility">Accessibility</string>
|
|
35
|
+
<string name="epubactivity_accessibility_screen_reader_start">Start Screen Reader</string>
|
|
36
|
+
<string name="epubactivity_accessibility_screen_reader_pause">Pause Screen Reader</string>
|
|
37
|
+
<string name="epubactivity_accessibility_screen_reader_resume">Resume Screen Reader</string>
|
|
38
|
+
<string name="epubactivity_accessibility_screen_reader_stop">Stop Screen Reader</string>
|
|
39
|
+
|
|
40
|
+
<string name="title_activity_opdscatalog">OPDS Catalog</string>
|
|
41
|
+
<string name="action_settings">Settings</string>
|
|
42
|
+
<string name="title_activity_r2_about">About R2 Reader</string>
|
|
43
|
+
<string name="title_activity_opds_list">OPDS Feeds</string>
|
|
44
|
+
<string name="title_activity_opds_detail">Detail</string>
|
|
45
|
+
<string name="title_fragment_drm_management">DRM Management</string>
|
|
46
|
+
<string name="title_activity_epub">Detail</string>
|
|
47
|
+
<string name="floating_button_add_book">Add a Book</string>
|
|
48
|
+
<string name="floating_button_add_feed">Add a OPDS Feed</string>
|
|
49
|
+
<string name="about_r2_reader">About R2 Reader</string>
|
|
50
|
+
<string name="more_options">More Options</string>
|
|
51
|
+
<string name="opds_feeds">OPDS Feeds</string>
|
|
52
|
+
<string name="popup_delete_button">DELETE</string>
|
|
53
|
+
<string name="add_publication_to_library">Add a publication to your library</string>
|
|
54
|
+
<string name="select_from_your_device">select from your device</string>
|
|
55
|
+
<string name="download_from_url">download from a url</string>
|
|
56
|
+
|
|
57
|
+
<string name="app_version_header">Version</string>
|
|
58
|
+
<string name="app_version_label">App Version:</string>
|
|
59
|
+
<string name="app_version">2.2.0</string>
|
|
60
|
+
<string name="github_tab_label">GitHub Tag:</string>
|
|
61
|
+
<string name="github_tag">2.2.0</string>
|
|
62
|
+
|
|
63
|
+
<string name="copyright_label">Copyright</string>
|
|
64
|
+
<string name="copyright">\@ 2019 European Digital Reading Lab</string>
|
|
65
|
+
<string name="bsd_license_label">[BSD-3 license]</string>
|
|
66
|
+
<string name="bsd_license_label_accessible">[B S D 3 license]</string>
|
|
67
|
+
<string name="acknowledgements_label">Acknowledgements</string>
|
|
68
|
+
<string name="acknowledgements_french_state">R2 Reader wouldn\'t have been developed without the financial help of the French state.</string>
|
|
69
|
+
<string name="catalog_list_more">More</string>
|
|
70
|
+
<string name="catalog_detail_download_button">Download</string>
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
<string name="menu_label_drm">DRM</string>
|
|
74
|
+
<string name="menu_label_settings">Settings</string>
|
|
75
|
+
<string name="menu_label_toc">TOC</string>
|
|
76
|
+
<string name="usersettings_label_font">Font</string>
|
|
77
|
+
<string name="usersettings_appearance_default">Default</string>
|
|
78
|
+
<string name="usersettings_appearance_sepia">Sepia</string>
|
|
79
|
+
<string name="usersettings_appearance_night">Night</string>
|
|
80
|
+
<string name="usersettings_label_scroll_mode">Scroll mode</string>
|
|
81
|
+
<string name="usersettings_publisher_default">"Publisher's Default"</string>
|
|
82
|
+
<string name="usersettings_publisher_default_accessibility">"Publisher's Default Settings"</string>
|
|
83
|
+
<string name="usersettings_label_columns">Columns</string>
|
|
84
|
+
<string name="usersettings_auto">Auto</string>
|
|
85
|
+
<string name="usersettings_column_one">1</string>
|
|
86
|
+
<string name="usersettings_column_two">2</string>
|
|
87
|
+
<string name="usersettings_label_page_margins">Page Margins</string>
|
|
88
|
+
<string name="usersettings_page_margin_default">0.75</string>
|
|
89
|
+
<string name="usersettings_label_word_spacing">Word Spacing</string>
|
|
90
|
+
<string name="usersettings_label_letter_spacing">Letter Spacing</string>
|
|
91
|
+
<string name="usersettings_label_line_height">Line Height</string>
|
|
92
|
+
<string name="usersettings_label_TTS_speech_speed">TTS speed</string>
|
|
93
|
+
|
|
94
|
+
<!-- Accessibility -->
|
|
95
|
+
|
|
96
|
+
<string name="usersettings_description_TTS_speech_speed">Set TTS speech speed</string>
|
|
97
|
+
<string name="usersettings_description_brightness">Set Brightness</string>
|
|
98
|
+
<string name="usersettings_description_font_increase">Increase Font Size</string>
|
|
99
|
+
<string name="usersettings_description_font_decrease">Decrease Font Size</string>
|
|
100
|
+
<string name="usersettings_description_pm_increase">Increase Page Margins Size</string>
|
|
101
|
+
<string name="usersettings_description_pm_decrease">Decrease Page Margins Size</string>
|
|
102
|
+
<string name="usersettings_description_ws_increase">Increase Word Spacing</string>
|
|
103
|
+
<string name="usersettings_description_ws_decrease">Decrease Word Spacing</string>
|
|
104
|
+
<string name="usersettings_description_ls_increase">Increase Letter Spacing</string>
|
|
105
|
+
<string name="usersettings_description_ls_decrease">Decrease Letter Spacing</string>
|
|
106
|
+
<string name="usersettings_description_lh_increase">Increase Line Height</string>
|
|
107
|
+
<string name="usersettings_description_lh_decrease">Decrease Line Height</string>
|
|
108
|
+
|
|
109
|
+
<string name="drm_information_header">INFORMATION</string>
|
|
110
|
+
<string name="drm_label_license_type">License Type</string>
|
|
111
|
+
<string name="drm_label_state">State</string>
|
|
112
|
+
<string name="drm_label_provider">Provider</string>
|
|
113
|
+
<string name="drm_label_issued">Issued</string>
|
|
114
|
+
<string name="drm_label_updated">Updated</string>
|
|
115
|
+
<string name="drm_label_rights">RIGHTS</string>
|
|
116
|
+
<string name="drm_label_prints_left">Prints left</string>
|
|
117
|
+
<string name="drm_label_copies_left">Copies left</string>
|
|
118
|
+
<string name="drm_label_start">Start</string>
|
|
119
|
+
<string name="drm_label_end">End</string>
|
|
120
|
+
<string name="drm_label_potential_right_end">Potential right end</string>
|
|
121
|
+
<string name="drm_label_actions">ACTIONS</string>
|
|
122
|
+
<string name="drm_label_renew">RENEW</string>
|
|
123
|
+
<string name="drm_label_return">RETURN</string>
|
|
124
|
+
<string name="zero">00:00</string>
|
|
125
|
+
<string name="chapter">Chapter</string>
|
|
126
|
+
<string name="chapter_page">Chapter / Page</string>
|
|
127
|
+
<string name="progression">Progression</string>
|
|
128
|
+
<string name="timestamp">Timestamp</string>
|
|
129
|
+
|
|
130
|
+
<!-- Outlines -->
|
|
131
|
+
<string name="contents_tab_label">Contents</string>
|
|
132
|
+
<string name="bookmarks_tab_label">Bookmarks</string>
|
|
133
|
+
<string name="highlights_tab_label">Highlights</string>
|
|
134
|
+
<string name="pagelist_tab_label">Page List</string>
|
|
135
|
+
<string name="landmarks_tab_label">Landmarks</string>
|
|
136
|
+
<string name="action_mode_menu_highlight">Highlight</string>
|
|
137
|
+
<string name="action_mode_menu_underline">Underline</string>
|
|
138
|
+
<string name="action_mode_menu_note">Note</string>
|
|
139
|
+
<string name="bookmark_added">Bookmark added</string>
|
|
140
|
+
<string name="bookmark_exists">Bookmark already exists</string>
|
|
141
|
+
|
|
142
|
+
<string name="title_catalogs">Catalogs</string>
|
|
143
|
+
<string name="title_bookshelf">Bookshelf</string>
|
|
144
|
+
<string name="title_about">About</string>
|
|
145
|
+
<string name="cover_image">Cover Image</string>
|
|
146
|
+
<string name="repfr">repfr</string>
|
|
147
|
+
|
|
148
|
+
<string name="delete">Delete</string>
|
|
149
|
+
<string name="cancel">Cancel</string>
|
|
150
|
+
<string name="confirm_delete_book_title">Delete Book?</string>
|
|
151
|
+
<string name="confirm_delete_book_text">Are you sure you want to delete this book?</string>
|
|
152
|
+
<string name="confirm_delete_catalog_title">Delete Catalog?</string>
|
|
153
|
+
<string name="confirm_delete_catalog_text">Are you sure you want to delete this Catalog feed?</string>
|
|
154
|
+
|
|
155
|
+
<string name="add_book">Add a Book</string>
|
|
156
|
+
<string name="add_catalog">Add an Catalog Feed</string>
|
|
157
|
+
<string name="ok">OK</string>
|
|
158
|
+
<string name="save">Save</string>
|
|
159
|
+
<string name="enter_title">Enter the Title</string>
|
|
160
|
+
<string name="enter_url">Enter the URL</string>
|
|
161
|
+
<string name="invalid_title">Please enter a title</string>
|
|
162
|
+
<string name="invalid_url">Please enter a valid URL</string>
|
|
163
|
+
<string name="catalog_parse_error">Error parsing Catalog feed. Please check the URL and try again</string>
|
|
164
|
+
|
|
165
|
+
<string name="publication_image_description">Cover image for %1$s</string>
|
|
166
|
+
|
|
167
|
+
<string name="return_publication">This will return the publication</string>
|
|
168
|
+
<string name="return_button">Return</string>
|
|
169
|
+
|
|
170
|
+
<string name="end_of_chapter">End of chapter</string>
|
|
171
|
+
|
|
172
|
+
<string name="unable_to_move_pub">Unable to move publication into the library</string>
|
|
173
|
+
<string name="import_publication_success">Publication added to your library</string>
|
|
174
|
+
<string name="unable_add_pub_database">Unable to add publication to the database</string>
|
|
175
|
+
<string name="failed_parsing_catalog">Failed parsing Catalog</string>
|
|
176
|
+
<string name="next_chapter">Next chapter</string>
|
|
177
|
+
<string name="next_sentence">Next sentence</string>
|
|
178
|
+
<string name="play_and_pause">Play and pause</string>
|
|
179
|
+
<string name="previous_sentence">Previous sentence</string>
|
|
180
|
+
<string name="previous_chapter">Previous chapter</string>
|
|
181
|
+
<string name="brightness_lower">Brightness lower</string>
|
|
182
|
+
<string name="brightness_higher">Brightness higher</string>
|
|
183
|
+
<string name="tts_slower">TTS slower</string>
|
|
184
|
+
<string name="tts_faster">TTS faster</string>
|
|
185
|
+
<string name="no_result">No result</string>
|
|
186
|
+
<string name="note">Note</string>
|
|
187
|
+
<string name="add_a_note">Add a note</string>
|
|
188
|
+
<string name="add_an_annotation">Add an annotation</string>
|
|
189
|
+
<string name="delete_highlight_or_annotation">Delete highlight or annotation</string>
|
|
190
|
+
<string name="yellow">Yellow</string>
|
|
191
|
+
<string name="green">Green</string>
|
|
192
|
+
<string name="blue">Blue</string>
|
|
193
|
+
<string name="red">Red</string>
|
|
194
|
+
<string name="purple">Purple</string>
|
|
195
|
+
<string name="seek_bar">Seek bar</string>
|
|
196
|
+
<string name="go_backward_30_seconds">Go backward 30 seconds</string>
|
|
197
|
+
<string name="play_or_pause">Play or pause</string>
|
|
198
|
+
<string name="go_forward_30_seconds">Go forward 30 seconds</string>
|
|
199
|
+
<string name="select_a_font">Select a font</string>
|
|
200
|
+
</resources>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
~ Module: r2-testapp-kotlin
|
|
3
|
+
~ Developers: Aferdita Muriqi, Clément Baumann
|
|
4
|
+
~
|
|
5
|
+
~ Copyright (c) 2018. European Digital Reading Lab. All rights reserved.
|
|
6
|
+
~ Licensed to the Readium Foundation under one or more contributor license agreements.
|
|
7
|
+
~ Use of this source code is governed by a BSD-style license which is detailed in the
|
|
8
|
+
~ LICENSE file present in the project repository where this source code is maintained.
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
<resources>
|
|
12
|
+
|
|
13
|
+
<!-- Base application theme. -->
|
|
14
|
+
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
|
|
15
|
+
<!-- Customize your theme here. -->
|
|
16
|
+
<item name="colorPrimary">@color/colorPrimary</item>
|
|
17
|
+
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
|
18
|
+
<item name="colorAccent">@color/colorAccentPrefs</item>
|
|
19
|
+
<item name="android:popupAnimationStyle">@null</item>
|
|
20
|
+
<item name="colorSurface">@color/white</item>
|
|
21
|
+
<item name="floatingActionButtonStyle">@style/Widget.App.FloatingActionButton</item>
|
|
22
|
+
</style>
|
|
23
|
+
|
|
24
|
+
<style name="AppTheme.NoActionBar">
|
|
25
|
+
<item name="windowActionBar">false</item>
|
|
26
|
+
<item name="windowNoTitle">true</item>
|
|
27
|
+
<item name="android:popupAnimationStyle">@null</item>
|
|
28
|
+
|
|
29
|
+
</style>
|
|
30
|
+
|
|
31
|
+
<style name="TabWidgetTheme" parent="AppTheme">
|
|
32
|
+
<item name="android:textSize">10sp</item>
|
|
33
|
+
<item name="android:textAlignment">center</item>
|
|
34
|
+
</style>
|
|
35
|
+
|
|
36
|
+
<style name="Widget.App.FloatingActionButton" parent="Widget.MaterialComponents.FloatingActionButton">
|
|
37
|
+
<item name="materialThemeOverlay">@style/ThemeOverlay.App.FloatingActionButton</item>
|
|
38
|
+
</style>
|
|
39
|
+
|
|
40
|
+
<style name="ThemeOverlay.App.FloatingActionButton" parent="">
|
|
41
|
+
<item name="colorSecondary">@color/colorPrimary</item>
|
|
42
|
+
<item name="colorOnSecondary">@color/white</item>
|
|
43
|
+
<item name="colorOnSurface">@color/colorPrimary</item>
|
|
44
|
+
</style>
|
|
45
|
+
|
|
46
|
+
</resources>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<network-security-config>
|
|
3
|
+
<domain-config cleartextTrafficPermitted="true">
|
|
4
|
+
|
|
5
|
+
<!--
|
|
6
|
+
Required with r2-navigator-kotlin
|
|
7
|
+
Used to serve a publication's resources from the local HTTP server
|
|
8
|
+
-->
|
|
9
|
+
<domain includeSubdomains="false">127.0.0.1</domain>
|
|
10
|
+
<domain includeSubdomains="false">localhost</domain>
|
|
11
|
+
|
|
12
|
+
<!--
|
|
13
|
+
Required with r2-lcp-kotlin
|
|
14
|
+
The CRL is served from an HTTP server, so we need to explicitly allow clear-text traffic on
|
|
15
|
+
this domain
|
|
16
|
+
See https://github.com/readium/r2-lcp-kotlin/issues/59
|
|
17
|
+
-->
|
|
18
|
+
<domain includeSubdomains="false">crl.edrlab.telesec.de</domain>
|
|
19
|
+
|
|
20
|
+
<!-- Publications from Feedbooks' catalog are downloaded through HTTP -->
|
|
21
|
+
<domain includeSubdomains="true">feedbooks.com</domain>
|
|
22
|
+
<domain includeSubdomains="true">feedbooks.net</domain>
|
|
23
|
+
|
|
24
|
+
<!--
|
|
25
|
+
Required for the Open Textbooks Catalog OPDS feed to load properly
|
|
26
|
+
open.minitex.org is for the publications
|
|
27
|
+
s3.amazonaws.com is for the cover images
|
|
28
|
+
-->
|
|
29
|
+
<domain includeSubdomains="false">open.minitex.org</domain>
|
|
30
|
+
<domain includeSubdomains="false">s3.amazonaws.com</domain>
|
|
31
|
+
|
|
32
|
+
<!--
|
|
33
|
+
Required to stream the Flatland audiobook sample.
|
|
34
|
+
-->
|
|
35
|
+
<domain includeSubdomains="true">archive.org</domain>
|
|
36
|
+
|
|
37
|
+
</domain-config>
|
|
38
|
+
</network-security-config>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Combine
|
|
2
|
+
import Foundation
|
|
3
|
+
import UIKit
|
|
4
|
+
import R2Shared
|
|
5
|
+
import R2Streamer
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/// Base module delegate, that sub-modules' delegate can extend.
|
|
9
|
+
/// Provides basic shared functionalities.
|
|
10
|
+
protocol ModuleDelegate: AnyObject {
|
|
11
|
+
func presentAlert(_ title: String, message: String, from viewController: UIViewController)
|
|
12
|
+
func presentError(_ error: Error?, from viewController: UIViewController)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/// Main application module, it:
|
|
17
|
+
/// - owns the sub-modules (reader, etc.)
|
|
18
|
+
/// - orchestrates the communication between its sub-modules, through the modules' delegates.
|
|
19
|
+
final class AppModule {
|
|
20
|
+
|
|
21
|
+
// App modules
|
|
22
|
+
var reader: ReaderModuleAPI! = nil
|
|
23
|
+
// var opds: OPDSModuleAPI! = nil
|
|
24
|
+
|
|
25
|
+
init() throws {
|
|
26
|
+
guard let server = PublicationServer() else {
|
|
27
|
+
/// FIXME: we should recover properly if the publication server can't start, maybe this should only forbid opening a publication?
|
|
28
|
+
fatalError("Can't start publication server")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
reader = ReaderModule(delegate: self, resourcesServer: server)
|
|
32
|
+
// opds = OPDSModule(delegate: self)
|
|
33
|
+
|
|
34
|
+
// Set Readium 2's logging minimum level.
|
|
35
|
+
R2EnableLog(withMinimumSeverityLevel: .debug)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
extension AppModule: ModuleDelegate {
|
|
41
|
+
|
|
42
|
+
func presentAlert(_ title: String, message: String, from viewController: UIViewController) {
|
|
43
|
+
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
|
44
|
+
let dismissButton = UIAlertAction(title: NSLocalizedString("ok_button", comment: "Alert button"), style: .cancel)
|
|
45
|
+
alert.addAction(dismissButton)
|
|
46
|
+
viewController.present(alert, animated: true)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func presentError(_ error: Error?, from viewController: UIViewController) {
|
|
50
|
+
guard let error = error else { return }
|
|
51
|
+
if case ReaderError.cancelled = error { return }
|
|
52
|
+
presentAlert(
|
|
53
|
+
NSLocalizedString("error_title", comment: "Alert title for errors"),
|
|
54
|
+
message: error.localizedDescription,
|
|
55
|
+
from: viewController
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
extension AppModule: ReaderModuleDelegate {}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import Combine
|
|
2
|
+
import Foundation
|
|
3
|
+
import R2Shared
|
|
4
|
+
|
|
5
|
+
final class Paths {
|
|
6
|
+
private init() {}
|
|
7
|
+
|
|
8
|
+
static let home: URL =
|
|
9
|
+
URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
|
|
10
|
+
|
|
11
|
+
static let temporary: URL =
|
|
12
|
+
URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
13
|
+
|
|
14
|
+
static let documents: URL =
|
|
15
|
+
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
|
16
|
+
|
|
17
|
+
static let samples = Bundle.main.resourceURL!.appendingPathComponent("Samples")
|
|
18
|
+
|
|
19
|
+
static let library: URL =
|
|
20
|
+
FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
|
|
21
|
+
|
|
22
|
+
static let covers: URL = {
|
|
23
|
+
let url = library.appendingPathComponent("Covers")
|
|
24
|
+
try! FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
|
|
25
|
+
return url
|
|
26
|
+
}()
|
|
27
|
+
|
|
28
|
+
static func makeDocumentURL(for source: URL? = nil, title: String?, mediaType: MediaType) -> AnyPublisher<URL, Never> {
|
|
29
|
+
Future(on: .global()) { promise in
|
|
30
|
+
// Is the file already in Documents/?
|
|
31
|
+
if let source = source, source.standardizedFileURL.deletingLastPathComponent() == documents.standardizedFileURL {
|
|
32
|
+
promise(.success(source))
|
|
33
|
+
} else {
|
|
34
|
+
let title = title.takeIf { !$0.isEmpty } ?? UUID().uuidString
|
|
35
|
+
let ext = mediaType.fileExtension?.addingPrefix(".") ?? ""
|
|
36
|
+
let filename = "\(title)\(ext)".sanitizedPathComponent
|
|
37
|
+
promise(.success(documents.appendingUniquePathComponent(filename)))
|
|
38
|
+
}
|
|
39
|
+
}.eraseToAnyPublisher()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static func makeTemporaryURL() -> AnyPublisher<URL, Never> {
|
|
43
|
+
Future(on: .global()) { promise in
|
|
44
|
+
promise(.success(temporary.appendingUniquePathComponent()))
|
|
45
|
+
}.eraseToAnyPublisher()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// Returns whether the given `url` locates a file that is under the app's home directory.
|
|
49
|
+
static func isAppFile(at url: URL) -> Bool {
|
|
50
|
+
home.isParentOf(url)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import CoreServices
|
|
2
|
+
import Foundation
|
|
3
|
+
import R2Shared
|
|
4
|
+
|
|
5
|
+
extension Publication {
|
|
6
|
+
|
|
7
|
+
/// Finds all the downloadable links for this publication.
|
|
8
|
+
var downloadLinks: [Link] {
|
|
9
|
+
links.filter {
|
|
10
|
+
return DocumentTypes.main.supportsMediaType($0.type)
|
|
11
|
+
|| DocumentTypes.main.supportsFileExtension($0.url(relativeTo: nil)?.pathExtension)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Combine
|
|
2
|
+
|
|
3
|
+
extension AnyPublisher {
|
|
4
|
+
|
|
5
|
+
public static func just(_ value: Output) -> Self {
|
|
6
|
+
Just(value)
|
|
7
|
+
.setFailureType(to: Failure.self)
|
|
8
|
+
.eraseToAnyPublisher()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public static func fail(_ error: Failure) -> Self {
|
|
12
|
+
Fail(error: error).eraseToAnyPublisher()
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Combine
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
extension Future {
|
|
5
|
+
/// Creates a `Future` which runs asynchronously on the given `queue`.
|
|
6
|
+
public convenience init(
|
|
7
|
+
on queue: DispatchQueue,
|
|
8
|
+
_ attemptToFulfill: @escaping (@escaping Future<Output, Failure>.Promise) -> Void
|
|
9
|
+
) {
|
|
10
|
+
self.init { promise in
|
|
11
|
+
queue.async {
|
|
12
|
+
attemptToFulfill(promise)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import Combine
|
|
2
|
+
import Foundation
|
|
3
|
+
import R2Shared
|
|
4
|
+
|
|
5
|
+
struct HTTPDownload {
|
|
6
|
+
let file: URL
|
|
7
|
+
let response: HTTPResponse
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
extension HTTPClient {
|
|
11
|
+
|
|
12
|
+
func fetch(_ request: HTTPRequestConvertible) -> AnyPublisher<HTTPResponse, HTTPError> {
|
|
13
|
+
var cancellable: R2Shared.Cancellable? = nil
|
|
14
|
+
return Future { promise in
|
|
15
|
+
cancellable = self.fetch(request, completion: promise)
|
|
16
|
+
}
|
|
17
|
+
.handleEvents(receiveCancel: { cancellable?.cancel() })
|
|
18
|
+
.eraseToAnyPublisher()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func download(_ request: HTTPRequestConvertible, progress: @escaping (Double) -> Void) -> AnyPublisher<HTTPDownload, HTTPError> {
|
|
22
|
+
openTemporaryFileForWriting()
|
|
23
|
+
.flatMap { (destination, handle) -> AnyPublisher<HTTPDownload, HTTPError> in
|
|
24
|
+
var cancellable: R2Shared.Cancellable? = nil
|
|
25
|
+
|
|
26
|
+
return Future { promise in
|
|
27
|
+
cancellable = self.stream(request,
|
|
28
|
+
consume: { data, progression in
|
|
29
|
+
if let progression = progression {
|
|
30
|
+
progress(progression)
|
|
31
|
+
}
|
|
32
|
+
handle.write(data)
|
|
33
|
+
},
|
|
34
|
+
completion: { result in
|
|
35
|
+
do {
|
|
36
|
+
try handle.close()
|
|
37
|
+
promise(.success(HTTPDownload(file: destination, response: try result.get())))
|
|
38
|
+
} catch {
|
|
39
|
+
try? FileManager.default.removeItem(at: destination)
|
|
40
|
+
promise(.failure(HTTPError(error: error)))
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
.handleEvents(receiveCancel: {
|
|
45
|
+
cancellable?.cancel()
|
|
46
|
+
try? handle.close()
|
|
47
|
+
try? FileManager.default.removeItem(at: destination)
|
|
48
|
+
})
|
|
49
|
+
.eraseToAnyPublisher()
|
|
50
|
+
}
|
|
51
|
+
.eraseToAnyPublisher()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private func openTemporaryFileForWriting() -> AnyPublisher<(URL, FileHandle), HTTPError> {
|
|
55
|
+
Paths.makeTemporaryURL()
|
|
56
|
+
.tryMap { destination in
|
|
57
|
+
// Makes sure the file exists.
|
|
58
|
+
try "".write(to: destination, atomically: true, encoding: .utf8)
|
|
59
|
+
let handle = try FileHandle(forWritingTo: destination)
|
|
60
|
+
return (destination, handle)
|
|
61
|
+
}
|
|
62
|
+
.mapError { HTTPError(kind: .other, cause: $0) }
|
|
63
|
+
.eraseToAnyPublisher()
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import R2Shared
|
|
3
|
+
|
|
4
|
+
extension Locator: Codable {
|
|
5
|
+
public init(from decoder: Decoder) throws {
|
|
6
|
+
let json = try decoder.singleValueContainer().decode(String.self)
|
|
7
|
+
try self.init(jsonString: json)!
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public func encode(to encoder: Encoder) throws {
|
|
11
|
+
var container = encoder.singleValueContainer()
|
|
12
|
+
try container.encode(jsonString)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
extension String {
|
|
4
|
+
|
|
5
|
+
/// Returns this string after removing any character forbidden in a single path component.
|
|
6
|
+
var sanitizedPathComponent: String {
|
|
7
|
+
// See https://superuser.com/a/358861
|
|
8
|
+
let invalidCharacters = CharacterSet(charactersIn: "\\/:*?\"<>|")
|
|
9
|
+
.union(.newlines)
|
|
10
|
+
.union(.illegalCharacters)
|
|
11
|
+
.union(.controlCharacters)
|
|
12
|
+
|
|
13
|
+
return components(separatedBy: invalidCharacters)
|
|
14
|
+
.joined(separator: " ")
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
/// SO 33545910/1585121 - Heberti Almeida (inspired).
|
|
4
|
+
extension UIImage {
|
|
5
|
+
class func imageWithTextView(textView: UITextView) -> UIImage {
|
|
6
|
+
UIGraphicsBeginImageContextWithOptions(textView.bounds.size, false, 0.0)
|
|
7
|
+
textView.layer.render(in: UIGraphicsGetCurrentContext()!)
|
|
8
|
+
let image = UIGraphicsGetImageFromCurrentImageContext()
|
|
9
|
+
UIGraphicsEndImageContext()
|
|
10
|
+
return image!
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
extension UIViewController {
|
|
5
|
+
|
|
6
|
+
/// Finds the first child view controller with the given type, recursively.
|
|
7
|
+
func findChildViewController<T: UIViewController>() -> T? {
|
|
8
|
+
for childViewController in children {
|
|
9
|
+
if let found = childViewController as? T {
|
|
10
|
+
return found
|
|
11
|
+
}
|
|
12
|
+
if let found: T = childViewController.findChildViewController() {
|
|
13
|
+
return found
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return nil
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
enum ScreenOrientation: String {
|
|
5
|
+
case landscape
|
|
6
|
+
case portrait
|
|
7
|
+
|
|
8
|
+
static var current: ScreenOrientation {
|
|
9
|
+
let orientation = UIDevice.current.orientation
|
|
10
|
+
return orientation.isLandscape ? .landscape : .portrait
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Combine
|
|
2
|
+
import Foundation
|
|
3
|
+
import R2Shared
|
|
4
|
+
|
|
5
|
+
struct Bookmark {
|
|
6
|
+
let id: String?
|
|
7
|
+
/// Foreign key to the publication.
|
|
8
|
+
var bookId: String
|
|
9
|
+
/// Location in the publication.
|
|
10
|
+
var locator: Locator
|
|
11
|
+
/// Progression in the publication, extracted from the locator.
|
|
12
|
+
var progression: Double?
|
|
13
|
+
/// Date of creation.
|
|
14
|
+
var created: Date = Date()
|
|
15
|
+
|
|
16
|
+
init(id: String? = nil, bookId: String, locator: Locator, created: Date = Date()) {
|
|
17
|
+
self.id = id
|
|
18
|
+
self.bookId = bookId
|
|
19
|
+
self.locator = locator
|
|
20
|
+
self.progression = locator.locations.totalProgression
|
|
21
|
+
self.created = created
|
|
22
|
+
}
|
|
23
|
+
}
|