Spaces:
Sleeping
Sleeping
File size: 6,665 Bytes
a6a4a7d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
import { useEffect } from 'react'
import { Editor } from 'tldraw'
export function useAndroidIntent(editor: Editor) {
useEffect(() => {
if (!editor) return
const convertUriToFileObject = async (uri: string): Promise<File | null> => {
try {
// Priority: Try Android Native Interface for content:// URIs
if (uri.startsWith('content://') && window.AndroidNative && window.AndroidNative.readContentUri) {
console.log("Using AndroidNative to read content URI:", uri);
const base64Data = window.AndroidNative.readContentUri(uri);
if (base64Data) {
const binaryString = atob(base64Data);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
// Try to get filename from URI
let fileName = 'imported_file';
try {
const parts = uri.split('/');
const lastPart = parts[parts.length - 1];
if (lastPart) {
fileName = decodeURIComponent(lastPart);
}
} catch(e) {}
// Guess mime type
let type = 'application/octet-stream';
if (fileName.endsWith('.pdf')) type = 'application/pdf';
if (fileName.endsWith('.png')) type = 'image/png';
if (fileName.endsWith('.jpg') || fileName.endsWith('.jpeg')) type = 'image/jpeg';
return new File([bytes], fileName, { type });
}
}
if (window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Filesystem) {
const { Filesystem } = window.Capacitor.Plugins;
// Fallback to Capacitor Filesystem
console.log("Using Capacitor Filesystem to read URI:", uri);
const fileData = await Filesystem.readFile({
path: uri
});
// Convert base64 data to Blob
// fileData.data is base64 string
const binaryString = atob(fileData.data as string);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
const fileName = uri.split('/').pop()?.split('?')[0] || 'imported_file';
return new File([bytes], fileName, { type: 'application/octet-stream' });
}
} catch (error) {
console.error('Error converting URI to file object:', error);
}
return null;
}
const forceRedirectToColorRM = (uri: string) => {
console.log("File intent detected. Redirecting to ColorRM immediately:", uri);
window.location.href = '/color_rm.html?importPdf=' + encodeURIComponent(uri);
}
const handleFile = async (uri: string) => {
console.log('Received shared file URI:', uri)
// FAST PATH: Redirect immediately if it's a content/file URI, assuming it's for ColorRM
// This skips reading the file in Tldraw app to save time/errors
if (uri.startsWith('content://') || uri.startsWith('file://')) {
forceRedirectToColorRM(uri);
return;
}
try {
const file = await convertUriToFileObject(uri)
if (file) {
// This fallback is only reachable if for some reason the FAST PATH above was skipped
// but convertUriToFileObject still worked (unlikely given the logic above)
if (file.type === 'application/pdf' || file.name.endsWith('.pdf')) {
forceRedirectToColorRM(uri);
} else {
editor.putExternalContent({
type: 'files',
files: [file]
})
}
} else {
alert('Could not read file from URI: ' + uri)
}
} catch (err) {
console.error('Error handling shared file:', err)
alert('Error processing shared file')
}
}
const handleUrl = (url: string) => {
console.log('Received shared URL:', url)
editor.putExternalContent({
type: 'url',
url: url
})
}
// Define global handlers (Editor version handles the actual drop)
// We chain with existing handlers if any (from Global)
const prevHandleFile = window.handleSharedFile;
window.handleSharedFile = (uri: string) => {
if (prevHandleFile) prevHandleFile(uri);
handleFile(uri);
}
window.handleSharedFiles = (uris: string[]) => {
console.log("Editor: Received multiple files, redirecting to ColorRM:", uris);
if (uris.length > 0) {
forceRedirectToColorRM(uris[0]);
}
}
const prevHandleUrl = window.handleSharedUrl;
window.handleSharedUrl = (url: string) => {
if (prevHandleUrl) prevHandleUrl(url);
handleUrl(url);
}
// 1. Process JS-buffered items
// The Global Intent Listener (in main.tsx) polls native and populates this buffer.
if (window.pendingFileUri) {
console.log("Editor: Processing buffered file:", window.pendingFileUri);
handleFile(window.pendingFileUri)
window.pendingFileUri = null
}
if (window.pendingUrl) {
console.log("Editor: Processing buffered url:", window.pendingUrl);
handleUrl(window.pendingUrl)
window.pendingUrl = null
}
// REMOVED: Native Polling & Listeners (Moved to useGlobalAndroidIntent)
// This hook now only reacts to window.handleSharedFile/Url calls and the buffer.
}, [editor])
}
|