fix: Shared image links are now correctly handled on iOS

This commit is contained in:
Aman Harwara
2023-07-21 15:53:36 +05:30
parent 68db05581b
commit ab2e88a710
5 changed files with 64 additions and 33 deletions

View File

@@ -109,42 +109,16 @@ export class ReceivedSharedItemsHandler {
return return
} }
if (isReceivedAndroidFile(item)) { if (isReceivedAndroidFile(item) || isReceivedIosFile(item)) {
const data = await readFile(item.contentUri, 'base64') this.sendFileToWebView(item).catch(console.error)
const file = {
name: item.fileName || item.contentUri,
data,
mimeType: item.mimeType,
}
this.webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.ReceivedFile,
messageType: 'event',
messageData: file,
}),
)
} else if (isReceivedIosFile(item)) {
const data = await readFile(item.path, 'base64')
const file = {
name: item.fileName || item.path,
data,
mimeType: item.mimeType,
}
this.webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.ReceivedFile,
messageType: 'event',
messageData: file,
}),
)
} else if (isReceivedWeblink(item)) { } else if (isReceivedWeblink(item)) {
this.webViewRef.current?.postMessage( this.webViewRef.current?.postMessage(
JSON.stringify({ JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.ReceivedText, reactNativeEvent: ReactNativeToWebEvent.ReceivedLink,
messageType: 'event', messageType: 'event',
messageData: { messageData: {
title: item.subject || item.weblink, title: item.subject || item.weblink,
text: item.weblink, link: item.weblink,
}, },
}), }),
) )
@@ -163,6 +137,23 @@ export class ReceivedSharedItemsHandler {
this.handleItemsQueue().catch(console.error) this.handleItemsQueue().catch(console.error)
} }
sendFileToWebView = async (item: ReceivedAndroidFile | ReceivedIosFile) => {
const path = isReceivedAndroidFile(item) ? item.contentUri : item.path
const data = await readFile(path, 'base64')
const file = {
name: item.fileName || item.path,
data,
mimeType: item.mimeType,
}
this.webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.ReceivedFile,
messageType: 'event',
messageData: file,
}),
)
}
private addSharedItemsToQueue = async (url?: string) => { private addSharedItemsToQueue = async (url?: string) => {
const received = const received =
Platform.OS === 'ios' ? await ReceiveSharingIntent.getFileNames(url) : await ReceiveSharingIntent.getFileNames() Platform.OS === 'ios' ? await ReceiveSharingIntent.getFileNames(url) : await ReceiveSharingIntent.getFileNames()

View File

@@ -10,5 +10,6 @@ export enum ReactNativeToWebEvent {
KeyboardWillShow = 'KeyboardWillShow', KeyboardWillShow = 'KeyboardWillShow',
KeyboardWillHide = 'KeyboardWillHide', KeyboardWillHide = 'KeyboardWillHide',
ReceivedFile = 'ReceivedFile', ReceivedFile = 'ReceivedFile',
ReceivedLink = 'ReceivedLink',
ReceivedText = 'ReceivedText', ReceivedText = 'ReceivedText',
} }

View File

@@ -18,6 +18,7 @@ export interface WebApplicationInterface extends ApplicationInterface {
handleMobileKeyboardDidChangeFrameEvent(frame: { height: number; contentHeight: number }): void handleMobileKeyboardDidChangeFrameEvent(frame: { height: number; contentHeight: number }): void
handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void
handleReceivedTextEvent(item: { text: string; title?: string }): Promise<void> handleReceivedTextEvent(item: { text: string; title?: string }): Promise<void>
handleReceivedLinkEvent(item: { link: string; title: string }): Promise<void>
isNativeMobileWeb(): boolean isNativeMobileWeb(): boolean
mobileDevice(): MobileDeviceInterface mobileDevice(): MobileDeviceInterface
handleAndroidBackButtonPressed(): void handleAndroidBackButtonPressed(): void

View File

@@ -54,7 +54,7 @@ import { ItemGroupController } from '@/Components/NoteView/Controller/ItemGroupC
import { VisibilityObserver } from './VisibilityObserver' import { VisibilityObserver } from './VisibilityObserver'
import { MomentsService } from '@/Controllers/Moments/MomentsService' import { MomentsService } from '@/Controllers/Moments/MomentsService'
import { DevMode } from './DevMode' import { DevMode } from './DevMode'
import { ToastType, addToast } from '@standardnotes/toast' import { ToastType, addToast, dismissToast } from '@standardnotes/toast'
export type WebEventObserver = (event: WebAppEvent, data?: unknown) => void export type WebEventObserver = (event: WebAppEvent, data?: unknown) => void
@@ -395,7 +395,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
const filesController = this.controllers.filesController const filesController = this.controllers.filesController
const blob = getBlobFromBase64(file.data, file.mimeType) const blob = getBlobFromBase64(file.data, file.mimeType)
const mappedFile = new File([blob], file.name, { type: file.mimeType }) const mappedFile = new File([blob], file.name, { type: file.mimeType })
void filesController.uploadNewFile(mappedFile, true) filesController.uploadNewFile(mappedFile, true).catch(console.error)
} }
async handleReceivedTextEvent({ text, title }: { text: string; title?: string | undefined }) { async handleReceivedTextEvent({ text, title }: { text: string; title?: string | undefined }) {
@@ -417,6 +417,41 @@ export class WebApplication extends SNApplication implements WebApplicationInter
}) })
} }
async handleReceivedLinkEvent({ link, title }: { link: string; title: string | undefined }) {
const url = new URL(link)
const paths = url.pathname.split('/')
const finalPath = paths[paths.length - 1]
const isImagePath = !!finalPath && /\.(png|svg|webp|jpe?g)/.test(finalPath)
if (isImagePath) {
const fetchToastUuid = addToast({
type: ToastType.Loading,
message: 'Fetching image from link...',
})
try {
const imgResponse = await fetch(link)
if (!imgResponse.ok) {
throw new Error(`${imgResponse.status}: Could not fetch image`)
}
const imgBlob = await imgResponse.blob()
const file = new File([imgBlob], finalPath, {
type: imgBlob.type,
})
this.controllers.filesController.uploadNewFile(file, true).catch(console.error)
} catch (error) {
console.error(error)
} finally {
dismissToast(fetchToastUuid)
}
return
}
this.handleReceivedTextEvent({
title: title,
text: link,
}).catch(console.error)
}
private async lockApplicationAfterMobileEventIfApplicable(): Promise<void> { private async lockApplicationAfterMobileEventIfApplicable(): Promise<void> {
const isLocked = await this.isLocked() const isLocked = await this.isLocked()
if (isLocked) { if (isLocked) {

View File

@@ -93,7 +93,10 @@ export class MobileWebReceiver {
) )
break break
case ReactNativeToWebEvent.ReceivedText: case ReactNativeToWebEvent.ReceivedText:
void this.application.handleReceivedTextEvent(messageData as { text: string; title?: string }) void this.application.handleReceivedTextEvent(messageData as { text: string })
break
case ReactNativeToWebEvent.ReceivedLink:
void this.application.handleReceivedLinkEvent(messageData as { link: string; title: string })
break break
default: default: