diff --git a/android/src/main/java/com/reactnativereadium/ReadiumView.kt b/android/src/main/java/com/reactnativereadium/ReadiumView.kt
index c62bc1e..a200ea9 100644
--- a/android/src/main/java/com/reactnativereadium/ReadiumView.kt
+++ b/android/src/main/java/com/reactnativereadium/ReadiumView.kt
@@ -78,6 +78,15 @@ class ReadiumView(
payload
)
}
+ is ReaderViewModel.Event.MetadataLoaded -> {
+ val json = event.metadata.toJSON()
+ val payload = Arguments.makeNativeMap(json.toMap())
+ module.receiveEvent(
+ this.id.toInt(),
+ ReadiumViewManager.ON_METADATA,
+ payload
+ )
+ }
else -> {
// do nothing
}
diff --git a/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt b/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt
index e5d8710..e4ed0e8 100644
--- a/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt
+++ b/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt
@@ -41,6 +41,13 @@ class ReadiumViewManager(
MapBuilder.of("bubbled", ON_TABLE_OF_CONTENTS)
)
)
+ .put(
+ ON_METADATA,
+ MapBuilder.of(
+ "phasedRegistrationNames",
+ MapBuilder.of("bubbled", ON_METADATA)
+ )
+ )
.build()
}
@@ -141,6 +148,7 @@ class ReadiumViewManager(
companion object {
var ON_LOCATION_CHANGE = "onLocationChange"
var ON_TABLE_OF_CONTENTS = "onTableOfContents"
+ var ON_METADATA = "onMetadata"
var COMMAND_CREATE = 1
}
}
diff --git a/android/src/main/java/com/reactnativereadium/reader/BaseReaderFragment.kt b/android/src/main/java/com/reactnativereadium/reader/BaseReaderFragment.kt
index ac995ab..b31b90a 100644
--- a/android/src/main/java/com/reactnativereadium/reader/BaseReaderFragment.kt
+++ b/android/src/main/java/com/reactnativereadium/reader/BaseReaderFragment.kt
@@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.readium.r2.navigator.*
import org.readium.r2.shared.publication.Locator
+import org.readium.r2.shared.publication.Metadata
import com.reactnativereadium.utils.EventChannel
import kotlinx.coroutines.channels.Channel
@@ -38,6 +39,7 @@ abstract class BaseReaderFragment : Fragment() {
val viewScope = viewLifecycleOwner.lifecycleScope
channel.send(ReaderViewModel.Event.TableOfContentsLoaded(model.publication.tableOfContents))
+ channel.send(ReaderViewModel.Event.MetadataLoaded(model.publication.metadata))
navigator.currentLocator
.onEach { channel.send(ReaderViewModel.Event.LocatorUpdate(it)) }
.launchIn(viewScope)
diff --git a/android/src/main/java/com/reactnativereadium/reader/ReaderViewModel.kt b/android/src/main/java/com/reactnativereadium/reader/ReaderViewModel.kt
index 944f85b..537de00 100644
--- a/android/src/main/java/com/reactnativereadium/reader/ReaderViewModel.kt
+++ b/android/src/main/java/com/reactnativereadium/reader/ReaderViewModel.kt
@@ -22,6 +22,7 @@ import org.readium.r2.shared.Search
import org.readium.r2.shared.UserException
import org.readium.r2.shared.publication.Link
import org.readium.r2.shared.util.Try
+import org.readium.r2.shared.publication.Metadata
@OptIn(Search::class, ExperimentalDecorator::class)
class ReaderViewModel(
@@ -113,6 +114,7 @@ class ReaderViewModel(
class Failure(val error: UserException) : Event()
class LocatorUpdate(val locator: Locator) : Event()
class TableOfContentsLoaded(val toc: List) : Event()
+ class MetadataLoaded(val metadata: Metadata) : Event()
}
sealed class FeedbackEvent {
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index c916992..095cbee 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -964,7 +964,7 @@ PODS:
- React-Mapbuffer (0.74.3):
- glog
- React-debug
- - react-native-readium (1.2.1):
+ - react-native-readium (2.0.2):
- R2Navigator
- R2Shared
- R2Streamer
@@ -1503,7 +1503,7 @@ SPEC CHECKSUMS:
React-jsitracing: 6b3c8c98313642140530f93c46f5a6ca4530b446
React-logger: fa92ba4d3a5d39ac450f59be2a3cec7b099f0304
React-Mapbuffer: 9f68550e7c6839d01411ac8896aea5c868eff63a
- react-native-readium: 7f71dab8b9c3eff510a2b7527e7a249691637215
+ react-native-readium: 3de612400580e915706306b4f8879d7ebd029ed7
react-native-safe-area-context: b7daa1a8df36095a032dff095a1ea8963cb48371
react-native-slider: ce295d2bf830a7990af05b0bd70ab28c133e230c
React-nativeconfig: fa5de9d8f4dbd5917358f8ad3ad1e08762f01dcb
@@ -1535,7 +1535,7 @@ SPEC CHECKSUMS:
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
SwiftSoup: 33e8d374021a6c332788f78fa29a93227d8a7699
- Yoga: 88480008ccacea6301ff7bf58726e27a72931c8d
+ Yoga: 04f1db30bb810187397fa4c37dd1868a27af229c
PODFILE CHECKSUM: 686539c4adb72be4e293af103a245974f4ffa466
diff --git a/example/src/components/Reader.tsx b/example/src/components/Reader.tsx
index 0140f04..4823364 100644
--- a/example/src/components/Reader.tsx
+++ b/example/src/components/Reader.tsx
@@ -1,10 +1,7 @@
import React, { useEffect, useState, useRef } from 'react';
import { StyleSheet, View, Text, Platform, DimensionValue } from 'react-native';
-import {
- ReadiumView,
- Settings,
-} from 'react-native-readium';
-import type { Link, Locator, File } from 'react-native-readium';
+import { ReadiumView, Settings } from 'react-native-readium';
+import type { Link, Locator, File, Metadata } from 'react-native-readium';
import RNFS from '../utils/RNFS';
import {
@@ -22,11 +19,13 @@ export const Reader: React.FC = () => {
const [file, setFile] = useState();
const [location, setLocation] = useState();
const [settings, setSettings] = useState>(DEFAULT_SETTINGS);
+ const [metadata, setMetadata] = useState(null);
const ref = useRef();
+ console.log('Metadata:', JSON.stringify(metadata, null, 2));
+
useEffect(() => {
async function run() {
-
if (Platform.OS === 'web') {
setFile({
url: EPUB_URL,
@@ -56,7 +55,7 @@ export const Reader: React.FC = () => {
}
}
- run()
+ run();
}, []);
if (file) {
@@ -66,11 +65,13 @@ export const Reader: React.FC = () => {
setLocation({
- href: loc.href,
- type: 'application/xhtml+xml',
- title: loc.title || '',
- })}
+ onPress={(loc) =>
+ setLocation({
+ href: loc.href,
+ type: 'application/xhtml+xml',
+ title: loc.title || '',
+ })
+ }
/>
@@ -97,7 +98,10 @@ export const Reader: React.FC = () => {
settings={settings}
onLocationChange={(locator: Locator) => setLocation(locator)}
onTableOfContents={(toc: Link[] | null) => {
- if (toc) setToc(toc)
+ if (toc) setToc(toc);
+ }}
+ onMetadata={(metadata: Metadata) => {
+ if (metadata) setMetadata(metadata);
}}
/>
@@ -118,7 +122,7 @@ export const Reader: React.FC = () => {
downloading file
);
-}
+};
const styles = StyleSheet.create({
container: {
diff --git a/ios/ReadiumView.swift b/ios/ReadiumView.swift
index dd798b1..3a1a0f5 100644
--- a/ios/ReadiumView.swift
+++ b/ios/ReadiumView.swift
@@ -35,6 +35,7 @@ class ReadiumView : UIView, Loggable {
}
@objc var onLocationChange: RCTDirectEventBlock?
@objc var onTableOfContents: RCTDirectEventBlock?
+ @objc var onMetadata: RCTDirectEventBlock?
func loadBook(
url: String,
@@ -163,5 +164,9 @@ class ReadiumView : UIView, Loggable {
return link.json
})
])
+ self.onMetadata?([
+ "metadata": vc.publication.metadata.json
+ ])
+
}
}
diff --git a/ios/ReadiumViewManager.m b/ios/ReadiumViewManager.m
index acedabe..01503d9 100644
--- a/ios/ReadiumViewManager.m
+++ b/ios/ReadiumViewManager.m
@@ -7,5 +7,6 @@ @interface RCT_EXTERN_MODULE(ReadiumViewManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(settings, NSDictionary *)
RCT_EXPORT_VIEW_PROPERTY(onLocationChange, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onTableOfContents, RCTDirectEventBlock)
+RCT_EXPORT_VIEW_PROPERTY(onMetadata, RCTDirectEventBlock)
@end
diff --git a/src/components/ReadiumView.tsx b/src/components/ReadiumView.tsx
index 49d6ae7..55cbbd1 100644
--- a/src/components/ReadiumView.tsx
+++ b/src/components/ReadiumView.tsx
@@ -1,4 +1,12 @@
-import React, { useCallback, useState, useEffect, forwardRef, ForwardedRef, useRef, createRef } from 'react';
+import React, {
+ useCallback,
+ useState,
+ useEffect,
+ forwardRef,
+ ForwardedRef,
+ useRef,
+ createRef,
+} from 'react';
import { View, Platform, findNodeHandle, StyleSheet } from 'react-native';
import type { BaseReadiumViewProps, Dimensions } from '../interfaces';
@@ -8,74 +16,102 @@ import { BaseReadiumView } from './BaseReadiumView';
export type ReadiumProps = BaseReadiumViewProps;
-export const ReadiumView: React.FC = forwardRef(({
- onLocationChange: wrappedOnLocationChange,
- onTableOfContents: wrappedOnTableOfContents,
- settings: unmappedSettings,
- ...props
-}, forwardedRef) => {
- const defaultRef = useRef(null);
- const [{ height, width }, setDimensions] = useState({
- width: 0,
- height: 0,
- });
-
- // set the view dimensions on layout
- const onLayout = useCallback(({ nativeEvent: { layout: { width, height } }}: any) => {
- setDimensions({
- width: dimension(width),
- height: dimension(height),
+export const ReadiumView: React.FC = forwardRef(
+ (
+ {
+ onLocationChange: wrappedOnLocationChange,
+ onTableOfContents: wrappedOnTableOfContents,
+ onMetadata: wrappedOnMetadata,
+ settings: unmappedSettings,
+ ...props
+ },
+ forwardedRef
+ ) => {
+ const defaultRef = useRef(null);
+ const [{ height, width }, setDimensions] = useState({
+ width: 0,
+ height: 0,
});
- }, []);
- // wrap the native onLocationChange and extract the raw event value
- const onLocationChange = useCallback((event: any) => {
- if (wrappedOnLocationChange) {
- wrappedOnLocationChange(event.nativeEvent);
- }
- }, [wrappedOnLocationChange]);
+ // set the view dimensions on layout
+ const onLayout = useCallback(
+ ({
+ nativeEvent: {
+ layout: { width, height },
+ },
+ }: any) => {
+ setDimensions({
+ width: dimension(width),
+ height: dimension(height),
+ });
+ },
+ []
+ );
- const onTableOfContents = useCallback((event: any) => {
- if (wrappedOnTableOfContents) {
- const toc = event.nativeEvent.toc || null;
- wrappedOnTableOfContents(toc);
- }
- }, [wrappedOnTableOfContents]);
+ // wrap the native onLocationChange and extract the raw event value
+ const onLocationChange = useCallback(
+ (event: any) => {
+ if (wrappedOnLocationChange) {
+ wrappedOnLocationChange(event.nativeEvent);
+ }
+ },
+ [wrappedOnLocationChange]
+ );
- // create the view fragment on android
- useEffect(() => {
- if (Platform.OS === 'android' && defaultRef.current) {
- const viewId = findNodeHandle(defaultRef.current);
- createFragment(viewId);
- }
- }, []);
+ const onTableOfContents = useCallback(
+ (event: any) => {
+ if (wrappedOnTableOfContents) {
+ const toc = event.nativeEvent.toc || null;
+ wrappedOnTableOfContents(toc);
+ }
+ },
+ [wrappedOnTableOfContents]
+ );
- // assign the forwarded ref
- useEffect(() => {
- if (forwardedRef && 'current' in forwardedRef) {
- forwardedRef.current = defaultRef.current;
- } else if (forwardedRef) {
- forwardedRef(defaultRef);
- }
- }, [defaultRef.current !== null])
+ const onMetadata = useCallback(
+ (event: any) => {
+ if (wrappedOnMetadata) {
+ wrappedOnMetadata(event.nativeEvent);
+ }
+ },
+ [wrappedOnMetadata]
+ );
- return (
-
-
-
- );
-});
+ // create the view fragment on android
+ useEffect(() => {
+ if (Platform.OS === 'android' && defaultRef.current) {
+ const viewId = findNodeHandle(defaultRef.current);
+ createFragment(viewId);
+ }
+ }, []);
+
+ // assign the forwarded ref
+ useEffect(() => {
+ if (forwardedRef && 'current' in forwardedRef) {
+ forwardedRef.current = defaultRef.current;
+ } else if (forwardedRef) {
+ forwardedRef(defaultRef);
+ }
+ }, [defaultRef.current !== null]);
+
+ return (
+
+
+
+ );
+ }
+);
const styles = StyleSheet.create({
container: { width: '100%', height: '100%' },
diff --git a/src/interfaces/BaseReadiumViewProps.ts b/src/interfaces/BaseReadiumViewProps.ts
index b645b2e..b348719 100644
--- a/src/interfaces/BaseReadiumViewProps.ts
+++ b/src/interfaces/BaseReadiumViewProps.ts
@@ -4,6 +4,7 @@ import type { Settings } from './Settings';
import type { Link } from './Link';
import type { Locator } from './Locator';
import type { File } from './File';
+import type { Metadata } from './Metadata';
export type BaseReadiumViewProps = {
file: File;
@@ -12,6 +13,7 @@ export type BaseReadiumViewProps = {
style?: ViewStyle;
onLocationChange?: (locator: Locator) => void;
onTableOfContents?: (toc: Link[] | null) => void;
+ onMetadata?: (metadata: Metadata) => void;
ref?: any;
height?: number;
width?: number;
diff --git a/src/interfaces/Metadata.ts b/src/interfaces/Metadata.ts
new file mode 100644
index 0000000..aa98ef7
--- /dev/null
+++ b/src/interfaces/Metadata.ts
@@ -0,0 +1,39 @@
+/**
+ * An interface representing the Readium Metadata object.
+ */
+export interface Metadata {
+ title: {
+ und: string;
+ };
+ identifier: string;
+ language: string[];
+ author: {
+ name: {
+ und: string;
+ };
+ sortAs?: {
+ und: string;
+ };
+ }[];
+ description: string;
+ published?: string;
+ publisher?: {
+ name: {
+ und: string;
+ };
+ }[];
+ subject?: {
+ name: {
+ und: string;
+ };
+ }[];
+ presentation?: {
+ layout: string;
+ spread: string;
+ overflow: string;
+ orientation: string;
+ continuous: boolean;
+ };
+ readingProgression: string;
+ conformsTo?: string[];
+}
diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts
index b480442..83d2a97 100644
--- a/src/interfaces/index.ts
+++ b/src/interfaces/index.ts
@@ -4,3 +4,4 @@ export * from './File';
export * from './Link';
export * from './Locator';
export * from './Settings';
+export * from './Metadata';