-
-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reorganized a bit of the reader screen to account for future readers a bit better, and added a really bare-bones EPUB reader. This frankly will not hold up in time, IMO, and I'll likely either have to move off of epubjs in favor of an alternative that works well with RN or just build something in house.
- Loading branch information
1 parent
1d30084
commit aec4118
Showing
23 changed files
with
433 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from 'react' | ||
|
||
import { ScreenRootView, Text } from '../primitives' | ||
|
||
export default function UnsupportedReader() { | ||
return ( | ||
<ScreenRootView> | ||
<Text>The book reader for this format is not supported yet. Check back later!</Text> | ||
</ScreenRootView> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { useReader } from '@epubjs-react-native/core' | ||
import React from 'react' | ||
import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||
|
||
import { Text, View } from '@/components/primitives' | ||
|
||
export const FOOTER_HEIGHT = 24 | ||
|
||
export default function EpubJSFooter() { | ||
const { currentLocation } = useReader() | ||
|
||
const { bottom } = useSafeAreaInsets() | ||
|
||
const currentPage = currentLocation?.start?.displayed.page || 1 | ||
const totalPages = currentLocation?.end?.displayed.page || 1 | ||
|
||
return ( | ||
<View | ||
className="w-full shrink-0 items-start justify-start px-4" | ||
style={{ height: FOOTER_HEIGHT + bottom }} | ||
> | ||
<Text> | ||
{currentPage}/{totalPages} | ||
</Text> | ||
</View> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { Location, Reader } from '@epubjs-react-native/core' | ||
import { useFileSystem } from '@epubjs-react-native/expo-file-system' | ||
import { API, isAxiosError, updateEpubProgress } from '@stump/api' | ||
import { Media } from '@stump/types' | ||
import { useColorScheme } from 'nativewind' | ||
import React, { useCallback, useEffect, useState } from 'react' | ||
import { useWindowDimensions } from 'react-native' | ||
|
||
import EpubJSReaderContainer from './EpubJSReaderContainer' | ||
|
||
type Props = { | ||
/** | ||
* The media which is being read | ||
*/ | ||
book: Media | ||
/** | ||
* The initial CFI to start the reader on | ||
*/ | ||
initialCfi?: string | ||
/** | ||
* Whether the reader should be in incognito mode | ||
*/ | ||
incognito?: boolean | ||
} | ||
|
||
/** | ||
* A reader for books that are EPUBs, using EpubJS as the reader | ||
* | ||
* TODO: create a custom reader component, this is a HUGE effort but will pay off in | ||
* the long run | ||
*/ | ||
export default function EpubJSReader({ book, initialCfi, incognito }: Props) { | ||
/** | ||
* The base64 representation of the book file. The reader component does not accept | ||
* credentials in the fetch, so we just have to fetch manually and pass the base64 | ||
* representation to the reader as the source. | ||
*/ | ||
const [base64, setBase64] = useState<string | null>(null) | ||
|
||
const { width, height } = useWindowDimensions() | ||
const { colorScheme } = useColorScheme() | ||
|
||
/** | ||
* An effect that fetches the book file and loads it into the reader component | ||
* as a base64 string | ||
*/ | ||
useEffect(() => { | ||
async function fetchBook() { | ||
try { | ||
const response = await fetch(`${API.getUri()}/media/${book.id}/file`) | ||
const data = await response.blob() | ||
const reader = new FileReader() | ||
reader.onloadend = () => { | ||
const result = reader.result as string | ||
// Note: uncomment this line to show an infinite loader... | ||
// setBase64(result) | ||
const adjustedResult = result.split(',')[1] || result | ||
setBase64(adjustedResult) | ||
} | ||
reader.readAsDataURL(data) | ||
} catch (e) { | ||
console.error(e) | ||
} | ||
} | ||
|
||
fetchBook() | ||
}, [book.id]) | ||
|
||
/** | ||
* A callback that updates the read progress of the current location | ||
* | ||
* If the reader is in incognito mode, this will do nothing. | ||
*/ | ||
const handleLocationChanged = useCallback( | ||
async (_: number, currentLocation: Location, progress: number) => { | ||
if (!incognito) { | ||
const { | ||
start: { cfi }, | ||
} = currentLocation | ||
|
||
try { | ||
await updateEpubProgress({ | ||
epubcfi: cfi, | ||
id: book.id, | ||
is_complete: progress >= 1.0, | ||
percentage: progress, | ||
}) | ||
} catch (e) { | ||
console.error(e) | ||
if (isAxiosError(e)) { | ||
console.error(e.response?.data) | ||
} | ||
} | ||
} | ||
}, | ||
[incognito, book.id], | ||
) | ||
|
||
if (!base64) { | ||
return null | ||
} | ||
|
||
return ( | ||
<EpubJSReaderContainer> | ||
<Reader | ||
src={base64} | ||
onDisplayError={(error) => console.error(error)} | ||
width={width} | ||
// height={height - height * 0.08} | ||
height={height} | ||
fileSystem={useFileSystem} | ||
initialLocation={initialCfi} | ||
onLocationChange={handleLocationChanged} | ||
// renderLoadingFileComponent={LoadingSpinner} | ||
defaultTheme={ | ||
colorScheme === 'dark' | ||
? { | ||
body: { background: '#0F1011 !important', color: '#E8EDF4' }, | ||
} | ||
: { body: { color: 'black' } } | ||
} | ||
/> | ||
</EpubJSReaderContainer> | ||
) | ||
} |
20 changes: 20 additions & 0 deletions
20
apps/expo/src/components/reader/epub/EpubJSReaderContainer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { ReaderProvider } from '@epubjs-react-native/core' | ||
import React from 'react' | ||
|
||
import { ScreenRootView, View } from '@/components/primitives' | ||
|
||
type Props = { | ||
children: React.ReactNode | ||
} | ||
|
||
// total ass, I hate epubjs lol maybe im just dumb? I cannot get the reader to listen to the height | ||
export default function EpubJSReaderContainer({ children }: Props) { | ||
return ( | ||
<ScreenRootView classes="flex-none bg-white dark:bg-gray-950"> | ||
<ReaderProvider> | ||
<View className="flex-none shrink dark:bg-gray-950">{children}</View> | ||
{/* <EpubJSFooter /> */} | ||
</ReaderProvider> | ||
</ScreenRootView> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { LoadingFileProps } from '@epubjs-react-native/core' | ||
import React, { useEffect, useState } from 'react' | ||
|
||
import { Text, View } from '@/components/primitives' | ||
|
||
// FIXME: This causes an error... | ||
export default function LoadingSpinner({ | ||
// downloadProgress, | ||
// downloadError, | ||
downloadSuccess, | ||
}: LoadingFileProps) { | ||
// Setup a timeout that will check if we are stuck loading, abougt 10 seconds | ||
const [didTimeout, setDidTimeout] = useState(false) | ||
|
||
// If we are still loading after 10 seconds, we are stuck | ||
useEffect(() => { | ||
const timeout = setTimeout(() => { | ||
setDidTimeout(true) | ||
}, 10000) | ||
|
||
return () => clearTimeout(timeout) | ||
}, []) | ||
|
||
if (didTimeout && !downloadSuccess) { | ||
return ( | ||
<View> | ||
<Text>It looks like we are stuck loading the book. Check your server logs</Text> | ||
</View> | ||
) | ||
} else if (!downloadSuccess) { | ||
return ( | ||
<View> | ||
<Text>Loading...</Text> | ||
</View> | ||
) | ||
} else { | ||
return null | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as EpubJSReader } from './EpubJSReader' |
Oops, something went wrong.