victorsoares96 / epubjs-react-native

ePub.js Reader for React Native
MIT License
129 stars 44 forks source link

Trouble using a hardcoded URI from my device. #284

Open aly-001 opened 1 week ago

aly-001 commented 1 week ago

Summary

I’m trying to implement a ReadScreen component for my app that uses the epubjs-react-native library to open an epub given a URI of a file that’s on my machine.

I’m running into a strange error. When I dynamically set the URI using a document picker, and then pass that picked URI as a state variable to the Reader component from epubjs-react-native, it works great. (I’ll explain the flow soon)

However, when I retrieve that same URI I’m passing as a state variable (by logging it on the console and copying it) and then paste that as the src prop to the Reader component, it doesn’t work, and I get “opening…” showing on my screen for a very long time.

I’m wondering what the difference between passing a picked URI from a file state variable and the actual uri is, and how I can get the reader to work with an actual uri.

So, here’s the working code that uses the picker:

import React, {useState} from "react";
import { View, Button } from "react-native";
import { ReaderProvider } from "@epubjs-react-native/core";
import * as DocumentPicker from "expo-document-picker";
import { Reader } from "@epubjs-react-native/core";
import { useFileSystem } from "@epubjs-react-native/expo-file-system";

export default function ReadScreen() {

  const [fileUri, setFileUri] = useState(null);

  const pickDocument = async () => {
    try {
      const res = await DocumentPicker.getDocumentAsync({
        type: "application/epub+zip",
        copyToCacheDirectory: false,
      });
      if (res.assets && res.assets.length > 0) {
        setFileUri(res.assets[0].uri);
      } else {
        setFileUri(null);
        console.log("No file selected");
      }
    } catch (err) {
      console.log("Error while picking the file", err);
    }
  };

  if (fileUri){
    return (
      <ReaderProvider>
        <Reader src={fileUri} fileSystem={useFileSystem} />
      </ReaderProvider>
    );
  } else {
    return (
      <View >
        <Button
          title="Pick an epub file"
          onPress={pickDocument}
        />
      </View>
    );
  }
}

How this works:

There is a state variable called “fileUri” initialized to null. Depending on whether this variable is defined or null, the component renders two different things.

If fileUri null, it renders a button is used to call “pickDocument”. PickDocument uses the DocumentPicker from Expo, gets a response and sets fileUri to the uri of the response object.

If fileUri is not null, it renders a Reader component with “src” set to fileUri.

So the flow is:

1) fileUri is null

2) A button is rendered

3) Button pressed opens the document picker

4) If a valid file is selected, fileUri gets set and is no longer null

5) Reader gets called rendered the fileUri set as src.

Now, my objective is to be able to use a hardcoded URI from my device and render a Reader component with that URI. So how do I get the URI? I log it! (I add the following hook:)

  useEffect(() => {
    console.log(fileUri);
  }, [fileUri]);

This is what I get on the console:

file:///private/var/mobile/Containers/Data/Application/45FF978B-313D-4160-8D88-28E588F5F85B/tmp/host.exp.Exponent-Inbox/Aldous%20Huxley%20-%20Brave%20New%20World-Harper%20Perennial%20Modern%20Classics%20(2010).epub

Now, it would make sense that if I use this URI by just setting it for “src” in the Reader component, it would yield exactly the same result.

import React, { useState, useEffect } from "react";
import { View, Button } from "react-native";
import { ReaderProvider } from "@epubjs-react-native/core";
import * as DocumentPicker from "expo-document-picker";
import { Reader } from "@epubjs-react-native/core";
import { useFileSystem } from "@epubjs-react-native/expo-file-system";

export default function ReadScreen() {

  return (
    <ReaderProvider>
      <Reader
        src={
          "file:///private/var/mobile/Containers/Data/Application/45FF978B-313D-4160-8D88-28E588F5F85B/tmp/host.exp.Exponent-Inbox/Aldous%20Huxley%20-%20Brave%20New%20World-Harper%20Perennial%20Modern%20Classics%20(2010).epub"
        }
        fileSystem={useFileSystem}
      />
    </ReaderProvider>
  );
}

But this yields an infinite spinner that says “Opening” below it.

What platform(s) does this occur on?

iOS

What workflow(s) does this occur on?

Expo Workflow

Environment (or package.json)

{ "name": "screens", "version": "1.0.0", "main": "expo/AppEntry.js", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@epubjs-react-native/core": "^1.4.5", "@expo/vector-icons": "^14.0.2", "@types/react": "~18.2.79", "expo": "~51.0.14", "expo-document-picker": "^12.0.2", "expo-file-system": "^17.0.1", "expo-status-bar": "~1.12.1", "openai": "^4.51.0", "react": "18.2.0", "react-native": "0.74.2", "react-native-gesture-handler": "^2.17.0", "react-native-webview": "^13.10.3", "typescript": "~5.3.3",

"@epubjs-react-native/expo-file-system": "^1.1.3",
"@epubjs-react-native/file-system": "^1.1.3",
"@react-native-community/hooks": "^3.0.0",
"@react-navigation/native": "react-navigation/native",
"axios": "^1.7.2",
"express": "^4.19.2",
"react-native-fs": "^2.20.0",
"react-native-paper": "^5.12.3",
"react-native-safe-area-context": "^4.10.1"

}, "devDependencies": { "@babel/core": "^7.20.0" }, "private": true }

Your .epub file

No response

Minimal reproducible example

No response

I confirm that i have

victorsoares96 commented 2 days ago

thanks for share, i'll see this asap