Files
gh-christianlouis-docuelevate/mobile/src/context/ShareContext.tsx
T
copilot-swe-agent[bot] 71a7a57adc fix(mobile): add shared file to ShareContext directly in +not-found.tsx
When iOS delivers a file via "Open In…", expo-router strips the
docuelevate:// scheme and routes to +not-found.tsx. Previously, this
screen only redirected to the Upload tab and relied on the Linking
handler in _layout.tsx to add the file to ShareContext. This was
unreliable because expo-router may consume the URL event before the
Linking handler fires.

Now +not-found.tsx directly reconstructs the file:// URI from the
pathname and adds it to ShareContext before redirecting. ShareContext
deduplicates by URI to prevent double uploads if both mechanisms fire.

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-19 11:12:34 +00:00

61 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* ShareContext propagates files received from the iOS Share Sheet or the
* Android Share Intent to the UploadScreen so they can be uploaded
* automatically.
*
* The root layout listens for incoming file:// / content:// URLs via
* expo-linking and calls addPendingFile(). UploadScreen consumes the context,
* uploads each pending file, then calls clearPendingFiles().
*/
import React, { createContext, useCallback, useContext, useState } from "react";
export interface SharedFile {
uri: string;
filename: string;
mimeType?: string;
}
interface ShareContextValue {
pendingFiles: SharedFile[];
addPendingFile: (file: SharedFile) => void;
clearPendingFiles: () => void;
}
const ShareContext = createContext<ShareContextValue>({
pendingFiles: [],
addPendingFile: () => {},
clearPendingFiles: () => {},
});
export function ShareProvider({ children }: { children: React.ReactNode }) {
const [pendingFiles, setPendingFiles] = useState<SharedFile[]>([]);
const addPendingFile = useCallback((file: SharedFile) => {
setPendingFiles((prev) => {
// Deduplicate by normalised URI so the same file is not uploaded twice
// when both the Linking handler (_layout.tsx) and +not-found.tsx fire.
const normalize = (uri: string) => {
try { return decodeURIComponent(uri); } catch { return uri; }
};
const norm = normalize(file.uri);
if (prev.some((f) => normalize(f.uri) === norm)) return prev;
return [...prev, file];
});
}, []);
const clearPendingFiles = useCallback(() => {
setPendingFiles([]);
}, []);
return (
<ShareContext.Provider value={{ pendingFiles, addPendingFile, clearPendingFiles }}>
{children}
</ShareContext.Provider>
);
}
export function useShare(): ShareContextValue {
return useContext(ShareContext);
}