You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

168 lines
4.7 KiB

/**
* WebView Utility Actions
*
* Helper module for sending utility actions to Flutter via HabibApp channel.
* Actions: download_file, copy_to_clipboard, open_external_url, upload_file, buy_coin
*
* Docs: WEBVIEW_ACTION_DOWNLOAD.md
*/
// ─── Helpers ─────────────────────────────────────────────
/** Check if running inside Flutter WebView (HabibApp channel available). */
export function isInFlutterWebView(): boolean {
return typeof window !== "undefined" && !!window.HabibApp?.postMessage;
}
/**
* Low-level: send a JSON message to Flutter via HabibApp.postMessage.
* Returns `true` if the message was dispatched, `false` if channel unavailable.
*/
export function postActionToFlutter(
action: string,
data?: Record<string, unknown>,
): boolean {
if (!isInFlutterWebView()) return false;
const message = data !== undefined ? { action, data } : { action };
window.HabibApp!.postMessage(JSON.stringify(message));
return true;
}
// ─── download_file ───────────────────────────────────────
export interface DownloadFileOptions {
url: string;
fileName?: string;
title?: string;
mimeType?: string;
fileType?: "image" | "video" | "audio" | "document" | "archive" | "other";
size?: number;
metadata?: Record<string, unknown>;
}
/**
* Ask Flutter to download a file natively.
*
* ```ts
* downloadFile({ url: 'https://…/doc.pdf', fileName: 'doc.pdf', mimeType: 'application/pdf', fileType: 'document' });
* ```
*/
export function downloadFile(options: DownloadFileOptions): boolean {
return postActionToFlutter(
"download_file",
options as unknown as Record<string, unknown>,
);
}
// ─── copy_to_clipboard ──────────────────────────────────
export interface CopyToClipboardOptions {
text: string;
label?: string;
showToast?: boolean;
}
/**
* Copy text to the device clipboard via Flutter.
* Falls back to `navigator.clipboard.writeText` if not in WebView.
*/
export async function copyToClipboard(
text: string,
label?: string,
): Promise<boolean> {
if (isInFlutterWebView()) {
return postActionToFlutter("copy_to_clipboard", {
text,
label,
showToast: true,
});
}
// Fallback for normal browser
try {
await navigator.clipboard.writeText(text);
return true;
} catch {
return false;
}
}
// ─── open_external_url ──────────────────────────────────
export interface OpenExternalUrlOptions {
url: string;
mode?: "externalApplication" | "platformDefault";
title?: string;
showErrorToast?: boolean;
}
/**
* Ask Flutter to open a URL in the external browser / app.
*
* ```ts
* openExternalUrl({ url: 'https://habibapp.com' });
* ```
*/
export function openExternalUrl(options: OpenExternalUrlOptions): boolean {
return postActionToFlutter("open_external_url", {
mode: "externalApplication",
showErrorToast: true,
...options,
} as Record<string, unknown>);
}
// ─── upload_file ─────────────────────────────────────────
export interface UploadFileOptions {
mediaType: "image" | "video" | "image+video" | "audio" | "file";
source?: "gallery" | "camera" | "any";
multiple?: boolean;
returnAs?: "upload" | "base64";
uploadUrl?: string;
fieldName?: string;
uploadMethod?: string;
headers?: Record<string, string>;
maxBytes?: number;
allowedExtensions?: string[];
maxWidth?: number;
maxHeight?: number;
imageQuality?: number;
title?: string;
}
/**
* Ask Flutter to pick (and optionally upload) a file from the device.
*
* ```ts
* uploadFile({
* mediaType: 'image',
* source: 'gallery',
* returnAs: 'upload',
* uploadUrl: '/hussainya/dashboard/upload-media/',
* maxBytes: 5_242_880,
* });
* ```
*/
export function uploadFile(options: UploadFileOptions): boolean {
return postActionToFlutter(
"upload_file",
options as unknown as Record<string, unknown>,
);
}
// ─── buy_coin ────────────────────────────────────────────
/**
* Ask Flutter to open the Habib Coin packages list page (Add Coin).
*
* Used when a payment fails with "Not enough coins": the user tops up
* natively, returns to the WebView and retries the payment.
*
* ```ts
* buyHabibCoinPackages();
* ```
*/
export function buyHabibCoinPackages(): boolean {
return postActionToFlutter("buy_coin");
}