react-native-readium 3.0.2 → 4.0.0
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/README.md +2 -1
- package/android/src/main/java/com/reactnativereadium/ReadiumView.kt +10 -7
- package/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt +7 -6
- package/android/src/main/java/com/reactnativereadium/reader/EpubReaderFragment.kt +25 -47
- package/android/src/main/java/com/reactnativereadium/reader/ReaderService.kt +2 -15
- package/android/src/main/java/com/reactnativereadium/utils/FragmentFactory.kt +1 -1
- package/ios/App/AppModule.swift +1 -1
- package/ios/Common/EPUBPreferences.swift +8 -0
- package/ios/Reader/Common/ReaderViewController.swift +8 -14
- package/ios/Reader/EPUB/AssociatedColors.swift +7 -7
- package/ios/Reader/EPUB/EPUBModule.swift +6 -7
- package/ios/Reader/EPUB/EPUBViewController.swift +8 -10
- package/ios/Reader/ReaderFormatModule.swift +3 -4
- package/ios/Reader/ReaderModule.swift +3 -7
- package/ios/Reader/ReaderService.swift +4 -19
- package/ios/ReadiumView.swift +31 -33
- package/ios/ReadiumViewManager.m +1 -1
- package/lib/src/components/ReadiumView.d.ts +4 -2
- package/lib/src/components/ReadiumView.js +4 -4
- package/lib/src/components/ReadiumView.web.d.ts +5 -1
- package/lib/src/components/ReadiumView.web.js +2 -2
- package/lib/src/interfaces/BaseReadiumViewProps.d.ts +1 -2
- package/lib/src/interfaces/Preferences.d.ts +27 -0
- package/lib/src/interfaces/Preferences.js +1 -0
- package/lib/src/interfaces/index.d.ts +1 -1
- package/lib/src/interfaces/index.js +1 -1
- package/lib/src/utils/RANGES.js +1 -1
- package/lib/web/hooks/useSettingsObserver.d.ts +2 -2
- package/lib/web/hooks/useSettingsObserver.js +39 -5
- package/package.json +1 -1
- package/react-native-readium.podspec +2 -0
- package/src/components/ReadiumView.tsx +16 -7
- package/src/components/ReadiumView.web.tsx +7 -3
- package/src/interfaces/BaseReadiumViewProps.ts +1 -3
- package/src/interfaces/Preferences.ts +35 -0
- package/src/interfaces/index.ts +1 -1
- package/src/utils/RANGES.ts +1 -1
- package/web/hooks/useSettingsObserver.ts +52 -7
- package/android/src/main/java/com/reactnativereadium/epub/UserSettings.kt +0 -246
- package/lib/src/interfaces/Settings.d.ts +0 -40
- package/lib/src/interfaces/Settings.js +0 -61
- package/src/interfaces/Settings.ts +0 -75
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ target 'ExampleApp' do
|
|
|
85
85
|
config = use_native_modules!
|
|
86
86
|
...
|
|
87
87
|
pod 'GCDWebServer', podspec: 'https://raw.githubusercontent.com/readium/GCDWebServer/3.7.5/GCDWebServer.podspec', modular_headers: true
|
|
88
|
+
pod 'ReadiumAdapterGCDWebServer', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/2.6.0/Support/CocoaPods/ReadiumAdapterGCDWebServer.podspec', modular_headers: true
|
|
88
89
|
pod 'R2Navigator', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/2.6.0/Support/CocoaPods/ReadiumNavigator.podspec'
|
|
89
90
|
pod 'R2Shared', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/2.6.0/Support/CocoaPods/ReadiumShared.podspec'
|
|
90
91
|
pod 'R2Streamer', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/2.6.0/Support/CocoaPods/ReadiumStreamer.podspec'
|
|
@@ -160,7 +161,7 @@ DRM is not supported at this time. However, there is a clear path to [support it
|
|
|
160
161
|
|------|------|----------|-------------|
|
|
161
162
|
| `file` | [`File`](https://github.com/5-stones/react-native-readium/blob/main/src/interfaces/File.ts) | :x: | A file object containing the path to the eBook file on disk. |
|
|
162
163
|
| `location` | [`Locator`](https://github.com/5-stones/react-native-readium/blob/main/src/interfaces/Locator.ts) \| [`Link`](https://github.com/5-stones/react-native-readium/blob/main/src/interfaces/Link.ts) | :white_check_mark: | A locator prop that allows you to externally control the location of the reader (e.g. Chapters or Bookmarks). <br/><br/>:warning: If you want to set the `location` of an ebook on initial load, you should use the `File.initialLocation` property (look at the `file` prop). See more [here](https://github.com/5-stones/react-native-readium/issues/16#issuecomment-1344128937) |
|
|
163
|
-
| `
|
|
164
|
+
| `preferences` | [`Partial<Preferences>`](https://github.com/readium/swift-toolkit/blob/main/docs/Guides/Navigator%20Preferences.md#appendix-preference-constraints) | :white_check_mark: | An object that allows you to control various aspects of the reader's UI (epub only) |
|
|
164
165
|
| `style` | `ViewStyle` | :white_check_mark: | A traditional style object. |
|
|
165
166
|
| `onLocationChange` | `(locator: Locator) => void` | :white_check_mark: | A callback that fires whenever the location is changed (e.g. the user transitions to a new page)|
|
|
166
167
|
| `onTableOfContents` | `(toc: Link[] \| null) => void` | :white_check_mark: | A callback that fires once the file is parsed and emits the table of contents embedded in the file. Returns `null` or an empty `[]` if no TOC exists. See the [`Link`](https://github.com/5-stones/react-native-readium/blob/main/src/interfaces/Link.ts) interface for more info. |
|
|
@@ -9,9 +9,12 @@ import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
|
9
9
|
import com.reactnativereadium.reader.BaseReaderFragment
|
|
10
10
|
import com.reactnativereadium.reader.EpubReaderFragment
|
|
11
11
|
import com.reactnativereadium.reader.ReaderViewModel
|
|
12
|
+
import com.reactnativereadium.reader.VisualReaderFragment
|
|
12
13
|
import com.reactnativereadium.utils.Dimensions
|
|
13
14
|
import com.reactnativereadium.utils.File
|
|
14
15
|
import com.reactnativereadium.utils.LinkOrLocator
|
|
16
|
+
import org.readium.r2.navigator.epub.EpubNavigatorFragment
|
|
17
|
+
import org.readium.r2.navigator.epub.EpubPreferences
|
|
15
18
|
import org.readium.r2.shared.extensions.toMap
|
|
16
19
|
|
|
17
20
|
class ReadiumView(
|
|
@@ -21,7 +24,7 @@ class ReadiumView(
|
|
|
21
24
|
var file: File? = null
|
|
22
25
|
var fragment: BaseReaderFragment? = null
|
|
23
26
|
var isViewInitialized: Boolean = false
|
|
24
|
-
var
|
|
27
|
+
var lateInitSerializedUserPreferences: String? = null
|
|
25
28
|
|
|
26
29
|
fun updateLocation(location: LinkOrLocator) : Boolean {
|
|
27
30
|
if (fragment == null) {
|
|
@@ -31,25 +34,25 @@ class ReadiumView(
|
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
fun
|
|
35
|
-
if (
|
|
37
|
+
fun updatePreferencesFromJsonString(preferences: String?) {
|
|
38
|
+
if (preferences == null) {
|
|
36
39
|
return
|
|
37
40
|
} else if (fragment == null) {
|
|
38
|
-
|
|
41
|
+
lateInitSerializedUserPreferences = preferences
|
|
39
42
|
return
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
if (fragment is EpubReaderFragment) {
|
|
43
|
-
(fragment as EpubReaderFragment).
|
|
46
|
+
(fragment as EpubReaderFragment).updatePreferencesFromJsonString(preferences)
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
lateInitSerializedUserPreferences = null
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
fun addFragment(frag: BaseReaderFragment) {
|
|
50
53
|
fragment = frag
|
|
51
54
|
setupLayout()
|
|
52
|
-
|
|
55
|
+
updatePreferencesFromJsonString(lateInitSerializedUserPreferences)
|
|
53
56
|
val activity: FragmentActivity? = reactContext.currentActivity as FragmentActivity?
|
|
54
57
|
activity!!.supportFragmentManager
|
|
55
58
|
.beginTransaction()
|
|
@@ -84,11 +84,14 @@ class ReadiumViewManager(
|
|
|
84
84
|
fun locationToLinkOrLocator(location: ReadableMap): LinkOrLocator? {
|
|
85
85
|
val json = JSONObject(location.toHashMap() as HashMap<*, *>)
|
|
86
86
|
val hasLocations = json.has("locations")
|
|
87
|
+
val hasType = json.has("type") && !json.getString("type").isEmpty()
|
|
87
88
|
val hasChildren = json.has("children")
|
|
88
89
|
val hasHashHref = (json.get("href") as String).contains("#")
|
|
90
|
+
val hasTemplated = json.has("templated")
|
|
91
|
+
|
|
89
92
|
var linkOrLocator: LinkOrLocator? = null
|
|
90
93
|
|
|
91
|
-
if ((hasChildren || hasHashHref) && !hasLocations) {
|
|
94
|
+
if ((!hasType || hasChildren || hasHashHref || hasTemplated) && !hasLocations) {
|
|
92
95
|
val link = Link.fromJSON(json)
|
|
93
96
|
if (link != null) {
|
|
94
97
|
linkOrLocator = LinkOrLocator.Link(link)
|
|
@@ -112,11 +115,9 @@ class ReadiumViewManager(
|
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
@ReactProp(name = "
|
|
116
|
-
fun
|
|
117
|
-
|
|
118
|
-
settings.toHashMap().forEach { (key, value) -> if (value != null) map[key] = value }
|
|
119
|
-
view.updateSettingsFromMap(map)
|
|
118
|
+
@ReactProp(name = "preferences")
|
|
119
|
+
fun setPreferences(view: ReadiumView, serialisedPreferences: String) {
|
|
120
|
+
view.updatePreferencesFromJsonString(serialisedPreferences)
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
@ReactPropGroup(names = ["width", "height"], customType = "Style")
|
|
@@ -14,9 +14,7 @@ import android.view.accessibility.AccessibilityManager
|
|
|
14
14
|
import androidx.appcompat.app.AppCompatActivity
|
|
15
15
|
import androidx.appcompat.widget.SearchView
|
|
16
16
|
import androidx.fragment.app.commitNow
|
|
17
|
-
import androidx.lifecycle.lifecycleScope
|
|
18
17
|
import androidx.lifecycle.ViewModelProvider
|
|
19
|
-
import com.reactnativereadium.epub.UserSettings
|
|
20
18
|
import com.reactnativereadium.R
|
|
21
19
|
import com.reactnativereadium.utils.toggleSystemUi
|
|
22
20
|
import java.net.URL
|
|
@@ -24,11 +22,11 @@ import kotlinx.coroutines.delay
|
|
|
24
22
|
import org.readium.r2.navigator.epub.EpubNavigatorFragment
|
|
25
23
|
import org.readium.r2.navigator.ExperimentalDecorator
|
|
26
24
|
import org.readium.r2.navigator.Navigator
|
|
27
|
-
import org.readium.r2.
|
|
25
|
+
import org.readium.r2.navigator.epub.EpubPreferences
|
|
26
|
+
import org.readium.r2.navigator.epub.EpubPreferencesSerializer
|
|
28
27
|
import org.readium.r2.shared.publication.Locator
|
|
29
28
|
import org.readium.r2.shared.publication.Publication
|
|
30
29
|
import org.readium.r2.shared.ReadiumCSSName
|
|
31
|
-
import org.readium.r2.shared.SCROLL_REF
|
|
32
30
|
|
|
33
31
|
@OptIn(ExperimentalDecorator::class)
|
|
34
32
|
class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listener {
|
|
@@ -38,13 +36,13 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
|
|
|
38
36
|
private lateinit var publication: Publication
|
|
39
37
|
lateinit var navigatorFragment: EpubNavigatorFragment
|
|
40
38
|
private lateinit var factory: ReaderViewModel.Factory
|
|
41
|
-
private var
|
|
39
|
+
private var initialPreferencesJsonString: String? = null
|
|
42
40
|
|
|
43
41
|
private lateinit var menuScreenReader: MenuItem
|
|
44
42
|
private lateinit var menuSearch: MenuItem
|
|
45
43
|
lateinit var menuSearchView: SearchView
|
|
46
44
|
|
|
47
|
-
private lateinit var
|
|
45
|
+
private lateinit var userPreferences: EpubPreferences
|
|
48
46
|
private var isScreenReaderVisible = false
|
|
49
47
|
private var isSearchViewIconified = true
|
|
50
48
|
|
|
@@ -61,12 +59,16 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
|
|
|
61
59
|
)
|
|
62
60
|
}
|
|
63
61
|
|
|
64
|
-
fun
|
|
65
|
-
if (this::
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
fun updatePreferencesFromJsonString(serialisedPreferences: String) {
|
|
63
|
+
if (this::userPreferences.isInitialized) {
|
|
64
|
+
val serializer = EpubPreferencesSerializer()
|
|
65
|
+
this.userPreferences = serializer.deserialize(serialisedPreferences)
|
|
66
|
+
if (navigator is EpubNavigatorFragment) {
|
|
67
|
+
(navigator as EpubNavigatorFragment).submitPreferences(this.userPreferences)
|
|
68
|
+
}
|
|
69
|
+
initialPreferencesJsonString = null
|
|
68
70
|
} else {
|
|
69
|
-
|
|
71
|
+
initialPreferencesJsonString = serialisedPreferences
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
@@ -86,12 +88,10 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
|
|
|
86
88
|
publication = it.publication
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
val baseUrl = checkNotNull(requireArguments().getString(BASE_URL_ARG))
|
|
90
91
|
|
|
91
92
|
childFragmentManager.fragmentFactory =
|
|
92
93
|
EpubNavigatorFragment.createFactory(
|
|
93
94
|
publication = publication,
|
|
94
|
-
baseUrl = baseUrl,
|
|
95
95
|
initialLocator = model.initialLocation,
|
|
96
96
|
listener = this,
|
|
97
97
|
config = EpubNavigatorFragment.Configuration().apply {
|
|
@@ -124,28 +124,16 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
|
|
|
124
124
|
|
|
125
125
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
126
126
|
super.onViewCreated(view, savedInstanceState)
|
|
127
|
-
|
|
128
|
-
val activity = requireActivity()
|
|
129
|
-
userSettings = UserSettings(
|
|
130
|
-
navigatorFragment.preferences,
|
|
131
|
-
activity,
|
|
132
|
-
publication.userSettingsUIPreset
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
// This is a hack to draw the right background color on top and bottom blank spaces
|
|
136
|
-
navigatorFragment.lifecycleScope.launchWhenStarted {
|
|
137
|
-
val appearancePref = navigatorFragment.preferences.getInt(APPEARANCE_REF, 0)
|
|
138
|
-
val backgroundsColors = mutableListOf("#ffffff", "#faf4e8", "#000000")
|
|
139
|
-
navigatorFragment.resourcePager.setBackgroundColor(Color.parseColor(backgroundsColors[appearancePref]))
|
|
140
|
-
}
|
|
141
127
|
}
|
|
142
128
|
|
|
143
129
|
override fun onResume() {
|
|
144
130
|
super.onResume()
|
|
145
131
|
val activity = requireActivity()
|
|
146
132
|
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
if (!this::userPreferences.isInitialized) {
|
|
134
|
+
userPreferences = EpubPreferences()
|
|
135
|
+
}
|
|
136
|
+
initialPreferencesJsonString?.let { updatePreferencesFromJsonString(it)}
|
|
149
137
|
|
|
150
138
|
// If TalkBack or any touch exploration service is activated we force scroll mode (and
|
|
151
139
|
// override user preferences)
|
|
@@ -153,18 +141,14 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
|
|
|
153
141
|
isExploreByTouchEnabled = am.isTouchExplorationEnabled
|
|
154
142
|
|
|
155
143
|
if (isExploreByTouchEnabled) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
userSettings.saveChanges()
|
|
160
|
-
|
|
161
|
-
lifecycleScope.launchWhenResumed {
|
|
162
|
-
delay(500)
|
|
163
|
-
userSettings.updateViewCSS(SCROLL_REF)
|
|
164
|
-
}
|
|
144
|
+
this.userPreferences = this.userPreferences.plus(
|
|
145
|
+
EpubPreferences(scroll = true)
|
|
146
|
+
)
|
|
165
147
|
} else {
|
|
166
148
|
if (publication.cssStyle != "cjk-vertical") {
|
|
167
|
-
|
|
149
|
+
this.userPreferences = this.userPreferences.plus(
|
|
150
|
+
EpubPreferences(scroll = null)
|
|
151
|
+
)
|
|
168
152
|
}
|
|
169
153
|
}
|
|
170
154
|
}
|
|
@@ -181,20 +165,14 @@ class EpubReaderFragment : VisualReaderFragment(), EpubNavigatorFragment.Listene
|
|
|
181
165
|
|
|
182
166
|
companion object {
|
|
183
167
|
|
|
184
|
-
private const val BASE_URL_ARG = "baseUrl"
|
|
185
|
-
|
|
186
168
|
private const val SEARCH_FRAGMENT_TAG = "search"
|
|
187
169
|
|
|
188
170
|
private const val IS_SCREEN_READER_VISIBLE_KEY = "isScreenReaderVisible"
|
|
189
171
|
|
|
190
172
|
private const val IS_SEARCH_VIEW_ICONIFIED = "isSearchViewIconified"
|
|
191
173
|
|
|
192
|
-
fun newInstance(
|
|
193
|
-
return EpubReaderFragment()
|
|
194
|
-
arguments = Bundle().apply {
|
|
195
|
-
putString(BASE_URL_ARG, baseUrl.toString())
|
|
196
|
-
}
|
|
197
|
-
}
|
|
174
|
+
fun newInstance(): EpubReaderFragment {
|
|
175
|
+
return EpubReaderFragment()
|
|
198
176
|
}
|
|
199
177
|
}
|
|
200
178
|
}
|
|
@@ -8,10 +8,8 @@ import com.reactnativereadium.utils.LinkOrLocator
|
|
|
8
8
|
import java.io.File
|
|
9
9
|
import java.io.IOException
|
|
10
10
|
import java.net.ServerSocket
|
|
11
|
-
import java.net.URL
|
|
12
11
|
import org.readium.r2.shared.extensions.mediaType
|
|
13
12
|
import org.readium.r2.shared.extensions.tryOrNull
|
|
14
|
-
import org.readium.r2.shared.Injectable
|
|
15
13
|
import org.readium.r2.shared.publication.Locator
|
|
16
14
|
import org.readium.r2.shared.publication.asset.FileAsset
|
|
17
15
|
import org.readium.r2.shared.publication.Publication
|
|
@@ -80,13 +78,11 @@ class ReaderService(
|
|
|
80
78
|
sender = reactContext
|
|
81
79
|
)
|
|
82
80
|
.onSuccess {
|
|
83
|
-
val url = prepareToServe(it)
|
|
84
|
-
if (url != null) {
|
|
85
81
|
val locator = locatorFromLinkOrLocator(initialLocation, it)
|
|
86
|
-
val readerFragment = EpubReaderFragment.newInstance(
|
|
82
|
+
val readerFragment = EpubReaderFragment.newInstance()
|
|
87
83
|
readerFragment.initFactory(it, locator)
|
|
88
84
|
callback.invoke(readerFragment)
|
|
89
|
-
|
|
85
|
+
|
|
90
86
|
}
|
|
91
87
|
.onFailure {
|
|
92
88
|
tryOrNull { asset.file.delete() }
|
|
@@ -95,15 +91,6 @@ class ReaderService(
|
|
|
95
91
|
}
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
private fun prepareToServe(publication: Publication): URL? {
|
|
99
|
-
val userProperties =
|
|
100
|
-
reactContext.filesDir.path + "/" + Injectable.Style.rawValue + "/UserProperties.json"
|
|
101
|
-
return server.addPublication(
|
|
102
|
-
publication,
|
|
103
|
-
userPropertiesFile = File(userProperties)
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
94
|
private fun startServer() {
|
|
108
95
|
if (!server.isAlive) {
|
|
109
96
|
try {
|
|
@@ -25,7 +25,7 @@ inline fun <reified T : Fragment> createFragmentFactory(crossinline factory: ()
|
|
|
25
25
|
*
|
|
26
26
|
* ```
|
|
27
27
|
* supportFragmentManager.fragmentFactory = CompositeFragmentFactory(
|
|
28
|
-
* EpubNavigatorFragment.createFactory(publication,
|
|
28
|
+
* EpubNavigatorFragment.createFactory(publication, initialLocator, this),
|
|
29
29
|
* PdfNavigatorFragment.createFactory(publication, initialLocator, this)
|
|
30
30
|
* )
|
|
31
31
|
* ```
|
package/ios/App/AppModule.swift
CHANGED
|
@@ -27,7 +27,7 @@ final class AppModule {
|
|
|
27
27
|
fatalError("Can't start publication server")
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
reader = ReaderModule(delegate: self
|
|
30
|
+
reader = ReaderModule(delegate: self)
|
|
31
31
|
|
|
32
32
|
// Set Readium 2's logging minimum level.
|
|
33
33
|
R2EnableLog(withMinimumSeverityLevel: .debug)
|
|
@@ -290,20 +290,14 @@ extension ReaderViewController: NavigatorDelegate {
|
|
|
290
290
|
|
|
291
291
|
extension ReaderViewController: VisualNavigatorDelegate {
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if thresholdRange ~= point.x {
|
|
299
|
-
moved = navigator.goLeft(animated: false)
|
|
300
|
-
} else if thresholdRange ~= (viewport.maxX - point.x) {
|
|
301
|
-
moved = navigator.goRight(animated: false)
|
|
293
|
+
func navigator(_ navigator: VisualNavigator, didTapAt point: CGPoint) {
|
|
294
|
+
let moved = DirectionalNavigationAdapter(navigator: navigator).didTap(at: point)
|
|
295
|
+
if !moved {
|
|
296
|
+
toggleNavigationBar()
|
|
297
|
+
}
|
|
302
298
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
299
|
+
|
|
300
|
+
func navigator(_ navigator: VisualNavigator, didPressKey event: KeyEvent) {
|
|
301
|
+
DirectionalNavigationAdapter(navigator: navigator).didPressKey(event: event)
|
|
306
302
|
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
303
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import UIKit
|
|
2
|
-
import
|
|
2
|
+
import R2Navigator
|
|
3
3
|
|
|
4
4
|
class AssociatedColors {
|
|
5
5
|
|
|
6
|
-
/// Get associated colors for a specific
|
|
7
|
-
/// - parameter
|
|
6
|
+
/// Get associated colors for a specific theme setting
|
|
7
|
+
/// - parameter theme: The selected theme
|
|
8
8
|
/// - Returns: A tuple with a main color and a text color
|
|
9
|
-
static func getColors(for
|
|
9
|
+
static func getColors(for theme: Theme) -> (mainColor: UIColor, textColor: UIColor) {
|
|
10
10
|
var mainColor, textColor: UIColor
|
|
11
11
|
|
|
12
|
-
switch
|
|
13
|
-
case
|
|
12
|
+
switch theme {
|
|
13
|
+
case .sepia:
|
|
14
14
|
mainColor = UIColor.init(red: 250/255, green: 244/255, blue: 232/255, alpha: 1)
|
|
15
15
|
textColor = UIColor.init(red: 18/255, green: 18/255, blue: 18/255, alpha: 1)
|
|
16
|
-
case
|
|
16
|
+
case .dark:
|
|
17
17
|
mainColor = UIColor.black
|
|
18
18
|
textColor = UIColor.init(red: 254/255, green: 254/255, blue: 254/255, alpha: 1)
|
|
19
19
|
default:
|
|
@@ -11,25 +11,24 @@ final class EPUBModule: ReaderFormatModule {
|
|
|
11
11
|
self.delegate = delegate
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
func supports(_ publication: Publication) -> Bool {
|
|
15
|
+
publication.conforms(to: .epub)
|
|
16
|
+
|| publication.readingOrder.allAreHTML
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
func makeReaderViewController(
|
|
19
20
|
for publication: Publication,
|
|
20
21
|
locator: Locator?,
|
|
21
|
-
bookId: String
|
|
22
|
-
resourcesServer: ResourcesServer
|
|
22
|
+
bookId: String
|
|
23
23
|
) throws -> ReaderViewController {
|
|
24
24
|
guard publication.metadata.identifier != nil else {
|
|
25
25
|
throw ReaderError.epubNotValid
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
let epubViewController = EPUBViewController(
|
|
28
|
+
let epubViewController = try EPUBViewController(
|
|
29
29
|
publication: publication,
|
|
30
30
|
locator: locator,
|
|
31
|
-
bookId: bookId
|
|
32
|
-
resourcesServer: resourcesServer
|
|
31
|
+
bookId: bookId
|
|
33
32
|
)
|
|
34
33
|
epubViewController.moduleDelegate = delegate
|
|
35
34
|
return epubViewController
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
import R2Shared
|
|
3
3
|
import R2Navigator
|
|
4
|
+
import ReadiumAdapterGCDWebServer
|
|
4
5
|
|
|
5
6
|
class EPUBViewController: ReaderViewController {
|
|
6
7
|
|
|
7
8
|
init(
|
|
8
9
|
publication: Publication,
|
|
9
10
|
locator: Locator?,
|
|
10
|
-
bookId: String
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
let navigator = EPUBNavigatorViewController(
|
|
11
|
+
bookId: String
|
|
12
|
+
) throws {
|
|
13
|
+
let navigator = try EPUBNavigatorViewController(
|
|
14
14
|
publication: publication,
|
|
15
15
|
initialLocation: locator,
|
|
16
|
-
|
|
16
|
+
httpServer: GCDHTTPServer.shared
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
super.init(
|
|
@@ -33,13 +33,11 @@ class EPUBViewController: ReaderViewController {
|
|
|
33
33
|
super.viewDidLoad()
|
|
34
34
|
|
|
35
35
|
/// Set initial UI appearance.
|
|
36
|
-
|
|
37
|
-
setUIColor(for: appearance)
|
|
38
|
-
}
|
|
36
|
+
setUIColor(for: epubNavigator.settings.theme)
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
internal func setUIColor(for
|
|
42
|
-
let colors = AssociatedColors.getColors(for:
|
|
39
|
+
internal func setUIColor(for theme: Theme) {
|
|
40
|
+
let colors = AssociatedColors.getColors(for: theme)
|
|
43
41
|
|
|
44
42
|
navigator.view.backgroundColor = colors.mainColor
|
|
45
43
|
view.backgroundColor = colors.mainColor
|
|
@@ -8,15 +8,14 @@ protocol ReaderFormatModule {
|
|
|
8
8
|
|
|
9
9
|
var delegate: ReaderFormatModuleDelegate? { get }
|
|
10
10
|
|
|
11
|
-
///
|
|
12
|
-
|
|
11
|
+
/// Returns whether the given publication is supported by this module.
|
|
12
|
+
func supports(_ publication: Publication) -> Bool
|
|
13
13
|
|
|
14
14
|
/// Creates the view controller to present the publication.
|
|
15
15
|
func makeReaderViewController(
|
|
16
16
|
for publication: Publication,
|
|
17
17
|
locator: Locator?,
|
|
18
|
-
bookId: String
|
|
19
|
-
resourcesServer: ResourcesServer
|
|
18
|
+
bookId: String
|
|
20
19
|
) throws -> ReaderViewController
|
|
21
20
|
|
|
22
21
|
}
|
|
@@ -20,17 +20,14 @@ protocol ReaderModuleDelegate: ModuleDelegate {}
|
|
|
20
20
|
|
|
21
21
|
final class ReaderModule: ReaderModuleAPI {
|
|
22
22
|
weak var delegate: ReaderModuleDelegate?
|
|
23
|
-
private let resourcesServer: ResourcesServer
|
|
24
23
|
|
|
25
24
|
/// Sub-modules to handle different publication formats (eg. EPUB, CBZ)
|
|
26
25
|
var formatModules: [ReaderFormatModule] = []
|
|
27
26
|
|
|
28
27
|
init(
|
|
29
|
-
delegate: ReaderModuleDelegate
|
|
30
|
-
resourcesServer: ResourcesServer
|
|
28
|
+
delegate: ReaderModuleDelegate?
|
|
31
29
|
) {
|
|
32
30
|
self.delegate = delegate
|
|
33
|
-
self.resourcesServer = resourcesServer
|
|
34
31
|
|
|
35
32
|
formatModules = [
|
|
36
33
|
// CBZModule(delegate: self),
|
|
@@ -49,7 +46,7 @@ final class ReaderModule: ReaderModuleAPI {
|
|
|
49
46
|
locator: Locator?
|
|
50
47
|
) -> ReaderViewController? {
|
|
51
48
|
guard let module = self.formatModules.first(
|
|
52
|
-
where:{ $0.
|
|
49
|
+
where:{ $0.supports(publication) }
|
|
53
50
|
) else {
|
|
54
51
|
print("Unable to display the publication due to an unsupported format.")
|
|
55
52
|
return nil
|
|
@@ -59,8 +56,7 @@ final class ReaderModule: ReaderModuleAPI {
|
|
|
59
56
|
return try module.makeReaderViewController(
|
|
60
57
|
for: publication,
|
|
61
58
|
locator: locator,
|
|
62
|
-
bookId: bookId
|
|
63
|
-
resourcesServer: resourcesServer
|
|
59
|
+
bookId: bookId
|
|
64
60
|
)
|
|
65
61
|
} catch {
|
|
66
62
|
print("An unexpected error occurred when attempting to build the reader view.")
|
|
@@ -7,13 +7,11 @@ import UIKit
|
|
|
7
7
|
final class ReaderService: Loggable {
|
|
8
8
|
var app: AppModule?
|
|
9
9
|
var streamer = Streamer()
|
|
10
|
-
var publicationServer: PublicationServer?
|
|
11
10
|
private var subscriptions = Set<AnyCancellable>()
|
|
12
11
|
|
|
13
12
|
init() {
|
|
14
13
|
do {
|
|
15
14
|
self.app = try AppModule()
|
|
16
|
-
self.publicationServer = PublicationServer()
|
|
17
15
|
} catch {
|
|
18
16
|
print("TODO: An error occurred instantiating the ReaderService")
|
|
19
17
|
print(error)
|
|
@@ -29,11 +27,13 @@ final class ReaderService: Loggable {
|
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
let hasLocations = location?["locations"] != nil
|
|
30
|
+
let hasType = (location?["type"] as? String)?.isEmpty == false
|
|
32
31
|
let hasChildren = location?["children"] != nil
|
|
33
|
-
let hasHashHref = (location
|
|
32
|
+
let hasHashHref = (location?["href"] as? String)?.contains("#") == true
|
|
33
|
+
let hasTemplated = location?["templated"] != nil
|
|
34
34
|
|
|
35
35
|
// check that we're not dealing with a Link
|
|
36
|
-
if ((hasChildren || hasHashHref) && !hasLocations) {
|
|
36
|
+
if ((!hasType || hasChildren || hasHashHref || hasTemplated) && !hasLocations) {
|
|
37
37
|
guard let publication = publication else {
|
|
38
38
|
return nil
|
|
39
39
|
}
|
|
@@ -65,7 +65,6 @@ final class ReaderService: Loggable {
|
|
|
65
65
|
print(">>>>>>>>>>> TODO: handle me", error)
|
|
66
66
|
},
|
|
67
67
|
receiveValue: { pub in
|
|
68
|
-
self.preparePresentation(of: pub)
|
|
69
68
|
let locator: Locator? = ReaderService.locatorFromLocation(location, pub)
|
|
70
69
|
let vc = reader.getViewController(
|
|
71
70
|
for: pub,
|
|
@@ -139,18 +138,4 @@ final class ReaderService: Loggable {
|
|
|
139
138
|
}
|
|
140
139
|
return .just(publication)
|
|
141
140
|
}
|
|
142
|
-
|
|
143
|
-
private func preparePresentation(of publication: Publication) {
|
|
144
|
-
if (self.publicationServer == nil) {
|
|
145
|
-
log(.error, "Whoops")
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
publicationServer?.removeAll()
|
|
150
|
-
do {
|
|
151
|
-
try publicationServer?.add(publication)
|
|
152
|
-
} catch {
|
|
153
|
-
log(.error, error)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
141
|
}
|