Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example App Fix Images #204

Merged
merged 2 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class DecryptedLocalAttachment(
companion object {
fun fromJsonObject(obj: JsonObject) = DecryptedLocalAttachment(
obj.get("fileUri").asString,
obj.get("mimeType").asString,
obj.get("mimeType")?.asString ?: "",
obj.get("filename")?.asString ?: "",
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@
import expo.modules.ApplicationLifecycleDispatcher;
import expo.modules.ReactNativeHostWrapper;

import com.ReactNativeBlobUtil.ReactNativeBlobUtilUtils;

import java.security.cert.CertificateException;
import java.util.List;

import javax.net.ssl.X509TrustManager;

public class MainApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost =
Expand Down Expand Up @@ -64,6 +69,21 @@ public void onCreate() {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
}
ReactNativeBlobUtilUtils.sharedTrustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
};

ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
ApplicationLifecycleDispatcher.onApplicationCreate(this);
}
Expand Down
16 changes: 15 additions & 1 deletion example/dev/local/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ services:
depends_on:
wakunode:
condition: service_healthy
build: ./test
build: ./test

upload-service:
build: ./upload-service
ports:
- 4567:4567

caddy:
image: caddy:latest
ports:
- "443:443"
volumes:
- ./upload-service/Caddyfile:/etc/caddy/Caddyfile
- ./upload-service/data/data:/data
- ./upload-service/data/config:/config
6 changes: 4 additions & 2 deletions example/src/ConversationScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,11 @@ export default function ConversationScreen({
<View style={{ flex: 1 }}>
<AttachmentModal
visible={isShowingAttachmentModal}
onAttachedImageFromCamera={(image) =>
onAttachedImageFromCamera={(image) => {
console.log('from camera', image)
}
setAttachment({ image })
setShowingAttachmentModal(false)
}}
onAttachedImageFromLibrary={(image) => {
setAttachment({ image })
setShowingAttachmentModal(false)
Expand Down
82 changes: 58 additions & 24 deletions example/src/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useEffect, useState } from 'react'
import EncryptedStorage from 'react-native-encrypted-storage'
import { useQuery, UseQueryResult } from 'react-query'
import { useMutation, useQuery, UseQueryResult } from 'react-query'
import {
Conversation,
DecodedMessage,
Expand Down Expand Up @@ -273,38 +274,71 @@ export function usePrepareRemoteAttachment({
}): {
remoteAttachment: RemoteAttachmentContent | undefined
} {
const [remoteAttachment, setRemoteAttachment] = useState<
RemoteAttachmentContent | undefined
>(undefined)
const { client } = useXmtp()
const { data: encrypted } = useQuery<EncryptedLocalAttachment>(
['xmtp', 'remoteAttachment', 'local', fileUri, mimeType ?? ''],
() =>
const { mutateAsync: encryptAttachment } = useMutation<
EncryptedLocalAttachment,
unknown,
{ fileUri?: string; mimeType?: string }
>(
['xmtp', 'remoteAttachment', 'local'],
({ fileUri, mimeType }) =>
client!.encryptAttachment({
fileUri: fileUri!,
mimeType,
}),
{
enabled: !!client && !!fileUri,
}
{}
)
const { data: url } = useQuery<string>(
['xmtp', 'remoteAttachment', 'upload', encrypted?.metadata?.contentDigest],
() =>
const { mutateAsync: uploadAttachment } = useMutation<
string,
unknown,
EncryptedLocalAttachment
>(
['xmtp', 'remoteAttachment', 'upload'],
(attachement: EncryptedLocalAttachment) =>
uploadFile(
encrypted!.encryptedLocalFileUri,
encrypted?.metadata?.contentDigest
),
{
enabled: !!encrypted,
}
attachement!.encryptedLocalFileUri,
attachement?.metadata?.contentDigest
)
)
return {
remoteAttachment: url
? {
url,

const callback = useCallback(
async ({ fileUri, mimeType }: { fileUri: string; mimeType?: string }) => {
const encrypted = await encryptAttachment({
fileUri,
mimeType,
})
const url = await uploadAttachment(encrypted)
return {
url,
metadata: encrypted.metadata,
}
},
[encryptAttachment, uploadAttachment]
)

useEffect(() => {
console.log('Preparing remote attachment', { fileUri, mimeType })
if (!fileUri) {
setRemoteAttachment(undefined)
return
}
callback({ fileUri, mimeType })
.then((res) => {
setRemoteAttachment({
url: res.url,
scheme: 'https://',
...encrypted!.metadata,
}
: undefined,
}
...res.metadata,
})
})
.catch((err) => {
console.log('Error preparing remote attachment', err)
})
}, [fileUri, mimeType, callback])

return { remoteAttachment }
}

/**
Expand Down
19 changes: 13 additions & 6 deletions example/src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import ReactNativeBlobUtil from 'react-native-blob-util'
// It is not intended for production use, but is useful for testing and development.
// See `dev/local/upload-service`

const storageUrl = process.env.REACT_APP_STORAGE_URL || 'https://localhost'
const useLocalServer = !process.env.REACT_APP_USE_LOCAL_SERVER
const storageUrl = useLocalServer
? 'https://localhost'
: process.env.REACT_APP_STORAGE_URL
const headers = {
'Content-Type': 'application/octet-stream',
}
Expand All @@ -16,20 +19,24 @@ export async function uploadFile(
): Promise<string> {
const url = `${storageUrl}/${fileId}`
console.log('uploading to', url)
await ReactNativeBlobUtil.config({ fileCache: true }).fetch(
await ReactNativeBlobUtil.config({
fileCache: true,
trusty: useLocalServer,
}).fetch(
'POST',
url,
headers,
ReactNativeBlobUtil.wrap(localFileUri.slice('file://'.length))
)

return url
}

export async function downloadFile(url: string): Promise<string> {
console.log('downloading from', url)
const res = await ReactNativeBlobUtil.config({ fileCache: true }).fetch(
'GET',
url
)
const res = await ReactNativeBlobUtil.config({
fileCache: true,
trusty: useLocalServer,
}).fetch('GET', url)
return `file://${res.path()}`
}
Loading