feat: add ShareRoomPicker component for selecting rooms to share Android content
- Implemented ShareRoomPicker component to allow users to pick a room for sharing content received from Android intents. - Integrated search functionality to filter rooms and directs. - Added virtualized list for efficient rendering of room options. - Created utility functions for handling Android share payloads, including fetching and clearing pending shares. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
73
overlay/src/app/utils/androidShare.ts
Normal file
73
overlay/src/app/utils/androidShare.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Capacitor, registerPlugin, type PluginListenerHandle } from '@capacitor/core';
|
||||
|
||||
/** Metadata for a file received from an Android share intent. */
|
||||
export type AndroidSharedFile = {
|
||||
path: string;
|
||||
name: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
};
|
||||
|
||||
/** Payload persisted by the native Android share handler. */
|
||||
export type AndroidSharePayload = {
|
||||
text?: string;
|
||||
subject?: string;
|
||||
files: AndroidSharedFile[];
|
||||
receivedAt: number;
|
||||
};
|
||||
|
||||
interface AndroidShareHandlerPlugin {
|
||||
/** Returns the last pending share payload, if one exists. */
|
||||
getPendingShare(): Promise<{ share: AndroidSharePayload | null }>;
|
||||
/** Clears the last pending share payload after it has been consumed. */
|
||||
clearPendingShare(): Promise<void>;
|
||||
addListener(
|
||||
eventName: 'shareReceived',
|
||||
listenerFunc: (payload: AndroidSharePayload) => void
|
||||
): Promise<PluginListenerHandle>;
|
||||
}
|
||||
|
||||
const AndroidShareHandler = registerPlugin<AndroidShareHandlerPlugin>('AndroidShareHandler');
|
||||
|
||||
/** Returns true when the Android share bridge is available. */
|
||||
export const isAndroidShareSupported = (): boolean =>
|
||||
Capacitor.isNativePlatform() && Capacitor.getPlatform() === 'android';
|
||||
|
||||
/** Fetches the current pending native share payload. */
|
||||
export const getPendingAndroidShare = async (): Promise<AndroidSharePayload | null> => {
|
||||
if (!isAndroidShareSupported()) return null;
|
||||
const result = await AndroidShareHandler.getPendingShare();
|
||||
return result.share;
|
||||
};
|
||||
|
||||
/** Clears the native pending share payload. */
|
||||
export const clearPendingAndroidShare = async (): Promise<void> => {
|
||||
if (!isAndroidShareSupported()) return;
|
||||
await AndroidShareHandler.clearPendingShare();
|
||||
};
|
||||
|
||||
/** Subscribes to new incoming native share payloads. */
|
||||
export const listenForAndroidShares = async (
|
||||
listener: (payload: AndroidSharePayload) => void
|
||||
): Promise<PluginListenerHandle | undefined> => {
|
||||
if (!isAndroidShareSupported()) return undefined;
|
||||
return AndroidShareHandler.addListener('shareReceived', listener);
|
||||
};
|
||||
|
||||
/** Converts a cached native shared file into a browser File for upload. */
|
||||
export const materializeSharedFile = async (
|
||||
sharedFile: AndroidSharedFile,
|
||||
receivedAt: number
|
||||
): Promise<File> => {
|
||||
const fileUrl = Capacitor.convertFileSrc(sharedFile.path);
|
||||
const response = await fetch(fileUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to read shared file: ${sharedFile.name}`);
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
return new File([blob], sharedFile.name, {
|
||||
type: sharedFile.mimeType || blob.type,
|
||||
lastModified: receivedAt,
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user