mirror of
https://github.com/linkwarden/linkwarden.git
synced 2026-03-03 03:47:02 +00:00
137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import * as FileSystem from "expo-file-system";
|
|
import NetInfo from "@react-native-community/netinfo";
|
|
import useAuthStore from "@/store/auth";
|
|
import { ArchivedFormat } from "@linkwarden/types";
|
|
import { Link as LinkType } from "@linkwarden/prisma/client";
|
|
import WebView from "react-native-webview";
|
|
import { Image, Platform, ScrollView } from "react-native";
|
|
|
|
type Props = {
|
|
link: LinkType;
|
|
setIsLoading: (state: boolean) => void;
|
|
format: ArchivedFormat.png | ArchivedFormat.jpeg;
|
|
};
|
|
|
|
export default function ImageFormat({ link, setIsLoading, format }: Props) {
|
|
const FORMAT = format;
|
|
|
|
const extension = format === ArchivedFormat.png ? "png" : "jpeg";
|
|
|
|
const { auth } = useAuthStore();
|
|
const [content, setContent] = useState<string>("");
|
|
const [dimension, setDimension] = useState<{
|
|
width: number;
|
|
height: number;
|
|
}>();
|
|
|
|
useEffect(() => {
|
|
if (content)
|
|
Image.getSize(content, (width, height) => {
|
|
setDimension({ width, height });
|
|
});
|
|
}, [content]);
|
|
|
|
useEffect(() => {
|
|
async function loadCacheOrFetch() {
|
|
const filePath =
|
|
FileSystem.documentDirectory +
|
|
`archivedData/${extension}/link_${link.id}.${extension}`;
|
|
|
|
await FileSystem.makeDirectoryAsync(
|
|
filePath.substring(0, filePath.lastIndexOf("/")),
|
|
{
|
|
intermediates: true,
|
|
}
|
|
).catch(() => {});
|
|
|
|
const [info] = await Promise.all([FileSystem.getInfoAsync(filePath)]);
|
|
|
|
if (info.exists) {
|
|
setContent(filePath);
|
|
}
|
|
|
|
const net = await NetInfo.fetch();
|
|
|
|
if (net.isConnected) {
|
|
const apiUrl = `${auth.instance}/api/v1/archives/${link.id}?format=${FORMAT}`;
|
|
|
|
try {
|
|
const result = await FileSystem.downloadAsync(apiUrl, filePath, {
|
|
headers: { Authorization: `Bearer ${auth.session}` },
|
|
});
|
|
|
|
setContent(result.uri);
|
|
} catch (e) {
|
|
console.error("Failed to fetch content", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
loadCacheOrFetch();
|
|
}, [link]);
|
|
|
|
if (Platform.OS === "ios")
|
|
return (
|
|
content &&
|
|
dimension && (
|
|
<ScrollView maximumZoomScale={10}>
|
|
<Image
|
|
source={{ uri: content }}
|
|
onLoadEnd={() => setIsLoading(false)}
|
|
style={{
|
|
width: "100%",
|
|
height: "auto",
|
|
aspectRatio: dimension.width / dimension.height,
|
|
}}
|
|
resizeMode="contain"
|
|
/>
|
|
</ScrollView>
|
|
)
|
|
);
|
|
else
|
|
return (
|
|
content && (
|
|
<WebView
|
|
style={{
|
|
flex: 1,
|
|
}}
|
|
source={{
|
|
baseUrl: content,
|
|
html: `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
img {
|
|
max-width: 100%;
|
|
height: auto;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<img src="${content}" />
|
|
</body>
|
|
</html>
|
|
`,
|
|
}}
|
|
scalesPageToFit
|
|
originWhitelist={["*"]}
|
|
mixedContentMode="always"
|
|
javaScriptEnabled={true}
|
|
allowFileAccess={true}
|
|
allowFileAccessFromFileURLs={true}
|
|
allowUniversalAccessFromFileURLs={true}
|
|
onLoadEnd={() => setIsLoading(false)}
|
|
/>
|
|
)
|
|
);
|
|
}
|