@retion-miniapp/react-native 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -322,9 +322,10 @@ declare const closeMiniApp: () => void;
322
322
  * Giống icon app trên iOS:
323
323
  * - queued: chờ tới lượt (icon mờ) · downloading: tải lần đầu · updating: đã có bản cũ, đang tải bản mới
324
324
  * - installed: mở được · failed: lỗi sau khi thử lại (has_local → vẫn mở bản cũ)
325
+ * - paused: app này bị pauseMiniApp(app_id) — nằm trong hàng đợi nhưng không tải tới khi resumeMiniApp
325
326
  * - uninstalling: app không còn trong list, đang xoá
326
327
  */
327
- type MiniAppDownloadStatus = 'queued' | 'downloading' | 'updating' | 'installed' | 'failed' | 'uninstalling';
328
+ type MiniAppDownloadStatus = 'queued' | 'downloading' | 'updating' | 'installed' | 'failed' | 'paused' | 'uninstalling';
328
329
  interface MiniAppDownloadState {
329
330
  status: MiniAppDownloadStatus;
330
331
  /** 0–1 khi đang tải. */
@@ -359,6 +360,11 @@ type MiniAppEvent =
359
360
  app_ids: string[];
360
361
  removed: string[];
361
362
  }
363
+ /** Sync lỗi (mạng / API / token) — catalog cũ giữ nguyên, app trong máy vẫn mở được. */
364
+ | {
365
+ type: 'sync_failed';
366
+ error: string;
367
+ }
362
368
  /** Hàng đợi chuyển dừng ↔ chạy (pauseMiniAppDownloads / resumeMiniAppDownloads). reasons = lý do còn lại. */
363
369
  | {
364
370
  type: 'pause_change';
@@ -378,20 +384,53 @@ declare const useMiniAppDownloadsPaused: () => boolean;
378
384
  declare const onMiniAppEvent: (listener: (event: MiniAppEvent) => void) => () => void;
379
385
  /** Status hiện tại của mọi mini app — đọc 1 lần khi vẽ Sảnh, sau đó nghe onMiniAppEvent. */
380
386
  declare const getMiniAppStatuses: () => Record<string, MiniAppDownloadState>;
387
+ type MiniAppSyncResult = {
388
+ ok: true;
389
+ app_ids: string[];
390
+ removed: string[];
391
+ } | {
392
+ ok: false;
393
+ error: string;
394
+ };
381
395
  /**
382
396
  * Lấy list mini app (theo config.channels — kênh đứng trước được ưu tiên) → cập nhật catalog
383
- * → cho app khác version vào hàng đợi. Lỗi mạng → giữ catalog cũ, không xoá gì.
397
+ * → cho app khác version vào hàng đợi. Lỗi mạng → giữ catalog cũ, không xoá gì, bắn sync_failed.
398
+ * Không bao giờ reject — kết quả trả về giống event sync_complete / sync_failed.
384
399
  */
385
- declare const syncMiniAppCatalog: () => Promise<void>;
400
+ declare const syncMiniAppCatalog: () => Promise<MiniAppSyncResult>;
386
401
  /**
387
- * Gỡ mini app khỏi máy: bỏ khỏi hàng đợi, huỷ lượt tải đang chạy, xoá bundle, huỷ WebView (trừ khi
388
- * đang mở). syncMiniAppCatalog tự gọi cho app không còn trong list; app còn trong list → lần sync sau tải lại.
402
+ * Người dùng gỡ mini app: bỏ khỏi hàng đợi, huỷ lượt tải đang chạy, xoá bundle, huỷ WebView (trừ khi
403
+ * đang mở). Ghi nhớ (storage) → sync không tải lại; tải lại bằng restoreMiniApp / người dùng bấm mở.
389
404
  */
390
405
  declare const uninstallMiniApp: (app_id: string) => Promise<void>;
406
+ /**
407
+ * Tải lại app người dùng đã gỡ (vd màn "Thêm app"): bỏ ghi nhớ đã gỡ → vào hàng đợi (`queued`).
408
+ * false: app không có trong list (chưa sync / admin đã tắt).
409
+ */
410
+ declare const restoreMiniApp: (app_id: string) => boolean;
411
+ /**
412
+ * Pause riêng 1 app: đang tải → huỷ (tải lại từ đầu khi resume), đang chờ → `paused`, chưa cần tải →
413
+ * nhớ lại, bản mới ở lần sync sau cũng `paused`. App khác vẫn tải bình thường. Người dùng bấm mở → tải luôn.
414
+ * Lưu storage: thoát app mở lại vẫn pause, chỉ tải khi resumeMiniApp / người dùng bấm mở / gỡ app.
415
+ */
416
+ declare const pauseMiniApp: (app_id: string) => void;
417
+ /** Gỡ pause riêng của app → đang chờ thì về `queued` và hàng đợi chạy tiếp. */
418
+ declare const resumeMiniApp: (app_id: string) => void;
391
419
  /** Dừng hàng đợi vì `reason`. File đang tải (không phải do người dùng mở) bị huỷ, tải lại sau. */
392
420
  declare const pauseMiniAppDownloads: (reason: string) => void;
393
421
  /** Gỡ lý do dừng; hết lý do → chạy tiếp. */
394
422
  declare const resumeMiniAppDownloads: (reason: string) => void;
423
+ type MiniAppCatalogItem = MiniAppCatalogEntry & {
424
+ /** Máy đang có 1 bản (có thể cũ). */
425
+ installed: boolean;
426
+ /** Người dùng đã tự gỡ — sync không tải lại, chỉ tải khi restoreMiniApp. */
427
+ removed_by_user: boolean;
428
+ };
429
+ /**
430
+ * Mọi app trong list ứng dụng (lần sync gần nhất) kèm trạng thái — đọc đồng bộ, không gọi mạng.
431
+ * Dùng cho màn "Thêm app": lọc `!installed || removed_by_user`, tìm theo `name`, chọn → restoreMiniApp.
432
+ */
433
+ declare const getMiniAppCatalog: () => MiniAppCatalogItem[];
395
434
  /** app_id có trong catalog ứng dụng (đã phát hành) — đọc sync, không gọi mạng. */
396
435
  declare const getMiniAppCatalogEntry: (app_id: string) => MiniAppCatalogEntry | undefined;
397
436
  /**
@@ -415,4 +454,4 @@ declare class BridgeError extends Error {
415
454
  constructor(code: string, message: string);
416
455
  }
417
456
 
418
- export { DefaultMiniAppSplash, MINIAPP_PLATFORM_URL, type MiniAppBridgeOptions, type MiniAppCatalogEntry, type MiniAppChannel, type MiniAppConfig, type MiniAppContainerProps, type MiniAppContext, type MiniAppDownloadState, type MiniAppDownloadStatus, type MiniAppDownloadTask, type MiniAppEvent, type MiniAppFileSystem, type MiniAppHandlerContext, _default as MiniAppHost, type MiniAppHostData, BridgeError as MiniAppHostError, type MiniAppHostProps, type MiniAppKeepAlive, type MiniAppLaunch, type MiniAppLocalBundle, type MiniAppManifest, type MiniAppNativeHandlers, type MiniAppPaymentRequest, type MiniAppPaymentResult, type MiniAppPermission, type MiniAppSplashProps, type MiniAppStorage, type OpenMiniAppArgs, closeMiniApp, configureMiniApp, createMmkvStorage, createRnfsFileSystem, ensureMiniApp, getLocalMiniApp, getMiniAppCatalogEntry, getMiniAppStatuses, onMiniAppEvent, openMiniApp, pauseMiniAppDownloads, preloadMiniApp, resumeMiniAppDownloads, sendEventToWeb, syncMiniAppCatalog, uninstallMiniApp, useMiniAppDownload, useMiniAppDownloadsPaused };
457
+ export { DefaultMiniAppSplash, MINIAPP_PLATFORM_URL, type MiniAppBridgeOptions, type MiniAppCatalogEntry, type MiniAppCatalogItem, type MiniAppChannel, type MiniAppConfig, type MiniAppContainerProps, type MiniAppContext, type MiniAppDownloadState, type MiniAppDownloadStatus, type MiniAppDownloadTask, type MiniAppEvent, type MiniAppFileSystem, type MiniAppHandlerContext, _default as MiniAppHost, type MiniAppHostData, BridgeError as MiniAppHostError, type MiniAppHostProps, type MiniAppKeepAlive, type MiniAppLaunch, type MiniAppLocalBundle, type MiniAppManifest, type MiniAppNativeHandlers, type MiniAppPaymentRequest, type MiniAppPaymentResult, type MiniAppPermission, type MiniAppSplashProps, type MiniAppStorage, type MiniAppSyncResult, type OpenMiniAppArgs, closeMiniApp, configureMiniApp, createMmkvStorage, createRnfsFileSystem, ensureMiniApp, getLocalMiniApp, getMiniAppCatalog, getMiniAppCatalogEntry, getMiniAppStatuses, onMiniAppEvent, openMiniApp, pauseMiniApp, pauseMiniAppDownloads, preloadMiniApp, restoreMiniApp, resumeMiniApp, resumeMiniAppDownloads, sendEventToWeb, syncMiniAppCatalog, uninstallMiniApp, useMiniAppDownload, useMiniAppDownloadsPaused };
package/dist/index.d.ts CHANGED
@@ -322,9 +322,10 @@ declare const closeMiniApp: () => void;
322
322
  * Giống icon app trên iOS:
323
323
  * - queued: chờ tới lượt (icon mờ) · downloading: tải lần đầu · updating: đã có bản cũ, đang tải bản mới
324
324
  * - installed: mở được · failed: lỗi sau khi thử lại (has_local → vẫn mở bản cũ)
325
+ * - paused: app này bị pauseMiniApp(app_id) — nằm trong hàng đợi nhưng không tải tới khi resumeMiniApp
325
326
  * - uninstalling: app không còn trong list, đang xoá
326
327
  */
327
- type MiniAppDownloadStatus = 'queued' | 'downloading' | 'updating' | 'installed' | 'failed' | 'uninstalling';
328
+ type MiniAppDownloadStatus = 'queued' | 'downloading' | 'updating' | 'installed' | 'failed' | 'paused' | 'uninstalling';
328
329
  interface MiniAppDownloadState {
329
330
  status: MiniAppDownloadStatus;
330
331
  /** 0–1 khi đang tải. */
@@ -359,6 +360,11 @@ type MiniAppEvent =
359
360
  app_ids: string[];
360
361
  removed: string[];
361
362
  }
363
+ /** Sync lỗi (mạng / API / token) — catalog cũ giữ nguyên, app trong máy vẫn mở được. */
364
+ | {
365
+ type: 'sync_failed';
366
+ error: string;
367
+ }
362
368
  /** Hàng đợi chuyển dừng ↔ chạy (pauseMiniAppDownloads / resumeMiniAppDownloads). reasons = lý do còn lại. */
363
369
  | {
364
370
  type: 'pause_change';
@@ -378,20 +384,53 @@ declare const useMiniAppDownloadsPaused: () => boolean;
378
384
  declare const onMiniAppEvent: (listener: (event: MiniAppEvent) => void) => () => void;
379
385
  /** Status hiện tại của mọi mini app — đọc 1 lần khi vẽ Sảnh, sau đó nghe onMiniAppEvent. */
380
386
  declare const getMiniAppStatuses: () => Record<string, MiniAppDownloadState>;
387
+ type MiniAppSyncResult = {
388
+ ok: true;
389
+ app_ids: string[];
390
+ removed: string[];
391
+ } | {
392
+ ok: false;
393
+ error: string;
394
+ };
381
395
  /**
382
396
  * Lấy list mini app (theo config.channels — kênh đứng trước được ưu tiên) → cập nhật catalog
383
- * → cho app khác version vào hàng đợi. Lỗi mạng → giữ catalog cũ, không xoá gì.
397
+ * → cho app khác version vào hàng đợi. Lỗi mạng → giữ catalog cũ, không xoá gì, bắn sync_failed.
398
+ * Không bao giờ reject — kết quả trả về giống event sync_complete / sync_failed.
384
399
  */
385
- declare const syncMiniAppCatalog: () => Promise<void>;
400
+ declare const syncMiniAppCatalog: () => Promise<MiniAppSyncResult>;
386
401
  /**
387
- * Gỡ mini app khỏi máy: bỏ khỏi hàng đợi, huỷ lượt tải đang chạy, xoá bundle, huỷ WebView (trừ khi
388
- * đang mở). syncMiniAppCatalog tự gọi cho app không còn trong list; app còn trong list → lần sync sau tải lại.
402
+ * Người dùng gỡ mini app: bỏ khỏi hàng đợi, huỷ lượt tải đang chạy, xoá bundle, huỷ WebView (trừ khi
403
+ * đang mở). Ghi nhớ (storage) → sync không tải lại; tải lại bằng restoreMiniApp / người dùng bấm mở.
389
404
  */
390
405
  declare const uninstallMiniApp: (app_id: string) => Promise<void>;
406
+ /**
407
+ * Tải lại app người dùng đã gỡ (vd màn "Thêm app"): bỏ ghi nhớ đã gỡ → vào hàng đợi (`queued`).
408
+ * false: app không có trong list (chưa sync / admin đã tắt).
409
+ */
410
+ declare const restoreMiniApp: (app_id: string) => boolean;
411
+ /**
412
+ * Pause riêng 1 app: đang tải → huỷ (tải lại từ đầu khi resume), đang chờ → `paused`, chưa cần tải →
413
+ * nhớ lại, bản mới ở lần sync sau cũng `paused`. App khác vẫn tải bình thường. Người dùng bấm mở → tải luôn.
414
+ * Lưu storage: thoát app mở lại vẫn pause, chỉ tải khi resumeMiniApp / người dùng bấm mở / gỡ app.
415
+ */
416
+ declare const pauseMiniApp: (app_id: string) => void;
417
+ /** Gỡ pause riêng của app → đang chờ thì về `queued` và hàng đợi chạy tiếp. */
418
+ declare const resumeMiniApp: (app_id: string) => void;
391
419
  /** Dừng hàng đợi vì `reason`. File đang tải (không phải do người dùng mở) bị huỷ, tải lại sau. */
392
420
  declare const pauseMiniAppDownloads: (reason: string) => void;
393
421
  /** Gỡ lý do dừng; hết lý do → chạy tiếp. */
394
422
  declare const resumeMiniAppDownloads: (reason: string) => void;
423
+ type MiniAppCatalogItem = MiniAppCatalogEntry & {
424
+ /** Máy đang có 1 bản (có thể cũ). */
425
+ installed: boolean;
426
+ /** Người dùng đã tự gỡ — sync không tải lại, chỉ tải khi restoreMiniApp. */
427
+ removed_by_user: boolean;
428
+ };
429
+ /**
430
+ * Mọi app trong list ứng dụng (lần sync gần nhất) kèm trạng thái — đọc đồng bộ, không gọi mạng.
431
+ * Dùng cho màn "Thêm app": lọc `!installed || removed_by_user`, tìm theo `name`, chọn → restoreMiniApp.
432
+ */
433
+ declare const getMiniAppCatalog: () => MiniAppCatalogItem[];
395
434
  /** app_id có trong catalog ứng dụng (đã phát hành) — đọc sync, không gọi mạng. */
396
435
  declare const getMiniAppCatalogEntry: (app_id: string) => MiniAppCatalogEntry | undefined;
397
436
  /**
@@ -415,4 +454,4 @@ declare class BridgeError extends Error {
415
454
  constructor(code: string, message: string);
416
455
  }
417
456
 
418
- export { DefaultMiniAppSplash, MINIAPP_PLATFORM_URL, type MiniAppBridgeOptions, type MiniAppCatalogEntry, type MiniAppChannel, type MiniAppConfig, type MiniAppContainerProps, type MiniAppContext, type MiniAppDownloadState, type MiniAppDownloadStatus, type MiniAppDownloadTask, type MiniAppEvent, type MiniAppFileSystem, type MiniAppHandlerContext, _default as MiniAppHost, type MiniAppHostData, BridgeError as MiniAppHostError, type MiniAppHostProps, type MiniAppKeepAlive, type MiniAppLaunch, type MiniAppLocalBundle, type MiniAppManifest, type MiniAppNativeHandlers, type MiniAppPaymentRequest, type MiniAppPaymentResult, type MiniAppPermission, type MiniAppSplashProps, type MiniAppStorage, type OpenMiniAppArgs, closeMiniApp, configureMiniApp, createMmkvStorage, createRnfsFileSystem, ensureMiniApp, getLocalMiniApp, getMiniAppCatalogEntry, getMiniAppStatuses, onMiniAppEvent, openMiniApp, pauseMiniAppDownloads, preloadMiniApp, resumeMiniAppDownloads, sendEventToWeb, syncMiniAppCatalog, uninstallMiniApp, useMiniAppDownload, useMiniAppDownloadsPaused };
457
+ export { DefaultMiniAppSplash, MINIAPP_PLATFORM_URL, type MiniAppBridgeOptions, type MiniAppCatalogEntry, type MiniAppCatalogItem, type MiniAppChannel, type MiniAppConfig, type MiniAppContainerProps, type MiniAppContext, type MiniAppDownloadState, type MiniAppDownloadStatus, type MiniAppDownloadTask, type MiniAppEvent, type MiniAppFileSystem, type MiniAppHandlerContext, _default as MiniAppHost, type MiniAppHostData, BridgeError as MiniAppHostError, type MiniAppHostProps, type MiniAppKeepAlive, type MiniAppLaunch, type MiniAppLocalBundle, type MiniAppManifest, type MiniAppNativeHandlers, type MiniAppPaymentRequest, type MiniAppPaymentResult, type MiniAppPermission, type MiniAppSplashProps, type MiniAppStorage, type MiniAppSyncResult, type OpenMiniAppArgs, closeMiniApp, configureMiniApp, createMmkvStorage, createRnfsFileSystem, ensureMiniApp, getLocalMiniApp, getMiniAppCatalog, getMiniAppCatalogEntry, getMiniAppStatuses, onMiniAppEvent, openMiniApp, pauseMiniApp, pauseMiniAppDownloads, preloadMiniApp, restoreMiniApp, resumeMiniApp, resumeMiniAppDownloads, sendEventToWeb, syncMiniAppCatalog, uninstallMiniApp, useMiniAppDownload, useMiniAppDownloadsPaused };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var $t=Object.create;var ae=Object.defineProperty;var Nt=Object.getOwnPropertyDescriptor;var Ft=Object.getOwnPropertyNames;var Bt=Object.getPrototypeOf,Jt=Object.prototype.hasOwnProperty;var Vt=(e,t)=>{for(var n in t)ae(e,n,{get:t[n],enumerable:!0})},We=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ft(t))!Jt.call(e,s)&&s!==n&&ae(e,s,{get:()=>t[s],enumerable:!(r=Nt(t,s))||r.enumerable});return e};var je=(e,t,n)=>(n=e!=null?$t(Bt(e)):{},We(t||!e||!e.__esModule?ae(n,"default",{value:e,enumerable:!0}):n,e)),Wt=e=>We(ae({},"__esModule",{value:!0}),e);var rn={};Vt(rn,{DefaultMiniAppSplash:()=>Le,MINIAPP_PLATFORM_URL:()=>pe,MiniAppHost:()=>Rt,MiniAppHostError:()=>b,closeMiniApp:()=>Y,configureMiniApp:()=>qe,createMmkvStorage:()=>ze,createRnfsFileSystem:()=>Ke,ensureMiniApp:()=>_e,getLocalMiniApp:()=>T,getMiniAppCatalogEntry:()=>Ie,getMiniAppStatuses:()=>_t,onMiniAppEvent:()=>yt,openMiniApp:()=>mt,pauseMiniAppDownloads:()=>St,preloadMiniApp:()=>At,resumeMiniAppDownloads:()=>bt,sendEventToWeb:()=>ft,syncMiniAppCatalog:()=>ye,uninstallMiniApp:()=>ke,useMiniAppDownload:()=>Me,useMiniAppDownloadsPaused:()=>Mt});module.exports=Wt(rn);var pe="https://retion-miniapp-platform.vercel.app",q=null,He=new Set,qe=e=>{q=e,He.forEach(t=>t())},E=()=>{if(!q)throw new Error("[miniapp] Ch\u01B0a g\u1ECDi configureMiniApp()");return q},Ue=e=>{He.add(e),q&&e()},F=(...e)=>{q!=null&&q.debug&&console.log("[miniapp]",...e)};var Ke=(e,t)=>({document_dir:e.DocumentDirectoryPath,cache_dir:e.CachesDirectoryPath,exists:n=>e.exists(n),mkdir:n=>e.mkdir(n),remove:n=>e.unlink(n).catch(()=>{}),listDir:n=>e.readDir(n).then(r=>r.map(s=>s.name)).catch(()=>[]),sha256:n=>e.hash(n,"sha256"),unzip:async(n,r)=>{await t(n,r)},download:({url:n,to_file:r,onProgress:s})=>{let{jobId:o,promise:c}=e.downloadFile({fromUrl:n,toFile:r,progressInterval:250,begin:()=>{},progress:({bytesWritten:u,contentLength:a})=>s==null?void 0:s(u,a)});return{promise:c.then(({statusCode:u})=>({status:u})),cancel:()=>e.stopDownload(o)}}}),ze=e=>({getString:t=>e.getString(t),setString:(t,n)=>e.set(t,n)});var l=je(require("react")),w=require("react-native"),Tt=je(require("react-native-webview"));var ce=require("react-native"),le=1,b=class extends Error{constructor(n,r){super(r);this.code=n}},Ye=e=>{try{let t=JSON.parse(e);return(t==null?void 0:t.__retion)===le&&typeof t.method=="string"?t:null}catch{return null}},ue=e=>`window.__RETION_MINIAPP__ && window.__RETION_MINIAPP__.receive(${JSON.stringify(e)}); true;`,Ge=(e,t)=>ue({id:e,result:t}),Xe=(e,t)=>ue({id:e,error:{code:t.code,message:t.message}}),Ee=e=>ue({event:"context",data:e});var Ze=()=>`(function () {
1
+ "use strict";var qt=Object.create;var le=Object.defineProperty;var Ht=Object.getOwnPropertyDescriptor;var Ut=Object.getOwnPropertyNames;var Kt=Object.getPrototypeOf,zt=Object.prototype.hasOwnProperty;var Yt=(e,t)=>{for(var n in t)le(e,n,{get:t[n],enumerable:!0})},qe=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ut(t))!zt.call(e,s)&&s!==n&&le(e,s,{get:()=>t[s],enumerable:!(r=Ht(t,s))||r.enumerable});return e};var He=(e,t,n)=>(n=e!=null?qt(Kt(e)):{},qe(t||!e||!e.__esModule?le(n,"default",{value:e,enumerable:!0}):n,e)),Qt=e=>qe(le({},"__esModule",{value:!0}),e);var fn={};Yt(fn,{DefaultMiniAppSplash:()=>Ne,MINIAPP_PLATFORM_URL:()=>ue,MiniAppHost:()=>$t,MiniAppHostError:()=>E,closeMiniApp:()=>ee,configureMiniApp:()=>Ke,createMmkvStorage:()=>Qe,createRnfsFileSystem:()=>Ye,ensureMiniApp:()=>xe,getLocalMiniApp:()=>T,getMiniAppCatalog:()=>kt,getMiniAppCatalogEntry:()=>ae,getMiniAppStatuses:()=>bt,onMiniAppEvent:()=>_t,openMiniApp:()=>Mt,pauseMiniApp:()=>Rt,pauseMiniAppDownloads:()=>Ct,preloadMiniApp:()=>wt,restoreMiniApp:()=>Tt,resumeMiniApp:()=>Pt,resumeMiniAppDownloads:()=>Ot,sendEventToWeb:()=>At,syncMiniAppCatalog:()=>be,uninstallMiniApp:()=>Et,useMiniAppDownload:()=>Se,useMiniAppDownloadsPaused:()=>St});module.exports=Qt(fn);var ue="https://retion-miniapp-platform.vercel.app",Q=null,Ue=new Set,Ke=e=>{Q=e,Ue.forEach(t=>t())},x=()=>{if(!Q)throw new Error("[miniapp] Ch\u01B0a g\u1ECDi configureMiniApp()");return Q},ze=e=>{Ue.add(e),Q&&e()},J=(...e)=>{Q!=null&&Q.debug&&console.log("[miniapp]",...e)};var Ye=(e,t)=>({document_dir:e.DocumentDirectoryPath,cache_dir:e.CachesDirectoryPath,exists:n=>e.exists(n),mkdir:n=>e.mkdir(n),remove:n=>e.unlink(n).catch(()=>{}),listDir:n=>e.readDir(n).then(r=>r.map(s=>s.name)).catch(()=>[]),sha256:n=>e.hash(n,"sha256"),unzip:async(n,r)=>{await t(n,r)},download:({url:n,to_file:r,onProgress:s})=>{let{jobId:o,promise:l}=e.downloadFile({fromUrl:n,toFile:r,progressInterval:250,begin:()=>{},progress:({bytesWritten:i,contentLength:p})=>s==null?void 0:s(i,p)});return{promise:l.then(({statusCode:i})=>({status:i})),cancel:()=>e.stopDownload(o)}}}),Qe=e=>({getString:t=>e.getString(t),setString:(t,n)=>e.set(t,n)});var u=He(require("react")),w=require("react-native"),Lt=He(require("react-native-webview"));var de=require("react-native"),ge=1,E=class extends Error{constructor(n,r){super(r);this.code=n}},Xe=e=>{try{let t=JSON.parse(e);return(t==null?void 0:t.__retion)===ge&&typeof t.method=="string"?t:null}catch{return null}},fe=e=>`window.__RETION_MINIAPP__ && window.__RETION_MINIAPP__.receive(${JSON.stringify(e)}); true;`,Ze=(e,t)=>fe({id:e,result:t}),et=(e,t)=>fe({id:e,error:{code:t.code,message:t.message}}),Ce=e=>fe({event:"context",data:e});var tt=()=>`(function () {
2
2
  var post = function (level, args) {
3
3
  try {
4
4
  var parts = [];
@@ -8,7 +8,7 @@
8
8
  else if (typeof a === 'object') { try { parts.push(JSON.stringify(a).slice(0, 800)); } catch (e) { parts.push(String(a)); } }
9
9
  else { parts.push(String(a)); }
10
10
  }
11
- window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${le}, method: 'log', level: level, text: parts.join(' ') }));
11
+ window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${ge}, method: 'log', level: level, text: parts.join(' ') }));
12
12
  } catch (e) {}
13
13
  };
14
14
  ['log', 'info', 'warn', 'error'].forEach(function (level) {
@@ -19,7 +19,7 @@
19
19
  window.addEventListener('unhandledrejection', function (e) { post('error', ['[unhandledrejection]', e.reason]); });
20
20
  // Kh\xF4ng log query (c\xF3 th\u1EC3 ch\u1EE9a token) \u2014 ch\u1EC9 \u0111\u01B0\u1EDDng d\u1EABn + route.
21
21
  post('info', ['[page] ' + location.pathname + location.hash]);
22
- })(); true;`,et=()=>`(function () {
22
+ })(); true;`,nt=()=>`(function () {
23
23
  function atTop(el) {
24
24
  for (var n = el; n && n !== document.documentElement; n = n.parentElement) {
25
25
  if (n.scrollTop > 0) { return false; }
@@ -30,7 +30,7 @@
30
30
  function report(at_top) {
31
31
  if (at_top === last) { return; }
32
32
  last = at_top;
33
- window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${le}, method: 'touchAtTop', at_top: at_top }));
33
+ window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${ge}, method: 'touchAtTop', at_top: at_top }));
34
34
  }
35
35
  document.addEventListener('touchstart', function (e) { report(atTop(e.target)); }, { capture: true, passive: true });
36
36
  // Cu\u1ED9n r\u1EDDi \u0111\u1EA7u trang \u2192 b\xE1o ngay, kh\xF4ng \u0111\u1EE3i l\u1EA7n ch\u1EA1m sau (tr\xE1nh host d\xF9ng gi\xE1 tr\u1ECB c\u0169 "\u0111ang \u1EDF \u0111\u1EA7u").
@@ -38,8 +38,8 @@
38
38
  var el = e.target === document ? document.documentElement : e.target;
39
39
  if (el && el.scrollTop > 0) { report(false); }
40
40
  }, { capture: true, passive: true });
41
- })(); true;`,tt=e=>ue({event:e}),nt=(e,t)=>{let n=rt(t);return`try { history.replaceState(history.state, '', location.pathname + ${JSON.stringify(n?`?${n}`:"")} + location.hash); } catch (e) {}
42
- ${Ee(e)}`},rt=e=>Object.entries(e).filter(([,t])=>t!=null&&t!=="").map(([t,n])=>`${encodeURIComponent(t)}=${encodeURIComponent(String(n))}`).join("&"),ot=(e,t={})=>{let n=rt(t);return`window.__RETION_MINIAPP_HOST__ = { protocol: ${le} };
41
+ })(); true;`,rt=e=>fe({event:e}),ot=(e,t)=>{let n=st(t);return`try { history.replaceState(history.state, '', location.pathname + ${JSON.stringify(n?`?${n}`:"")} + location.hash); } catch (e) {}
42
+ ${Ce(e)}`},st=e=>Object.entries(e).filter(([,t])=>t!=null&&t!=="").map(([t,n])=>`${encodeURIComponent(t)}=${encodeURIComponent(String(n))}`).join("&"),it=(e,t={})=>{let n=st(t);return`window.__RETION_MINIAPP_HOST__ = { protocol: ${ge} };
43
43
  window.__RETION_MINIAPP_CONTEXT__ = ${JSON.stringify(e)};
44
44
  ${n?`try { history.replaceState(history.state, '', location.pathname + '?' + ${JSON.stringify(n)} + location.hash); } catch (e) {}`:""}
45
- true;`},it={partner:"partner_token",chatbox:"chatbox_token"},st=(e,t)=>{let n={...e};for(let r of Object.values(it))t.includes(r)||delete n[r];return n},be=new Set,Qe=async(e,t)=>{if(be.has(e))throw new b("BUSY",`${e} \u0111ang ch\u1EA1y \u2014 ch\u1EDD l\u01B0\u1EE3t tr\u01B0\u1EDBc xong`);be.add(e);try{return await t()}finally{be.delete(e)}},xe=(e,t)=>{if(typeof e!="string"||!e)throw new b("INVALID_PARAMS",`Thi\u1EBFu ${t}`);return e},at=async({method:e,params:t},{getHostData:n,getPermissions:r,is_dark:s,close:o,app_id:c,instance_id:u,options:a})=>{var A,g,I,v;let h=a==null?void 0:a.handlers,m={app_id:c,instance_id:u,close:o},M=()=>new b("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF \u1EE9ng d\u1EE5ng n\xE0y`);switch(e){case"requestPayment":{let d=h==null?void 0:h.requestPayment;if(!d)throw M();let i=t==null?void 0:t.amount;if(typeof i!="number"||!Number.isFinite(i)||i<=0)throw new b("INVALID_PARAMS","amount ph\u1EA3i l\xE0 s\u1ED1 > 0");let x={...t,amount:i,currency:xe(t==null?void 0:t.currency,"currency")};return Qe(e,()=>d(x,m))}case"printImage":{let d=h==null?void 0:h.printImage;if(!d)throw M();let i=xe(t==null?void 0:t.image,"image");await Qe(e,()=>d({image:i},m));return}case"openScreen":if(!(h!=null&&h.openScreen))throw M();await h.openScreen({screen:xe(t==null?void 0:t.screen,"screen"),params:t==null?void 0:t.params},m);return;case"closeApp":o();return;case"openWebview":{let d=String((A=t==null?void 0:t.url)!=null?A:"");if(!/^https?:\/\//i.test(d))throw new b("INVALID_PARAMS","url ph\u1EA3i l\xE0 http(s)");await(a!=null&&a.openUrl?a.openUrl(d):ce.Linking.openURL(d));return}case"showToast":(I=a==null?void 0:a.showToast)==null||I.call(a,String((g=t==null?void 0:t.message)!=null?g:""));return;case"getSystemInfo":return{platform:ce.Platform.OS==="ios"?"ios":"android",appVersion:(v=a==null?void 0:a.app_version)!=null?v:"",theme:s?"dark":"light"};case"getAccessToken":{let d=n().access_token;if(!d)throw new b("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return d}case"getToken":{let d=t==null?void 0:t.type;if(d==="access"){let V=n().access_token;if(!V)throw new b("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return V}if(d!=="partner"&&d!=="chatbox")throw new b("HOST_ERROR",`Lo\u1EA1i token kh\xF4ng h\u1EE3p l\u1EC7: ${String(d)}`);let i=it[d];if(!r().includes(i))throw new b("PERMISSION_DENIED",`Mini app ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5p quy\u1EC1n ${i} (Console \u2192 Quy\u1EC1n l\u1EA5y token)`);let x=d==="partner"?n().partner_token:n().chatbox_token;if(!x)throw new b("HOST_ERROR",`Kh\xF4ng c\xF3 ${i}`);return x}case"getUserInfo":{let d=n().user;if(!d)throw new b("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin nh\xE2n vi\xEAn");return d}case"getPageInfo":{let d=n().page;if(!d)throw new b("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin page");return d}case"sendMessage":case"insertText":throw new b("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF phi\xEAn b\u1EA3n app n\xE0y`);default:throw new b("NOT_SUPPORTED",`API kh\xF4ng t\u1ED3n t\u1EA1i: ${e}`)}};var Te=e=>`bundle:${e}`,Re=()=>`${E().file_system.document_dir}/miniapps`,lt=(e,t,n="index.html",r=!1,s=[])=>{let o=`${Re()}/${e}/${t}`;return{app_id:e,version:t,dir:o,entry_uri:`file://${o}/${n}`,context_update:r,permissions:s}},pt=e=>{var t;E().storage.setString(Te(e.app_id),JSON.stringify({version:e.version,entry:e.entry,context_update:!!e.context_update,permissions:(t=e.permissions)!=null?t:[]}))},jt=(e,t)=>/^https?:\/\//.test(t)?t:`${e.replace(/[^/]*$/,"")}${t}`,T=e=>{let t=E().storage.getString(Te(e));if(!t)return null;try{let{version:n,entry:r,context_update:s,permissions:o}=JSON.parse(t);return lt(e,n,r,!!s,Array.isArray(o)?o:[])}catch{return null}},de=e=>E().file_system.exists(e.entry_uri.replace("file://","")),Pe=async e=>{let t=T(e.app_id);return(t==null?void 0:t.version)===e.version&&await de(t)},Ht=async(e,t)=>{let n=E().file_system,r=`${Re()}/${e}`,s=await n.listDir(r).catch(()=>[]);await Promise.all(s.filter(o=>!t.includes(o)).map(o=>n.remove(`${r}/${o}`).catch(()=>{})))},ut=async e=>{var t;await((t=re[e])==null?void 0:t.catch(()=>{})),E().storage.setString(Te(e),""),await E().file_system.remove(`${Re()}/${e}`).catch(()=>{})},Q=class extends Error{constructor(){super("cancelled"),this.name="MiniAppInstallCancelled"}},re={},Ce=(e,{base_url:t,onProgress:n}={})=>{var A;let r=E().file_system,s=null,o=!1,c=`${r.cache_dir}/${e.app_id}-${e.version}.zip`,u=()=>{if(o)throw new Q},a=async()=>{var v;u();let g=T(e.app_id);if((g==null?void 0:g.version)===e.version&&await r.exists(g.dir))return pt(e),T(e.app_id);u();let I=r.download({url:t?jt(t,e.bundle_url):e.bundle_url,to_file:c,onProgress:(d,i)=>{var V;let x=i>0?i:(V=e.size)!=null?V:0;x>0&&(n==null||n(Math.min(1,d/x)))}});s=I;try{let{status:d}=await I.promise;if(u(),d!==200)throw new Error(`bundle ${d}`);if(e.sha256)if(r.sha256){if(await r.sha256(c)!==e.sha256)throw new Error("sha256 mismatch")}else F("b\u1ECF qua ki\u1EC3m tra sha256 (file_system kh\xF4ng c\xF3 sha256)",e.app_id);u();let i=lt(e.app_id,e.version,e.entry,!!e.context_update,(v=e.permissions)!=null?v:[]);return await r.remove(i.dir).catch(()=>{}),await r.mkdir(i.dir),await r.unzip(c,i.dir),pt(e),Ht(e.app_id,[e.version,g==null?void 0:g.version].filter(Boolean)),i}catch(d){throw o?new Q:d}finally{s=null,r.remove(c).catch(()=>{})}},m=((A=re[e.app_id])!=null?A:Promise.resolve()).catch(()=>{}).then(a),M=m.catch(()=>{});return re[e.app_id]=M,M.then(()=>{re[e.app_id]===M&&delete re[e.app_id]}),{promise:m,cancel:()=>{o=!0,s==null||s.cancel()}}},ne={},qt=__DEV__?0:60*1e3,ct={},dt=(e,t)=>{var r,s;let n=T(e);return n&&Date.now()-((r=ct[t])!=null?r:0)<qt?Promise.resolve(n):((s=ne[e])!=null||(ne[e]=(async()=>{let o=await fetch(t,{headers:{"Cache-Control":"no-cache"}});if(!o.ok)throw new Error(`manifest ${o.status}`);let c=await o.json(),u=await Ce(c,{base_url:t}).promise;return ct[t]=Date.now(),u})().catch(o=>(console.warn("[miniapp] sync failed",e,o==null?void 0:o.message),T(e))).finally(()=>{ne[e]=void 0})),ne[e])};var ge=new Map,gt=(e,t)=>(ge.set(e,t),()=>{ge.get(e)===t&&ge.delete(e)}),ft=(e,t)=>{let n=ge.get(e);return n?n(t):!1};var fe=require("react"),he=e=>{let t=e,n=new Set;return{getState:()=>t,setState:r=>{let s=typeof r=="function"?r(t):r;t={...t,...s},n.forEach(o=>o())},subscribe:r=>(n.add(r),()=>{n.delete(r)})}},B=(e,t,n=Object.is)=>{let r=(0,fe.useRef)(null),s=()=>{let o=e.getState(),c=r.current;if(c&&c.state===o&&c.selector===t)return c.value;let u=t(o),a=c&&n(c.value,u)?c.value:u;return r.current={state:o,selector:t,value:a},a};return(0,fe.useSyncExternalStore)(e.subscribe,s)};var $=he({active_key:null,instances:{}}),ht=({app:e,instance_id:t,context:n={},url_params:r={},host_data:s={}},o)=>{var u;let c=(u=E().keep_alive)==null?void 0:u.max_webviews;$.setState(a=>{let h=t!=null?t:e.app_id,m={...a.instances,[h]:{key:h,app:e,context:n,url_params:r,host_data:s,last_used_at:Date.now()}},M=Object.keys(m);return c&&c>0&&M.length>c&&M.filter(A=>A!==h).sort((A,g)=>m[A].last_used_at-m[g].last_used_at).slice(0,M.length-c).forEach(A=>{delete m[A]}),o?{active_key:h,instances:m}:{instances:m}})},mt=e=>ht(e,!0),At=e=>ht(e,!1),Y=()=>$.setState({active_key:null}),me=e=>{$.setState(t=>{if(t.active_key===e||!t.instances[e])return{};let n={...t.instances};return delete n[e],{instances:n}})};var wt="catalog",Ut=10*1e3,Kt=2,zt=3e3,Qt=()=>{var e;try{return JSON.parse((e=E().storage.getString(wt))!=null?e:"{}")}catch{return{}}},R=he({catalog:{},downloads:{},pause_reasons:[]});Ue(()=>R.setState({catalog:Qt()}));var Me=e=>B(R,t=>e?t.downloads[e]:void 0),Mt=()=>B(R,e=>e.pause_reasons.length>0),K=(...e)=>F("queue",...e),P=[],U={},_=null,Ae=new Set,z={},Oe=new Set,X=e=>{Oe.forEach(t=>{try{t(e)}catch(n){console.warn("[miniapp-queue] event listener error",n==null?void 0:n.message)}})},yt=e=>(Oe.add(e),()=>{Oe.delete(e)}),_t=()=>R.getState().downloads,J=(e,t)=>{let n=!!T(e),r=R.getState().downloads[e],s=t.status==="downloading"&&n?"updating":t.status,o={...r!=null?r:{status:"queued",progress:0},...t,...s?{status:s}:{},has_local:n};R.setState(c=>({downloads:{...c.downloads,[e]:o}})),(r==null?void 0:r.status)!==o.status||(r==null?void 0:r.version)!==o.version||(r==null?void 0:r.has_local)!==o.has_local?X({type:"status_change",app_id:e,state:o}):r.progress!==o.progress&&X({type:"progress",app_id:e,progress:o.progress,version:o.version})},we=(e,t)=>{var n;(n=z[e])==null||n.forEach(r=>r(t)),delete z[e]},Yt=()=>R.getState().pause_reasons.length>0,G=e=>{var u;if(_)return;let t=e?P.indexOf(e):Yt()?-1:0;if(t<0||t>=P.length)return;let[n]=P.splice(t,1),r=R.getState().catalog[n];if(!r){we(n,T(n)),G();return}let s=Date.now();U[n]=((u=U[n])!=null?u:0)+1,J(n,{status:"downloading",progress:0,version:r.version,error:void 0});let o=0,c=Ce(r,{onProgress:a=>{let h=Math.floor(a*100);h!==o&&(o=h,J(n,{progress:h/100,version:r.version}))}});_={app_id:n,handle:c,forced:!!e},K("start",n,r.version,e?"(forced)":""),c.promise.then(a=>{K("installed",n,r.version,`${Date.now()-s}ms`),J(n,{status:"installed",progress:1,version:r.version}),we(n,a)}).catch(a=>{var m;if(a instanceof Q){if(Ae.has(n))return;K("paused",n),U[n]-=1,P.unshift(n),J(n,{status:"queued",progress:0,version:r.version});return}let h=String((m=a==null?void 0:a.message)!=null?m:a);if(console.warn("[miniapp-queue] failed",n,h),U[n]<Kt){J(n,{status:"queued",progress:0,version:r.version,error:h}),setTimeout(()=>{var M;P.includes(n)||(_==null?void 0:_.app_id)===n||(P.push(n),G((M=z[n])!=null&&M.length?n:void 0))},zt);return}J(n,{status:"failed",progress:0,version:r.version,error:h}),we(n,T(n))}).finally(()=>{_=null;let a=P.find(h=>{var m;return(m=z[h])==null?void 0:m.length});G(a)})},vt=(e,{front:t=!1}={})=>{if((_==null?void 0:_.app_id)===e)return;let n=P.indexOf(e);if(n>=0){if(!t)return;P.splice(n,1)}t?P.unshift(e):P.push(e)},Gt=async e=>{let{host_id:t,client_token:n}=E(),r=new AbortController,s=setTimeout(()=>r.abort(),Ut);try{let o=`${pe}/api/hosts/${encodeURIComponent(t)}/miniapps?channel=${e}`,c=await fetch(o,{headers:{Authorization:`Bearer ${n}`,"Cache-Control":"no-cache"},signal:r.signal});if(!c.ok)throw new Error(`host list ${e} ${c.status}`);return(await c.json()).apps.map(a=>({...a,channel:e}))}finally{clearTimeout(s)}},oe=null,ye=()=>(oe!=null||(oe=(async()=>{let e=Date.now();try{let t=await Promise.all(E().channels.map(Gt)),n={};[...t].reverse().flat().forEach(o=>{n[o.app_id]=o});let r=Object.keys(R.getState().catalog).filter(o=>!n[o]);E().storage.setString(wt,JSON.stringify(n)),R.setState({catalog:n}),await Promise.all(r.map(ke));let s=[];for(let o of Object.values(n))await Pe(o)?J(o.app_id,{status:"installed",progress:1,version:o.version}):s.push(o);s.forEach(o=>{U[o.app_id]=0,J(o.app_id,{status:"queued",progress:0,version:o.version,error:void 0}),vt(o.app_id)}),K("catalog",Object.keys(n).length,"apps, outdated",s.map(o=>o.app_id),"removed",r,`${Date.now()-e}ms`),X({type:"sync_complete",app_ids:Object.keys(n),removed:r}),G()}catch(t){console.warn("[miniapp-queue] sync catalog failed",t==null?void 0:t.message)}finally{oe=null}})()),oe),ke=async e=>{var r,s,o,c;if(Ae.has(e))return;Ae.add(e);let t=P.indexOf(e);t>=0&&P.splice(t,1),(_==null?void 0:_.app_id)===e&&_.handle.cancel();let n=(c=(o=(r=R.getState().downloads[e])==null?void 0:r.version)!=null?o:(s=T(e))==null?void 0:s.version)!=null?c:"";J(e,{status:"uninstalling",progress:0,version:n}),await ut(e),me(e),R.setState(u=>{let a={...u.downloads};return delete a[e],{downloads:a}}),delete U[e],Ae.delete(e),we(e,null),K("uninstalled",e),X({type:"uninstalled",app_id:e})},St=e=>{let{pause_reasons:t}=R.getState();t.includes(e)||(R.setState({pause_reasons:[...t,e]}),K("pause",e),t.length===0&&X({type:"pause_change",paused:!0,reasons:[e]}),_&&!_.forced&&_.handle.cancel())},bt=e=>{let{pause_reasons:t}=R.getState();if(!t.includes(e))return;let n=t.filter(r=>r!==e);R.setState({pause_reasons:n}),K("resume",e),n.length===0&&X({type:"pause_change",paused:!1,reasons:n}),G()},Ie=e=>R.getState().catalog[e],_e=async e=>{let t=Ie(e);if(!t)return;if(await Pe(t))return T(e);let n=new Promise(r=>{var s;((s=z[e])!=null?s:z[e]=[]).push(r)});return(_==null?void 0:_.app_id)===e?_.forced=!0:(U[e]=0,vt(e,{front:!0}),_&&!_.forced?_.handle.cancel():G(e)),n};var y=require("react/jsx-runtime"),De=e=>(e!=null?e:"").replace(/\?[^#]*/,""),xt=0,Xt=()=>{let e=new Set;return{emit:t=>e.forEach(n=>n(t)),subscribe:t=>(e.add(t),()=>{e.delete(t)})}},Zt=l.default.memo(({instance_key:e,is_active:t,is_front:n,is_dark:r,reload_tick:s,web_at_top:o,splash:c,bridge:u,opaque_background:a,onWebLoadEnd:h})=>{var Je,Ve;let m=(0,l.useRef)(null),M=(0,l.useRef)(!1),A=B($,p=>p.instances[e]),g=A==null?void 0:A.app.app_id,I=A==null?void 0:A.app.manifest_url,v=A==null?void 0:A.context,d=A==null?void 0:A.url_params,[i,x]=(0,l.useState)(()=>g?T(g):null),[V,Z]=(0,l.useState)(!1),[Pt,$e]=(0,l.useState)(0),[Ct,ee]=(0,l.useState)(0),[Ot,D]=(0,l.useState)(!1),N=(0,l.useRef)(null),Ne=p=>{N.current&&clearTimeout(N.current),N.current=setTimeout(()=>{N.current=null,D(!0)},p)};(0,l.useEffect)(()=>()=>{N.current&&clearTimeout(N.current)},[]),(0,l.useEffect)(()=>{if(!g||!t&&i)return;let p=!0;return Z(!1),(async()=>{let f=T(g),C=f?await de(f):!1;if(!p||(x(C?L=>!L||L.version!==f.version||L.permissions.join(",")!==f.permissions.join(",")?f:L:null),__DEV__&&Date.now()-xt>1e4&&(xt=Date.now(),await ye()),!p))return;let W=await _e(g),j=W!==void 0?W:I?await dt(g,I):T(g);if(p){if(!j){Z(!0);return}x(L=>L!=null?L:j)}})(),()=>{p=!1}},[t,g,I,Pt]),(0,l.useEffect)(()=>gt(e,p=>m.current?(m.current.postMessage(p),!0):!1),[e]);let kt=B(R,p=>{let f=g?p.downloads[g]:void 0;return(f==null?void 0:f.status)==="installed"?f.version:void 0});(0,l.useEffect)(()=>{if(t||!g||!i)return;let p=T(g);if(!p||p.version===i.version)return;let f=!0;return de(p).then(C=>{!f||!C||(F(`webview:${e}`,"\u0111\u1ED5i bundle (\u1EA9n)",i.version,"\u2192",p.version),x(p))}),()=>{f=!1}},[t,g,kt,i==null?void 0:i.version]),(0,l.useEffect)(()=>{var C;let p=(C=E().keep_alive)==null?void 0:C.idle_close_ms;if(t||!p||p<=0)return;let f=setTimeout(()=>{me(e)},p);return()=>clearTimeout(f)},[t,e]),(0,l.useEffect)(()=>{s>0&&(Z(!1),D(!1),ee(p=>p+1),$e(p=>p+1))},[s]);let Fe=(0,l.useRef)(t);(0,l.useEffect)(()=>{var p;Fe.current!==t&&(Fe.current=t,M.current&&((p=m.current)==null||p.injectJavaScript(tt(t?"resumed":"paused"))))},[t]);let ie=`${(Je=i==null?void 0:i.version)!=null?Je:"none"}:${(Ve=i==null?void 0:i.permissions.join(","))!=null?Ve:""}:${Ct}`,te=(0,l.useMemo)(()=>JSON.stringify([v!=null?v:{},d!=null?d:{}]),[v,d]),ve=(0,l.useMemo)(()=>{var p;return st(d!=null?d:{},(p=i==null?void 0:i.permissions)!=null?p:[])},[te,i==null?void 0:i.permissions]),It=(0,l.useMemo)(()=>ot(v!=null?v:{},ve)+et()+(E().debug?Ze():""),[ve]),se=(0,l.useRef)(null),Be=(0,l.useRef)(null);(0,l.useEffect)(()=>{var f,C,W;if(!i)return;if(Be.current!==ie){Be.current=ie,se.current=te;return}if(se.current===te)return;let p=((C=JSON.parse((f=se.current)!=null?f:"[]")[0])!=null?C:{}).org_id;if(se.current=te,p===(v==null?void 0:v.org_id)&&M.current){D(!1),Ne(1500),(W=m.current)==null||W.injectJavaScript(nt(v!=null?v:{},ve));return}D(!1),ee(j=>j+1)},[te,i,ie]);let Dt=(0,l.useCallback)(async p=>{var C,W,j,L,Se;let f=Ye(p.nativeEvent.data);if(!f){if(g&&(u!=null&&u.onWebEvent))try{Promise.resolve(u.onWebEvent(p.nativeEvent.data,{app_id:g,instance_id:e})).catch(S=>{console.warn("[miniapp] onWebEvent l\u1ED7i",g,S)})}catch(S){console.warn("[miniapp] onWebEvent l\u1ED7i",g,S)}return}if(f.method==="log"){let{level:S,text:O}=f;F(`web:${e}`,S!=null?S:"log",O!=null?O:"");return}if(f.method==="pong"){N.current||D(!0);return}if(f.method==="touchAtTop"){o.emit(!!f.at_top);return}if(f.method==="contextApplied"){N.current&&clearTimeout(N.current),N.current=null,D(!0);return}if(f.method==="ready"){M.current=!0,D(!0);let S=(C=$.getState().instances[e])==null?void 0:C.context;S&&((W=m.current)==null||W.injectJavaScript(Ee(S)));return}try{let S=await at(f,{getHostData:()=>{var O,H;return(H=(O=$.getState().instances[e])==null?void 0:O.host_data)!=null?H:{}},getPermissions:()=>{var O,H;return g?(H=(O=T(g))==null?void 0:O.permissions)!=null?H:[]:[]},is_dark:r,close:Y,app_id:g!=null?g:"",instance_id:e,options:u});f.id&&((j=m.current)==null||j.injectJavaScript(Ge(f.id,S)))}catch(S){if(!f.id)return;let O=S==null?void 0:S.code,H=S instanceof b?S:new b(typeof O=="string"?O:"HOST_ERROR",String((L=S==null?void 0:S.message)!=null?L:S));(Se=m.current)==null||Se.injectJavaScript(Xe(f.id,H))}},[e,r,g,o,u]),Lt=(0,l.useCallback)(()=>{Z(!1),ee(p=>p+1),$e(p=>p+1)},[]);return(0,y.jsxs)(w.View,{style:[w.StyleSheet.absoluteFill,a&&{backgroundColor:r?"#09090B":"#FFFFFF"},!n&&k.behind],pointerEvents:t?"auto":"none",children:[i?(0,y.jsx)(Tt.default,{ref:m,source:{uri:i.entry_uri},originWhitelist:["*"],allowingReadAccessToURL:`file://${i.dir}`,allowFileAccess:!0,allowFileAccessFromFileURLs:!0,allowUniversalAccessFromFileURLs:!0,injectedJavaScriptBeforeContentLoaded:It,onMessage:Dt,bounces:!1,overScrollMode:"never",onLoadStart:p=>{F(`webview:${e}`,"load start",De(p.nativeEvent.url)),M.current=!1,D(!1)},onError:p=>{F(`webview:${e}`,"load error",De(p.nativeEvent.url),p.nativeEvent.description),Z(!0),D(!1)},onLoadEnd:p=>{let f=p.nativeEvent.url;F(`webview:${e}`,"load end",De(f)),g&&(h==null||h({app_id:g,instance_id:e,url:f})),Ne(1500)},onContentProcessDidTerminate:()=>{M.current=!1,D(!1),ee(p=>p+1)},onRenderProcessGone:()=>(M.current=!1,D(!1),ee(p=>p+1),!0),style:k.webview},ie):null,A&&(0,y.jsx)(tn,{visible:!i||!Ot,interactive:V,children:(0,y.jsx)(en,{splash:c,app:A.app,is_dark:r,error:V,has_bundle:!!i,retry:Lt})})]})}),en=l.default.memo(({splash:e,app:t,is_dark:n,error:r,has_bundle:s,retry:o})=>{let c=e,u=Me(t.app_id),a=r?"error":!s&&(u==null?void 0:u.status)==="downloading"?"downloading":"loading";return(0,y.jsx)(c,{app:t,is_dark:n,status:a,progress:a==="downloading"?u==null?void 0:u.progress:void 0,retry:o})}),tn=({visible:e,interactive:t,children:n})=>{let r=(0,l.useRef)(new w.Animated.Value(e?1:0)).current,[s,o]=(0,l.useState)(e);return(0,l.useEffect)(()=>{if(e){o(!0),r.setValue(1);return}let c=w.Animated.timing(r,{toValue:0,duration:180,useNativeDriver:!0});return c.start(({finished:u})=>{u&&o(!1)}),()=>c.stop()},[e,r]),s?(0,y.jsx)(w.Animated.View,{style:[w.StyleSheet.absoluteFill,{opacity:r}],pointerEvents:t?"auto":"none",children:n}):null},Le=({app:e,is_dark:t,status:n,progress:r,retry:s})=>{let o=t?"#FAFAFA":"#18181B";return(0,y.jsxs)(w.View,{style:[k.splash,{backgroundColor:t?"#09090B":"#FFFFFF"}],children:[(0,y.jsx)(w.View,{style:[k.splash_icon,{backgroundColor:t?"#18181B":"#F4F4F5"}],children:e.icon?(0,y.jsx)(w.Image,{source:{uri:e.icon},style:k.splash_icon_image}):(0,y.jsx)(w.Text,{style:k.splash_letter,children:(e.name||"?").slice(0,1).toUpperCase()})}),(0,y.jsx)(w.Text,{style:[k.splash_name,{color:o}],children:e.name}),n==="error"?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(w.Text,{style:k.splash_hint,children:"Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c mini app"}),(0,y.jsx)(w.TouchableOpacity,{activeOpacity:.7,style:[k.retry_button,{backgroundColor:t?"#27272A":"#F4F4F5"}],onPress:s,children:(0,y.jsx)(w.Text,{style:[k.retry_text,{color:o}],children:"Th\u1EED l\u1EA1i"})})]}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(w.ActivityIndicator,{style:k.splash_spinner,color:t?"#A1A1AA":"#71717A"}),n==="downloading"&&(0,y.jsxs)(w.Text,{style:k.splash_hint,children:["\u0110ang t\u1EA3i mini app",r?` ${Math.round(r*100)}%`:"\u2026"]})]})]})},Et=(e,t)=>{let n=(0,l.useRef)(t),r=(0,l.useRef)(!1);__DEV__&&!r.current&&n.current!==t&&(r.current=!0,console.warn(`[miniapp] MiniAppHost prop "${e}" \u0111\u1ED5i gi\u1EEFa c\xE1c l\u1EA7n render \u2192 m\u1ECDi WebView b\u1ECB mount l\u1EA1i. Khai b\xE1o component b\xEAn ngo\xE0i render.`))},nn=({container:e,splash:t=Le,is_dark:n=!1,bridge:r,close_on_back:s=!0,opaque_background:o=!0,onWebLoadEnd:c})=>{Et("container",e),Et("splash",t);let u=e,a=B($,i=>i.active_key),h=(0,l.useRef)(a);a&&(h.current=a);let m=B($,i=>Object.keys(i.instances).join("|")),M=B($,i=>{var x;return i.active_key?(x=i.instances[i.active_key])==null?void 0:x.app.name:void 0}),A=(0,l.useMemo)(()=>m?m.split("|"):[],[m]),[g,I]=(0,l.useState)({}),v=(0,l.useRef)(Xt()).current;(0,l.useEffect)(()=>{if(!a||!s)return;let i=w.BackHandler.addEventListener("hardwareBackPress",()=>(Y(),!0));return()=>i.remove()},[a,s]);let d=(0,l.useCallback)(()=>{let i=$.getState().active_key;i&&I(x=>({...x,[i]:(x[i]||0)+1}))},[]);return A.length?(0,y.jsx)(u,{visible:!!a,title:M!=null?M:"",is_dark:n,close:Y,reload:d,subscribeWebAtTop:v.subscribe,children:A.map(i=>(0,y.jsx)(Zt,{instance_key:i,is_active:a===i,is_front:(a!=null?a:h.current)===i,is_dark:n,reload_tick:g[i]||0,web_at_top:v,splash:t,bridge:r,opaque_background:o,onWebLoadEnd:c},i))}):null},k=w.StyleSheet.create({webview:{flex:1,backgroundColor:"transparent"},behind:{zIndex:-1},splash:{flex:1,alignItems:"center",justifyContent:"center",gap:12},splash_icon:{width:72,height:72,borderRadius:20,alignItems:"center",justifyContent:"center",overflow:"hidden"},splash_icon_image:{width:72,height:72},splash_letter:{fontSize:28,fontWeight:"700",color:"#1D4ED8"},splash_name:{fontSize:16,fontWeight:"600"},splash_hint:{color:"#71717A"},splash_spinner:{marginTop:8},retry_button:{marginTop:4,paddingHorizontal:20,paddingVertical:10,borderRadius:999},retry_text:{fontWeight:"600"}}),Rt=l.default.memo(nn);0&&(module.exports={DefaultMiniAppSplash,MINIAPP_PLATFORM_URL,MiniAppHost,MiniAppHostError,closeMiniApp,configureMiniApp,createMmkvStorage,createRnfsFileSystem,ensureMiniApp,getLocalMiniApp,getMiniAppCatalogEntry,getMiniAppStatuses,onMiniAppEvent,openMiniApp,pauseMiniAppDownloads,preloadMiniApp,resumeMiniAppDownloads,sendEventToWeb,syncMiniAppCatalog,uninstallMiniApp,useMiniAppDownload,useMiniAppDownloadsPaused});
45
+ true;`},at={partner:"partner_token",chatbox:"chatbox_token"},pt=(e,t)=>{let n={...e};for(let r of Object.values(at))t.includes(r)||delete n[r];return n},Re=new Set,Ge=async(e,t)=>{if(Re.has(e))throw new E("BUSY",`${e} \u0111ang ch\u1EA1y \u2014 ch\u1EDD l\u01B0\u1EE3t tr\u01B0\u1EDBc xong`);Re.add(e);try{return await t()}finally{Re.delete(e)}},Pe=(e,t)=>{if(typeof e!="string"||!e)throw new E("INVALID_PARAMS",`Thi\u1EBFu ${t}`);return e},ct=async({method:e,params:t},{getHostData:n,getPermissions:r,is_dark:s,close:o,app_id:l,instance_id:i,options:p})=>{var M,g,D,S;let f=p==null?void 0:p.handlers,A={app_id:l,instance_id:i,close:o},y=()=>new E("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF \u1EE9ng d\u1EE5ng n\xE0y`);switch(e){case"requestPayment":{let d=f==null?void 0:f.requestPayment;if(!d)throw y();let a=t==null?void 0:t.amount;if(typeof a!="number"||!Number.isFinite(a)||a<=0)throw new E("INVALID_PARAMS","amount ph\u1EA3i l\xE0 s\u1ED1 > 0");let R={...t,amount:a,currency:Pe(t==null?void 0:t.currency,"currency")};return Ge(e,()=>d(R,A))}case"printImage":{let d=f==null?void 0:f.printImage;if(!d)throw y();let a=Pe(t==null?void 0:t.image,"image");await Ge(e,()=>d({image:a},A));return}case"openScreen":if(!(f!=null&&f.openScreen))throw y();await f.openScreen({screen:Pe(t==null?void 0:t.screen,"screen"),params:t==null?void 0:t.params},A);return;case"closeApp":o();return;case"openWebview":{let d=String((M=t==null?void 0:t.url)!=null?M:"");if(!/^https?:\/\//i.test(d))throw new E("INVALID_PARAMS","url ph\u1EA3i l\xE0 http(s)");await(p!=null&&p.openUrl?p.openUrl(d):de.Linking.openURL(d));return}case"showToast":(D=p==null?void 0:p.showToast)==null||D.call(p,String((g=t==null?void 0:t.message)!=null?g:""));return;case"getSystemInfo":return{platform:de.Platform.OS==="ios"?"ios":"android",appVersion:(S=p==null?void 0:p.app_version)!=null?S:"",theme:s?"dark":"light"};case"getAccessToken":{let d=n().access_token;if(!d)throw new E("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return d}case"getToken":{let d=t==null?void 0:t.type;if(d==="access"){let q=n().access_token;if(!q)throw new E("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return q}if(d!=="partner"&&d!=="chatbox")throw new E("HOST_ERROR",`Lo\u1EA1i token kh\xF4ng h\u1EE3p l\u1EC7: ${String(d)}`);let a=at[d];if(!r().includes(a))throw new E("PERMISSION_DENIED",`Mini app ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5p quy\u1EC1n ${a} (Console \u2192 Quy\u1EC1n l\u1EA5y token)`);let R=d==="partner"?n().partner_token:n().chatbox_token;if(!R)throw new E("HOST_ERROR",`Kh\xF4ng c\xF3 ${a}`);return R}case"getUserInfo":{let d=n().user;if(!d)throw new E("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin nh\xE2n vi\xEAn");return d}case"getPageInfo":{let d=n().page;if(!d)throw new E("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin page");return d}case"sendMessage":case"insertText":throw new E("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF phi\xEAn b\u1EA3n app n\xE0y`);default:throw new E("NOT_SUPPORTED",`API kh\xF4ng t\u1ED3n t\u1EA1i: ${e}`)}};var Oe=e=>`bundle:${e}`,ke=()=>`${x().file_system.document_dir}/miniapps`,dt=(e,t,n="index.html",r=!1,s=[])=>{let o=`${ke()}/${e}/${t}`;return{app_id:e,version:t,dir:o,entry_uri:`file://${o}/${n}`,context_update:r,permissions:s}},lt=e=>{var t;x().storage.setString(Oe(e.app_id),JSON.stringify({version:e.version,entry:e.entry,context_update:!!e.context_update,permissions:(t=e.permissions)!=null?t:[]}))},Gt=(e,t)=>/^https?:\/\//.test(t)?t:`${e.replace(/[^/]*$/,"")}${t}`,T=e=>{let t=x().storage.getString(Oe(e));if(!t)return null;try{let{version:n,entry:r,context_update:s,permissions:o}=JSON.parse(t);return dt(e,n,r,!!s,Array.isArray(o)?o:[])}catch{return null}},he=e=>x().file_system.exists(e.entry_uri.replace("file://","")),Ie=async e=>{let t=T(e.app_id);return(t==null?void 0:t.version)===e.version&&await he(t)},Xt=async(e,t)=>{let n=x().file_system,r=`${ke()}/${e}`,s=await n.listDir(r).catch(()=>[]);await Promise.all(s.filter(o=>!t.includes(o)).map(o=>n.remove(`${r}/${o}`).catch(()=>{})))},gt=async e=>{var t;await((t=se[e])==null?void 0:t.catch(()=>{})),x().storage.setString(Oe(e),""),await x().file_system.remove(`${ke()}/${e}`).catch(()=>{})},Z=class extends Error{constructor(){super("cancelled"),this.name="MiniAppInstallCancelled"}},se={},De=(e,{base_url:t,onProgress:n}={})=>{var M;let r=x().file_system,s=null,o=!1,l=`${r.cache_dir}/${e.app_id}-${e.version}.zip`,i=()=>{if(o)throw new Z},p=async()=>{var S;i();let g=T(e.app_id);if((g==null?void 0:g.version)===e.version&&await r.exists(g.dir))return lt(e),T(e.app_id);i();let D=r.download({url:t?Gt(t,e.bundle_url):e.bundle_url,to_file:l,onProgress:(d,a)=>{var q;let R=a>0?a:(q=e.size)!=null?q:0;R>0&&(n==null||n(Math.min(1,d/R)))}});s=D;try{let{status:d}=await D.promise;if(i(),d!==200)throw new Error(`bundle ${d}`);if(e.sha256)if(r.sha256){if(await r.sha256(l)!==e.sha256)throw new Error("sha256 mismatch")}else J("b\u1ECF qua ki\u1EC3m tra sha256 (file_system kh\xF4ng c\xF3 sha256)",e.app_id);i();let a=dt(e.app_id,e.version,e.entry,!!e.context_update,(S=e.permissions)!=null?S:[]);return await r.remove(a.dir).catch(()=>{}),await r.mkdir(a.dir),await r.unzip(l,a.dir),lt(e),Xt(e.app_id,[e.version,g==null?void 0:g.version].filter(Boolean)),a}catch(d){throw o?new Z:d}finally{s=null,r.remove(l).catch(()=>{})}},A=((M=se[e.app_id])!=null?M:Promise.resolve()).catch(()=>{}).then(p),y=A.catch(()=>{});return se[e.app_id]=y,y.then(()=>{se[e.app_id]===y&&delete se[e.app_id]}),{promise:A,cancel:()=>{o=!0,s==null||s.cancel()}}},oe={},Zt=__DEV__?0:60*1e3,ut={},ft=(e,t)=>{var r,s;let n=T(e);return n&&Date.now()-((r=ut[t])!=null?r:0)<Zt?Promise.resolve(n):((s=oe[e])!=null||(oe[e]=(async()=>{let o=await fetch(t,{headers:{"Cache-Control":"no-cache"}});if(!o.ok)throw new Error(`manifest ${o.status}`);let l=await o.json(),i=await De(l,{base_url:t}).promise;return ut[t]=Date.now(),i})().catch(o=>(console.warn("[miniapp] sync failed",e,o==null?void 0:o.message),T(e))).finally(()=>{oe[e]=void 0})),oe[e])};var Ae=new Map,ht=(e,t)=>(Ae.set(e,t),()=>{Ae.get(e)===t&&Ae.delete(e)}),At=(e,t)=>{let n=Ae.get(e);return n?n(t):!1};var me=require("react"),Me=e=>{let t=e,n=new Set;return{getState:()=>t,setState:r=>{let s=typeof r=="function"?r(t):r;t={...t,...s},n.forEach(o=>o())},subscribe:r=>(n.add(r),()=>{n.delete(r)})}},W=(e,t,n=Object.is)=>{let r=(0,me.useRef)(null),s=()=>{let o=e.getState(),l=r.current;if(l&&l.state===o&&l.selector===t)return l.value;let i=t(o),p=l&&n(l.value,i)?l.value:i;return r.current={state:o,selector:t,value:p},p};return(0,me.useSyncExternalStore)(e.subscribe,s)};var N=Me({active_key:null,instances:{}}),mt=({app:e,instance_id:t,context:n={},url_params:r={},host_data:s={}},o)=>{var i;let l=(i=x().keep_alive)==null?void 0:i.max_webviews;N.setState(p=>{let f=t!=null?t:e.app_id,A={...p.instances,[f]:{key:f,app:e,context:n,url_params:r,host_data:s,last_used_at:Date.now()}},y=Object.keys(A);return l&&l>0&&y.length>l&&y.filter(M=>M!==f).sort((M,g)=>A[M].last_used_at-A[g].last_used_at).slice(0,y.length-l).forEach(M=>{delete A[M]}),o?{active_key:f,instances:A}:{instances:A}})},Mt=e=>mt(e,!0),wt=e=>mt(e,!1),ee=()=>N.setState({active_key:null}),we=e=>{N.setState(t=>{if(t.active_key===e||!t.instances[e])return{};let n={...t.instances};return delete n[e],{instances:n}})};var yt="catalog",en="paused_apps",tn="removed_apps",nn=10*1e3,rn=2,on=3e3,sn=()=>{var e;try{return JSON.parse((e=x().storage.getString(yt))!=null?e:"{}")}catch{return{}}},b=Me({catalog:{},downloads:{},pause_reasons:[]}),vt=e=>{let t=new Set,n=()=>x().storage.setString(e,JSON.stringify([...t]));return{has:r=>t.has(r),values:()=>[...t],add:r=>t.has(r)?!1:(t.add(r),n(),!0),delete:r=>t.delete(r)?(n(),!0):!1,load:()=>{var r;t.clear();try{let s=JSON.parse((r=x().storage.getString(e))!=null?r:"[]");Array.isArray(s)&&s.forEach(o=>{typeof o=="string"&&t.add(o)})}catch{}}}},F=vt(en),K=vt(tn);ze(()=>{F.load(),K.load();let e=sn(),t={};Object.keys(e).filter(n=>!K.has(n)).forEach(n=>{let r=T(n);r?t[n]={status:"installed",progress:1,version:r.version,has_local:!0}:F.has(n)&&(t[n]={status:"paused",progress:0,version:e[n].version,has_local:!1})}),b.setState({catalog:e,downloads:t})});var Se=e=>W(b,t=>e?t.downloads[e]:void 0),St=()=>W(b,e=>e.pause_reasons.length>0),V=(...e)=>J("queue",...e),P=[],j={},m=null,ye=new Set,G={},Le=new Set,X=e=>{Le.forEach(t=>{try{t(e)}catch(n){console.warn("[miniapp-queue] event listener error",n==null?void 0:n.message)}})},_t=e=>(Le.add(e),()=>{Le.delete(e)}),bt=()=>b.getState().downloads,k=(e,t)=>{let n=!!T(e),r=b.getState().downloads[e],s=t.status==="downloading"&&n?"updating":t.status,o={...r!=null?r:{status:"queued",progress:0},...t,...s?{status:s}:{},has_local:n};b.setState(l=>({downloads:{...l.downloads,[e]:o}})),(r==null?void 0:r.status)!==o.status||(r==null?void 0:r.version)!==o.version||(r==null?void 0:r.has_local)!==o.has_local?X({type:"status_change",app_id:e,state:o}):r.progress!==o.progress&&X({type:"progress",app_id:e,progress:o.progress,version:o.version})},ve=(e,t)=>{var n;(n=G[e])==null||n.forEach(r=>r(t)),delete G[e]},an=()=>b.getState().pause_reasons.length>0,U=e=>{var i;if(m)return;let t=e?P.indexOf(e):an()?-1:P.findIndex(p=>!F.has(p));if(t<0||t>=P.length)return;let[n]=P.splice(t,1),r=b.getState().catalog[n];if(!r){ve(n,T(n)),U();return}let s=Date.now();j[n]=((i=j[n])!=null?i:0)+1,k(n,{status:"downloading",progress:0,version:r.version,error:void 0});let o=0,l=De(r,{onProgress:p=>{let f=Math.floor(p*100);f!==o&&(o=f,k(n,{progress:f/100,version:r.version}))}});m={app_id:n,handle:l,forced:!!e},V("start",n,r.version,e?"(forced)":""),l.promise.then(p=>{V("installed",n,r.version,`${Date.now()-s}ms`),k(n,{status:"installed",progress:1,version:r.version}),ve(n,p)}).catch(p=>{var A;if(p instanceof Z){if(ye.has(n))return;V("paused",n),j[n]-=1,P.unshift(n),k(n,{status:F.has(n)?"paused":"queued",progress:0,version:r.version});return}let f=String((A=p==null?void 0:p.message)!=null?A:p);if(console.warn("[miniapp-queue] failed",n,f),j[n]<rn){k(n,{status:"queued",progress:0,version:r.version,error:f}),setTimeout(()=>{var y;P.includes(n)||(m==null?void 0:m.app_id)===n||(P.push(n),U((y=G[n])!=null&&y.length?n:void 0))},on);return}k(n,{status:"failed",progress:0,version:r.version,error:f}),ve(n,T(n))}).finally(()=>{m=null;let p=P.find(f=>{var A;return(A=G[f])==null?void 0:A.length});U(p)})},_e=(e,{front:t=!1}={})=>{if((m==null?void 0:m.app_id)===e)return;let n=P.indexOf(e);if(n>=0){if(!t)return;P.splice(n,1)}t?P.unshift(e):P.push(e)},pn=async e=>{let{host_id:t,client_token:n}=x(),r=new AbortController,s=setTimeout(()=>r.abort(),nn);try{let o=`${ue}/api/hosts/${encodeURIComponent(t)}/miniapps?channel=${e}`,l=await fetch(o,{headers:{Authorization:`Bearer ${n}`,"Cache-Control":"no-cache"},signal:r.signal});if(!l.ok)throw new Error(`host list ${e} ${l.status}`);return(await l.json()).apps.map(p=>({...p,channel:e}))}finally{clearTimeout(s)}},ie=null,be=()=>(ie!=null||(ie=(async()=>{var t;let e=Date.now();try{let n=await Promise.all(x().channels.map(pn)),r={};[...n].reverse().flat().forEach(i=>{r[i.app_id]=i});let s=Object.keys(b.getState().catalog).filter(i=>!r[i]);x().storage.setString(yt,JSON.stringify(r)),b.setState({catalog:r}),await Promise.all(s.map(i=>xt(i,{by_user:!1}))),s.forEach(i=>K.delete(i));let o=Object.keys(r).filter(i=>!K.has(i)),l=[];for(let i of o.map(p=>r[p]))await Ie(i)?k(i.app_id,{status:"installed",progress:1,version:i.version}):l.push(i);return l.forEach(i=>{j[i.app_id]=0,k(i.app_id,{status:F.has(i.app_id)?"paused":"queued",progress:0,version:i.version,error:void 0}),_e(i.app_id)}),V("catalog",o.length,"apps, outdated",l.map(i=>i.app_id),"removed",s,`${Date.now()-e}ms`),X({type:"sync_complete",app_ids:o,removed:s}),U(),{ok:!0,app_ids:o,removed:s}}catch(n){let r=String((n==null?void 0:n.name)==="AbortError"?"timeout":(t=n==null?void 0:n.message)!=null?t:n);return console.warn("[miniapp-queue] sync catalog failed",r),X({type:"sync_failed",error:r}),{ok:!1,error:r}}finally{ie=null}})()),ie),xt=async(e,{by_user:t})=>{var s,o,l,i;if(t&&K.add(e),ye.has(e))return;ye.add(e),F.delete(e);let n=P.indexOf(e);n>=0&&P.splice(n,1),(m==null?void 0:m.app_id)===e&&m.handle.cancel();let r=(i=(l=(s=b.getState().downloads[e])==null?void 0:s.version)!=null?l:(o=T(e))==null?void 0:o.version)!=null?i:"";k(e,{status:"uninstalling",progress:0,version:r}),await gt(e),we(e),b.setState(p=>{let f={...p.downloads};return delete f[e],{downloads:f}}),delete j[e],ye.delete(e),ve(e,null),V("uninstalled",e,t?"(user)":"(not in list)"),X({type:"uninstalled",app_id:e})},Et=e=>xt(e,{by_user:!0}),Tt=e=>{let t=ae(e);return t?(K.delete(e),(m==null?void 0:m.app_id)===e||P.includes(e)||(j[e]=0,k(e,{status:F.has(e)?"paused":"queued",progress:0,version:t.version,error:void 0}),_e(e),U(),V("restore",e)),!0):!1},Rt=e=>{if(F.has(e))return;if(F.add(e),V("pause app",e),(m==null?void 0:m.app_id)===e&&!m.forced){m.handle.cancel();return}let t=b.getState().downloads[e];P.includes(e)&&t&&k(e,{status:"paused",progress:0,version:t.version})},Pt=e=>{if(!F.delete(e))return;V("resume app",e);let t=b.getState().downloads[e];(t==null?void 0:t.status)==="paused"&&!P.includes(e)&&ae(e)&&(j[e]=0,_e(e)),P.includes(e)&&t&&k(e,{status:"queued",progress:0,version:t.version}),U()},Ct=e=>{let{pause_reasons:t}=b.getState();t.includes(e)||(b.setState({pause_reasons:[...t,e]}),V("pause",e),t.length===0&&X({type:"pause_change",paused:!0,reasons:[e]}),m&&!m.forced&&m.handle.cancel())},Ot=e=>{let{pause_reasons:t}=b.getState();if(!t.includes(e))return;let n=t.filter(r=>r!==e);b.setState({pause_reasons:n}),V("resume",e),n.length===0&&X({type:"pause_change",paused:!1,reasons:n}),U()},kt=()=>Object.values(b.getState().catalog).map(e=>({...e,installed:!!T(e.app_id),removed_by_user:K.has(e.app_id)})),ae=e=>b.getState().catalog[e],xe=async e=>{let t=ae(e);if(!t)return;if(F.delete(e),K.delete(e),await Ie(t))return T(e);let n=new Promise(r=>{var s;((s=G[e])!=null?s:G[e]=[]).push(r)});return(m==null?void 0:m.app_id)===e?m.forced=!0:(j[e]=0,_e(e,{front:!0}),m&&!m.forced?m.handle.cancel():U(e)),n};var v=require("react/jsx-runtime"),$e=e=>(e!=null?e:"").replace(/\?[^#]*/,""),It=0,cn=()=>{let e=new Set;return{emit:t=>e.forEach(n=>n(t)),subscribe:t=>(e.add(t),()=>{e.delete(t)})}},ln=u.default.memo(({instance_key:e,is_active:t,is_front:n,is_dark:r,reload_tick:s,web_at_top:o,splash:l,bridge:i,opaque_background:p,onWebLoadEnd:f})=>{var We,je;let A=(0,u.useRef)(null),y=(0,u.useRef)(!1),M=W(N,c=>c.instances[e]),g=M==null?void 0:M.app.app_id,D=M==null?void 0:M.app.manifest_url,S=M==null?void 0:M.context,d=M==null?void 0:M.url_params,[a,R]=(0,u.useState)(()=>g?T(g):null),[q,te]=(0,u.useState)(!1),[Nt,Fe]=(0,u.useState)(0),[Ft,ne]=(0,u.useState)(0),[Bt,L]=(0,u.useState)(!1),B=(0,u.useRef)(null),Be=c=>{B.current&&clearTimeout(B.current),B.current=setTimeout(()=>{B.current=null,L(!0)},c)};(0,u.useEffect)(()=>()=>{B.current&&clearTimeout(B.current)},[]),(0,u.useEffect)(()=>{if(!g||!t&&a)return;let c=!0;return te(!1),(async()=>{let h=T(g),C=h?await he(h):!1;if(!c||(R(C?$=>!$||$.version!==h.version||$.permissions.join(",")!==h.permissions.join(",")?h:$:null),__DEV__&&Date.now()-It>1e4&&(It=Date.now(),await be()),!c))return;let H=await xe(g),z=H!==void 0?H:D?await ft(g,D):T(g);if(c){if(!z){te(!0);return}R($=>$!=null?$:z)}})(),()=>{c=!1}},[t,g,D,Nt]),(0,u.useEffect)(()=>ht(e,c=>A.current?(A.current.postMessage(c),!0):!1),[e]);let Jt=W(b,c=>{let h=g?c.downloads[g]:void 0;return(h==null?void 0:h.status)==="installed"?h.version:void 0});(0,u.useEffect)(()=>{if(t||!g||!a)return;let c=T(g);if(!c||c.version===a.version)return;let h=!0;return he(c).then(C=>{!h||!C||(J(`webview:${e}`,"\u0111\u1ED5i bundle (\u1EA9n)",a.version,"\u2192",c.version),R(c))}),()=>{h=!1}},[t,g,Jt,a==null?void 0:a.version]),(0,u.useEffect)(()=>{var C;let c=(C=x().keep_alive)==null?void 0:C.idle_close_ms;if(t||!c||c<=0)return;let h=setTimeout(()=>{we(e)},c);return()=>clearTimeout(h)},[t,e]),(0,u.useEffect)(()=>{s>0&&(te(!1),L(!1),ne(c=>c+1),Fe(c=>c+1))},[s]);let Je=(0,u.useRef)(t);(0,u.useEffect)(()=>{var c;Je.current!==t&&(Je.current=t,y.current&&((c=A.current)==null||c.injectJavaScript(rt(t?"resumed":"paused"))))},[t]);let pe=`${(We=a==null?void 0:a.version)!=null?We:"none"}:${(je=a==null?void 0:a.permissions.join(","))!=null?je:""}:${Ft}`,re=(0,u.useMemo)(()=>JSON.stringify([S!=null?S:{},d!=null?d:{}]),[S,d]),Ee=(0,u.useMemo)(()=>{var c;return pt(d!=null?d:{},(c=a==null?void 0:a.permissions)!=null?c:[])},[re,a==null?void 0:a.permissions]),Vt=(0,u.useMemo)(()=>it(S!=null?S:{},Ee)+nt()+(x().debug?tt():""),[Ee]),ce=(0,u.useRef)(null),Ve=(0,u.useRef)(null);(0,u.useEffect)(()=>{var h,C,H;if(!a)return;if(Ve.current!==pe){Ve.current=pe,ce.current=re;return}if(ce.current===re)return;let c=((C=JSON.parse((h=ce.current)!=null?h:"[]")[0])!=null?C:{}).org_id;if(ce.current=re,c===(S==null?void 0:S.org_id)&&y.current){L(!1),Be(1500),(H=A.current)==null||H.injectJavaScript(ot(S!=null?S:{},Ee));return}L(!1),ne(z=>z+1)},[re,a,pe]);let Wt=(0,u.useCallback)(async c=>{var C,H,z,$,Te;let h=Xe(c.nativeEvent.data);if(!h){if(g&&(i!=null&&i.onWebEvent))try{Promise.resolve(i.onWebEvent(c.nativeEvent.data,{app_id:g,instance_id:e})).catch(_=>{console.warn("[miniapp] onWebEvent l\u1ED7i",g,_)})}catch(_){console.warn("[miniapp] onWebEvent l\u1ED7i",g,_)}return}if(h.method==="log"){let{level:_,text:O}=h;J(`web:${e}`,_!=null?_:"log",O!=null?O:"");return}if(h.method==="pong"){B.current||L(!0);return}if(h.method==="touchAtTop"){o.emit(!!h.at_top);return}if(h.method==="contextApplied"){B.current&&clearTimeout(B.current),B.current=null,L(!0);return}if(h.method==="ready"){y.current=!0,L(!0);let _=(C=N.getState().instances[e])==null?void 0:C.context;_&&((H=A.current)==null||H.injectJavaScript(Ce(_)));return}try{let _=await ct(h,{getHostData:()=>{var O,Y;return(Y=(O=N.getState().instances[e])==null?void 0:O.host_data)!=null?Y:{}},getPermissions:()=>{var O,Y;return g?(Y=(O=T(g))==null?void 0:O.permissions)!=null?Y:[]:[]},is_dark:r,close:ee,app_id:g!=null?g:"",instance_id:e,options:i});h.id&&((z=A.current)==null||z.injectJavaScript(Ze(h.id,_)))}catch(_){if(!h.id)return;let O=_==null?void 0:_.code,Y=_ instanceof E?_:new E(typeof O=="string"?O:"HOST_ERROR",String(($=_==null?void 0:_.message)!=null?$:_));(Te=A.current)==null||Te.injectJavaScript(et(h.id,Y))}},[e,r,g,o,i]),jt=(0,u.useCallback)(()=>{te(!1),ne(c=>c+1),Fe(c=>c+1)},[]);return(0,v.jsxs)(w.View,{style:[w.StyleSheet.absoluteFill,p&&{backgroundColor:r?"#09090B":"#FFFFFF"},!n&&I.behind],pointerEvents:t?"auto":"none",children:[a?(0,v.jsx)(Lt.default,{ref:A,source:{uri:a.entry_uri},originWhitelist:["*"],allowingReadAccessToURL:`file://${a.dir}`,allowFileAccess:!0,allowFileAccessFromFileURLs:!0,allowUniversalAccessFromFileURLs:!0,injectedJavaScriptBeforeContentLoaded:Vt,onMessage:Wt,bounces:!1,overScrollMode:"never",onLoadStart:c=>{J(`webview:${e}`,"load start",$e(c.nativeEvent.url)),y.current=!1,L(!1)},onError:c=>{J(`webview:${e}`,"load error",$e(c.nativeEvent.url),c.nativeEvent.description),te(!0),L(!1)},onLoadEnd:c=>{let h=c.nativeEvent.url;J(`webview:${e}`,"load end",$e(h)),g&&(f==null||f({app_id:g,instance_id:e,url:h})),Be(1500)},onContentProcessDidTerminate:()=>{y.current=!1,L(!1),ne(c=>c+1)},onRenderProcessGone:()=>(y.current=!1,L(!1),ne(c=>c+1),!0),style:I.webview},pe):null,M&&(0,v.jsx)(dn,{visible:!a||!Bt,interactive:q,children:(0,v.jsx)(un,{splash:l,app:M.app,is_dark:r,error:q,has_bundle:!!a,retry:jt})})]})}),un=u.default.memo(({splash:e,app:t,is_dark:n,error:r,has_bundle:s,retry:o})=>{let l=e,i=Se(t.app_id),p=r?"error":!s&&(i==null?void 0:i.status)==="downloading"?"downloading":"loading";return(0,v.jsx)(l,{app:t,is_dark:n,status:p,progress:p==="downloading"?i==null?void 0:i.progress:void 0,retry:o})}),dn=({visible:e,interactive:t,children:n})=>{let r=(0,u.useRef)(new w.Animated.Value(e?1:0)).current,[s,o]=(0,u.useState)(e);return(0,u.useEffect)(()=>{if(e){o(!0),r.setValue(1);return}let l=w.Animated.timing(r,{toValue:0,duration:180,useNativeDriver:!0});return l.start(({finished:i})=>{i&&o(!1)}),()=>l.stop()},[e,r]),s?(0,v.jsx)(w.Animated.View,{style:[w.StyleSheet.absoluteFill,{opacity:r}],pointerEvents:t?"auto":"none",children:n}):null},Ne=({app:e,is_dark:t,status:n,progress:r,retry:s})=>{let o=t?"#FAFAFA":"#18181B";return(0,v.jsxs)(w.View,{style:[I.splash,{backgroundColor:t?"#09090B":"#FFFFFF"}],children:[(0,v.jsx)(w.View,{style:[I.splash_icon,{backgroundColor:t?"#18181B":"#F4F4F5"}],children:e.icon?(0,v.jsx)(w.Image,{source:{uri:e.icon},style:I.splash_icon_image}):(0,v.jsx)(w.Text,{style:I.splash_letter,children:(e.name||"?").slice(0,1).toUpperCase()})}),(0,v.jsx)(w.Text,{style:[I.splash_name,{color:o}],children:e.name}),n==="error"?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(w.Text,{style:I.splash_hint,children:"Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c mini app"}),(0,v.jsx)(w.TouchableOpacity,{activeOpacity:.7,style:[I.retry_button,{backgroundColor:t?"#27272A":"#F4F4F5"}],onPress:s,children:(0,v.jsx)(w.Text,{style:[I.retry_text,{color:o}],children:"Th\u1EED l\u1EA1i"})})]}):(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(w.ActivityIndicator,{style:I.splash_spinner,color:t?"#A1A1AA":"#71717A"}),n==="downloading"&&(0,v.jsxs)(w.Text,{style:I.splash_hint,children:["\u0110ang t\u1EA3i mini app",r?` ${Math.round(r*100)}%`:"\u2026"]})]})]})},Dt=(e,t)=>{let n=(0,u.useRef)(t),r=(0,u.useRef)(!1);__DEV__&&!r.current&&n.current!==t&&(r.current=!0,console.warn(`[miniapp] MiniAppHost prop "${e}" \u0111\u1ED5i gi\u1EEFa c\xE1c l\u1EA7n render \u2192 m\u1ECDi WebView b\u1ECB mount l\u1EA1i. Khai b\xE1o component b\xEAn ngo\xE0i render.`))},gn=({container:e,splash:t=Ne,is_dark:n=!1,bridge:r,close_on_back:s=!0,opaque_background:o=!0,onWebLoadEnd:l})=>{Dt("container",e),Dt("splash",t);let i=e,p=W(N,a=>a.active_key),f=(0,u.useRef)(p);p&&(f.current=p);let A=W(N,a=>Object.keys(a.instances).join("|")),y=W(N,a=>{var R;return a.active_key?(R=a.instances[a.active_key])==null?void 0:R.app.name:void 0}),M=(0,u.useMemo)(()=>A?A.split("|"):[],[A]),[g,D]=(0,u.useState)({}),S=(0,u.useRef)(cn()).current;(0,u.useEffect)(()=>{if(!p||!s)return;let a=w.BackHandler.addEventListener("hardwareBackPress",()=>(ee(),!0));return()=>a.remove()},[p,s]);let d=(0,u.useCallback)(()=>{let a=N.getState().active_key;a&&D(R=>({...R,[a]:(R[a]||0)+1}))},[]);return M.length?(0,v.jsx)(i,{visible:!!p,title:y!=null?y:"",is_dark:n,close:ee,reload:d,subscribeWebAtTop:S.subscribe,children:M.map(a=>(0,v.jsx)(ln,{instance_key:a,is_active:p===a,is_front:(p!=null?p:f.current)===a,is_dark:n,reload_tick:g[a]||0,web_at_top:S,splash:t,bridge:r,opaque_background:o,onWebLoadEnd:l},a))}):null},I=w.StyleSheet.create({webview:{flex:1,backgroundColor:"transparent"},behind:{zIndex:-1},splash:{flex:1,alignItems:"center",justifyContent:"center",gap:12},splash_icon:{width:72,height:72,borderRadius:20,alignItems:"center",justifyContent:"center",overflow:"hidden"},splash_icon_image:{width:72,height:72},splash_letter:{fontSize:28,fontWeight:"700",color:"#1D4ED8"},splash_name:{fontSize:16,fontWeight:"600"},splash_hint:{color:"#71717A"},splash_spinner:{marginTop:8},retry_button:{marginTop:4,paddingHorizontal:20,paddingVertical:10,borderRadius:999},retry_text:{fontWeight:"600"}}),$t=u.default.memo(gn);0&&(module.exports={DefaultMiniAppSplash,MINIAPP_PLATFORM_URL,MiniAppHost,MiniAppHostError,closeMiniApp,configureMiniApp,createMmkvStorage,createRnfsFileSystem,ensureMiniApp,getLocalMiniApp,getMiniAppCatalog,getMiniAppCatalogEntry,getMiniAppStatuses,onMiniAppEvent,openMiniApp,pauseMiniApp,pauseMiniAppDownloads,preloadMiniApp,restoreMiniApp,resumeMiniApp,resumeMiniAppDownloads,sendEventToWeb,syncMiniAppCatalog,uninstallMiniApp,useMiniAppDownload,useMiniAppDownloadsPaused});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- var _e="https://retion-miniapp-platform.vercel.app",q=null,qe=new Set,Rt=e=>{q=e,qe.forEach(t=>t())},S=()=>{if(!q)throw new Error("[miniapp] Ch\u01B0a g\u1ECDi configureMiniApp()");return q},Ue=e=>{qe.add(e),q&&e()},N=(...e)=>{q!=null&&q.debug&&console.log("[miniapp]",...e)};var Pt=(e,t)=>({document_dir:e.DocumentDirectoryPath,cache_dir:e.CachesDirectoryPath,exists:n=>e.exists(n),mkdir:n=>e.mkdir(n),remove:n=>e.unlink(n).catch(()=>{}),listDir:n=>e.readDir(n).then(r=>r.map(s=>s.name)).catch(()=>[]),sha256:n=>e.hash(n,"sha256"),unzip:async(n,r)=>{await t(n,r)},download:({url:n,to_file:r,onProgress:s})=>{let{jobId:o,promise:c}=e.downloadFile({fromUrl:n,toFile:r,progressInterval:250,begin:()=>{},progress:({bytesWritten:l,contentLength:a})=>s==null?void 0:s(l,a)});return{promise:c.then(({statusCode:l})=>({status:l})),cancel:()=>e.stopDownload(o)}}}),Ct=e=>({getString:t=>e.getString(t),setString:(t,n)=>e.set(t,n)});import Ne,{useCallback as Le,useEffect as F,useMemo as we,useRef as L,useState as Q}from"react";import{ActivityIndicator as Xt,Animated as Ie,BackHandler as Zt,Image as en,StyleSheet as Fe,Text as se,TouchableOpacity as tn,View as $e}from"react-native";import nn from"react-native-webview";import{Linking as Ot,Platform as kt}from"react-native";var le=1,_=class extends Error{constructor(n,r){super(r);this.code=n}},ze=e=>{try{let t=JSON.parse(e);return(t==null?void 0:t.__retion)===le&&typeof t.method=="string"?t:null}catch{return null}},ue=e=>`window.__RETION_MINIAPP__ && window.__RETION_MINIAPP__.receive(${JSON.stringify(e)}); true;`,Qe=(e,t)=>ue({id:e,result:t}),Ye=(e,t)=>ue({id:e,error:{code:t.code,message:t.message}}),be=e=>ue({event:"context",data:e});var Ge=()=>`(function () {
1
+ var xe="https://retion-miniapp-platform.vercel.app",Q=null,Ye=new Set,Ot=e=>{Q=e,Ye.forEach(t=>t())},S=()=>{if(!Q)throw new Error("[miniapp] Ch\u01B0a g\u1ECDi configureMiniApp()");return Q},Qe=e=>{Ye.add(e),Q&&e()},B=(...e)=>{Q!=null&&Q.debug&&console.log("[miniapp]",...e)};var kt=(e,t)=>({document_dir:e.DocumentDirectoryPath,cache_dir:e.CachesDirectoryPath,exists:n=>e.exists(n),mkdir:n=>e.mkdir(n),remove:n=>e.unlink(n).catch(()=>{}),listDir:n=>e.readDir(n).then(r=>r.map(a=>a.name)).catch(()=>[]),sha256:n=>e.hash(n,"sha256"),unzip:async(n,r)=>{await t(n,r)},download:({url:n,to_file:r,onProgress:a})=>{let{jobId:o,promise:l}=e.downloadFile({fromUrl:n,toFile:r,progressInterval:250,begin:()=>{},progress:({bytesWritten:s,contentLength:p})=>a==null?void 0:a(s,p)});return{promise:l.then(({statusCode:s})=>({status:s})),cancel:()=>e.stopDownload(o)}}}),It=e=>({getString:t=>e.getString(t),setString:(t,n)=>e.set(t,n)});import Ve,{useCallback as Be,useEffect as V,useMemo as Se,useRef as N,useState as Z}from"react";import{ActivityIndicator as cn,Animated as Ne,BackHandler as ln,Image as un,StyleSheet as We,Text as pe,TouchableOpacity as dn,View as Je}from"react-native";import gn from"react-native-webview";import{Linking as Dt,Platform as Lt}from"react-native";var de=1,_=class extends Error{constructor(n,r){super(r);this.code=n}},Xe=e=>{try{let t=JSON.parse(e);return(t==null?void 0:t.__retion)===de&&typeof t.method=="string"?t:null}catch{return null}},ge=e=>`window.__RETION_MINIAPP__ && window.__RETION_MINIAPP__.receive(${JSON.stringify(e)}); true;`,Ze=(e,t)=>ge({id:e,result:t}),et=(e,t)=>ge({id:e,error:{code:t.code,message:t.message}}),Re=e=>ge({event:"context",data:e});var tt=()=>`(function () {
2
2
  var post = function (level, args) {
3
3
  try {
4
4
  var parts = [];
@@ -8,7 +8,7 @@ var _e="https://retion-miniapp-platform.vercel.app",q=null,qe=new Set,Rt=e=>{q=e
8
8
  else if (typeof a === 'object') { try { parts.push(JSON.stringify(a).slice(0, 800)); } catch (e) { parts.push(String(a)); } }
9
9
  else { parts.push(String(a)); }
10
10
  }
11
- window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${le}, method: 'log', level: level, text: parts.join(' ') }));
11
+ window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${de}, method: 'log', level: level, text: parts.join(' ') }));
12
12
  } catch (e) {}
13
13
  };
14
14
  ['log', 'info', 'warn', 'error'].forEach(function (level) {
@@ -19,7 +19,7 @@ var _e="https://retion-miniapp-platform.vercel.app",q=null,qe=new Set,Rt=e=>{q=e
19
19
  window.addEventListener('unhandledrejection', function (e) { post('error', ['[unhandledrejection]', e.reason]); });
20
20
  // Kh\xF4ng log query (c\xF3 th\u1EC3 ch\u1EE9a token) \u2014 ch\u1EC9 \u0111\u01B0\u1EDDng d\u1EABn + route.
21
21
  post('info', ['[page] ' + location.pathname + location.hash]);
22
- })(); true;`,Xe=()=>`(function () {
22
+ })(); true;`,nt=()=>`(function () {
23
23
  function atTop(el) {
24
24
  for (var n = el; n && n !== document.documentElement; n = n.parentElement) {
25
25
  if (n.scrollTop > 0) { return false; }
@@ -30,7 +30,7 @@ var _e="https://retion-miniapp-platform.vercel.app",q=null,qe=new Set,Rt=e=>{q=e
30
30
  function report(at_top) {
31
31
  if (at_top === last) { return; }
32
32
  last = at_top;
33
- window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${le}, method: 'touchAtTop', at_top: at_top }));
33
+ window.ReactNativeWebView && window.ReactNativeWebView.postMessage(JSON.stringify({ __retion: ${de}, method: 'touchAtTop', at_top: at_top }));
34
34
  }
35
35
  document.addEventListener('touchstart', function (e) { report(atTop(e.target)); }, { capture: true, passive: true });
36
36
  // Cu\u1ED9n r\u1EDDi \u0111\u1EA7u trang \u2192 b\xE1o ngay, kh\xF4ng \u0111\u1EE3i l\u1EA7n ch\u1EA1m sau (tr\xE1nh host d\xF9ng gi\xE1 tr\u1ECB c\u0169 "\u0111ang \u1EDF \u0111\u1EA7u").
@@ -38,8 +38,8 @@ var _e="https://retion-miniapp-platform.vercel.app",q=null,qe=new Set,Rt=e=>{q=e
38
38
  var el = e.target === document ? document.documentElement : e.target;
39
39
  if (el && el.scrollTop > 0) { report(false); }
40
40
  }, { capture: true, passive: true });
41
- })(); true;`,Ze=e=>ue({event:e}),et=(e,t)=>{let n=tt(t);return`try { history.replaceState(history.state, '', location.pathname + ${JSON.stringify(n?`?${n}`:"")} + location.hash); } catch (e) {}
42
- ${be(e)}`},tt=e=>Object.entries(e).filter(([,t])=>t!=null&&t!=="").map(([t,n])=>`${encodeURIComponent(t)}=${encodeURIComponent(String(n))}`).join("&"),nt=(e,t={})=>{let n=tt(t);return`window.__RETION_MINIAPP_HOST__ = { protocol: ${le} };
41
+ })(); true;`,rt=e=>ge({event:e}),ot=(e,t)=>{let n=st(t);return`try { history.replaceState(history.state, '', location.pathname + ${JSON.stringify(n?`?${n}`:"")} + location.hash); } catch (e) {}
42
+ ${Re(e)}`},st=e=>Object.entries(e).filter(([,t])=>t!=null&&t!=="").map(([t,n])=>`${encodeURIComponent(t)}=${encodeURIComponent(String(n))}`).join("&"),it=(e,t={})=>{let n=st(t);return`window.__RETION_MINIAPP_HOST__ = { protocol: ${de} };
43
43
  window.__RETION_MINIAPP_CONTEXT__ = ${JSON.stringify(e)};
44
44
  ${n?`try { history.replaceState(history.state, '', location.pathname + '?' + ${JSON.stringify(n)} + location.hash); } catch (e) {}`:""}
45
- true;`},rt={partner:"partner_token",chatbox:"chatbox_token"},ot=(e,t)=>{let n={...e};for(let r of Object.values(rt))t.includes(r)||delete n[r];return n},ve=new Set,Ke=async(e,t)=>{if(ve.has(e))throw new _("BUSY",`${e} \u0111ang ch\u1EA1y \u2014 ch\u1EDD l\u01B0\u1EE3t tr\u01B0\u1EDBc xong`);ve.add(e);try{return await t()}finally{ve.delete(e)}},Se=(e,t)=>{if(typeof e!="string"||!e)throw new _("INVALID_PARAMS",`Thi\u1EBFu ${t}`);return e},it=async({method:e,params:t},{getHostData:n,getPermissions:r,is_dark:s,close:o,app_id:c,instance_id:l,options:a})=>{var m,d,O,M;let f=a==null?void 0:a.handlers,h={app_id:c,instance_id:l,close:o},A=()=>new _("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF \u1EE9ng d\u1EE5ng n\xE0y`);switch(e){case"requestPayment":{let u=f==null?void 0:f.requestPayment;if(!u)throw A();let i=t==null?void 0:t.amount;if(typeof i!="number"||!Number.isFinite(i)||i<=0)throw new _("INVALID_PARAMS","amount ph\u1EA3i l\xE0 s\u1ED1 > 0");let v={...t,amount:i,currency:Se(t==null?void 0:t.currency,"currency")};return Ke(e,()=>u(v,h))}case"printImage":{let u=f==null?void 0:f.printImage;if(!u)throw A();let i=Se(t==null?void 0:t.image,"image");await Ke(e,()=>u({image:i},h));return}case"openScreen":if(!(f!=null&&f.openScreen))throw A();await f.openScreen({screen:Se(t==null?void 0:t.screen,"screen"),params:t==null?void 0:t.params},h);return;case"closeApp":o();return;case"openWebview":{let u=String((m=t==null?void 0:t.url)!=null?m:"");if(!/^https?:\/\//i.test(u))throw new _("INVALID_PARAMS","url ph\u1EA3i l\xE0 http(s)");await(a!=null&&a.openUrl?a.openUrl(u):Ot.openURL(u));return}case"showToast":(O=a==null?void 0:a.showToast)==null||O.call(a,String((d=t==null?void 0:t.message)!=null?d:""));return;case"getSystemInfo":return{platform:kt.OS==="ios"?"ios":"android",appVersion:(M=a==null?void 0:a.app_version)!=null?M:"",theme:s?"dark":"light"};case"getAccessToken":{let u=n().access_token;if(!u)throw new _("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return u}case"getToken":{let u=t==null?void 0:t.type;if(u==="access"){let V=n().access_token;if(!V)throw new _("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return V}if(u!=="partner"&&u!=="chatbox")throw new _("HOST_ERROR",`Lo\u1EA1i token kh\xF4ng h\u1EE3p l\u1EC7: ${String(u)}`);let i=rt[u];if(!r().includes(i))throw new _("PERMISSION_DENIED",`Mini app ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5p quy\u1EC1n ${i} (Console \u2192 Quy\u1EC1n l\u1EA5y token)`);let v=u==="partner"?n().partner_token:n().chatbox_token;if(!v)throw new _("HOST_ERROR",`Kh\xF4ng c\xF3 ${i}`);return v}case"getUserInfo":{let u=n().user;if(!u)throw new _("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin nh\xE2n vi\xEAn");return u}case"getPageInfo":{let u=n().page;if(!u)throw new _("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin page");return u}case"sendMessage":case"insertText":throw new _("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF phi\xEAn b\u1EA3n app n\xE0y`);default:throw new _("NOT_SUPPORTED",`API kh\xF4ng t\u1ED3n t\u1EA1i: ${e}`)}};var xe=e=>`bundle:${e}`,Ee=()=>`${S().file_system.document_dir}/miniapps`,pt=(e,t,n="index.html",r=!1,s=[])=>{let o=`${Ee()}/${e}/${t}`;return{app_id:e,version:t,dir:o,entry_uri:`file://${o}/${n}`,context_update:r,permissions:s}},st=e=>{var t;S().storage.setString(xe(e.app_id),JSON.stringify({version:e.version,entry:e.entry,context_update:!!e.context_update,permissions:(t=e.permissions)!=null?t:[]}))},It=(e,t)=>/^https?:\/\//.test(t)?t:`${e.replace(/[^/]*$/,"")}${t}`,x=e=>{let t=S().storage.getString(xe(e));if(!t)return null;try{let{version:n,entry:r,context_update:s,permissions:o}=JSON.parse(t);return pt(e,n,r,!!s,Array.isArray(o)?o:[])}catch{return null}},de=e=>S().file_system.exists(e.entry_uri.replace("file://","")),Te=async e=>{let t=x(e.app_id);return(t==null?void 0:t.version)===e.version&&await de(t)},Dt=async(e,t)=>{let n=S().file_system,r=`${Ee()}/${e}`,s=await n.listDir(r).catch(()=>[]);await Promise.all(s.filter(o=>!t.includes(o)).map(o=>n.remove(`${r}/${o}`).catch(()=>{})))},ct=async e=>{var t;await((t=re[e])==null?void 0:t.catch(()=>{})),S().storage.setString(xe(e),""),await S().file_system.remove(`${Ee()}/${e}`).catch(()=>{})},Y=class extends Error{constructor(){super("cancelled"),this.name="MiniAppInstallCancelled"}},re={},Re=(e,{base_url:t,onProgress:n}={})=>{var m;let r=S().file_system,s=null,o=!1,c=`${r.cache_dir}/${e.app_id}-${e.version}.zip`,l=()=>{if(o)throw new Y},a=async()=>{var M;l();let d=x(e.app_id);if((d==null?void 0:d.version)===e.version&&await r.exists(d.dir))return st(e),x(e.app_id);l();let O=r.download({url:t?It(t,e.bundle_url):e.bundle_url,to_file:c,onProgress:(u,i)=>{var V;let v=i>0?i:(V=e.size)!=null?V:0;v>0&&(n==null||n(Math.min(1,u/v)))}});s=O;try{let{status:u}=await O.promise;if(l(),u!==200)throw new Error(`bundle ${u}`);if(e.sha256)if(r.sha256){if(await r.sha256(c)!==e.sha256)throw new Error("sha256 mismatch")}else N("b\u1ECF qua ki\u1EC3m tra sha256 (file_system kh\xF4ng c\xF3 sha256)",e.app_id);l();let i=pt(e.app_id,e.version,e.entry,!!e.context_update,(M=e.permissions)!=null?M:[]);return await r.remove(i.dir).catch(()=>{}),await r.mkdir(i.dir),await r.unzip(c,i.dir),st(e),Dt(e.app_id,[e.version,d==null?void 0:d.version].filter(Boolean)),i}catch(u){throw o?new Y:u}finally{s=null,r.remove(c).catch(()=>{})}},h=((m=re[e.app_id])!=null?m:Promise.resolve()).catch(()=>{}).then(a),A=h.catch(()=>{});return re[e.app_id]=A,A.then(()=>{re[e.app_id]===A&&delete re[e.app_id]}),{promise:h,cancel:()=>{o=!0,s==null||s.cancel()}}},ne={},Lt=__DEV__?0:60*1e3,at={},lt=(e,t)=>{var r,s;let n=x(e);return n&&Date.now()-((r=at[t])!=null?r:0)<Lt?Promise.resolve(n):((s=ne[e])!=null||(ne[e]=(async()=>{let o=await fetch(t,{headers:{"Cache-Control":"no-cache"}});if(!o.ok)throw new Error(`manifest ${o.status}`);let c=await o.json(),l=await Re(c,{base_url:t}).promise;return at[t]=Date.now(),l})().catch(o=>(console.warn("[miniapp] sync failed",e,o==null?void 0:o.message),x(e))).finally(()=>{ne[e]=void 0})),ne[e])};var ge=new Map,ut=(e,t)=>(ge.set(e,t),()=>{ge.get(e)===t&&ge.delete(e)}),$t=(e,t)=>{let n=ge.get(e);return n?n(t):!1};import{useRef as Nt,useSyncExternalStore as Ft}from"react";var fe=e=>{let t=e,n=new Set;return{getState:()=>t,setState:r=>{let s=typeof r=="function"?r(t):r;t={...t,...s},n.forEach(o=>o())},subscribe:r=>(n.add(r),()=>{n.delete(r)})}},B=(e,t,n=Object.is)=>{let r=Nt(null),s=()=>{let o=e.getState(),c=r.current;if(c&&c.state===o&&c.selector===t)return c.value;let l=t(o),a=c&&n(c.value,l)?c.value:l;return r.current={state:o,selector:t,value:a},a};return Ft(e.subscribe,s)};var D=fe({active_key:null,instances:{}}),dt=({app:e,instance_id:t,context:n={},url_params:r={},host_data:s={}},o)=>{var l;let c=(l=S().keep_alive)==null?void 0:l.max_webviews;D.setState(a=>{let f=t!=null?t:e.app_id,h={...a.instances,[f]:{key:f,app:e,context:n,url_params:r,host_data:s,last_used_at:Date.now()}},A=Object.keys(h);return c&&c>0&&A.length>c&&A.filter(m=>m!==f).sort((m,d)=>h[m].last_used_at-h[d].last_used_at).slice(0,A.length-c).forEach(m=>{delete h[m]}),o?{active_key:f,instances:h}:{instances:h}})},Bt=e=>dt(e,!0),Jt=e=>dt(e,!1),oe=()=>D.setState({active_key:null}),he=e=>{D.setState(t=>{if(t.active_key===e||!t.instances[e])return{};let n={...t.instances};return delete n[e],{instances:n}})};var gt="catalog",Vt=10*1e3,Wt=2,jt=3e3,Ht=()=>{var e;try{return JSON.parse((e=S().storage.getString(gt))!=null?e:"{}")}catch{return{}}},b=fe({catalog:{},downloads:{},pause_reasons:[]});Ue(()=>b.setState({catalog:Ht()}));var Ce=e=>B(b,t=>e?t.downloads[e]:void 0),qt=()=>B(b,e=>e.pause_reasons.length>0),K=(...e)=>N("queue",...e),T=[],U={},w=null,me=new Set,z={},Pe=new Set,X=e=>{Pe.forEach(t=>{try{t(e)}catch(n){console.warn("[miniapp-queue] event listener error",n==null?void 0:n.message)}})},Ut=e=>(Pe.add(e),()=>{Pe.delete(e)}),Kt=()=>b.getState().downloads,J=(e,t)=>{let n=!!x(e),r=b.getState().downloads[e],s=t.status==="downloading"&&n?"updating":t.status,o={...r!=null?r:{status:"queued",progress:0},...t,...s?{status:s}:{},has_local:n};b.setState(c=>({downloads:{...c.downloads,[e]:o}})),(r==null?void 0:r.status)!==o.status||(r==null?void 0:r.version)!==o.version||(r==null?void 0:r.has_local)!==o.has_local?X({type:"status_change",app_id:e,state:o}):r.progress!==o.progress&&X({type:"progress",app_id:e,progress:o.progress,version:o.version})},Ae=(e,t)=>{var n;(n=z[e])==null||n.forEach(r=>r(t)),delete z[e]},zt=()=>b.getState().pause_reasons.length>0,G=e=>{var l;if(w)return;let t=e?T.indexOf(e):zt()?-1:0;if(t<0||t>=T.length)return;let[n]=T.splice(t,1),r=b.getState().catalog[n];if(!r){Ae(n,x(n)),G();return}let s=Date.now();U[n]=((l=U[n])!=null?l:0)+1,J(n,{status:"downloading",progress:0,version:r.version,error:void 0});let o=0,c=Re(r,{onProgress:a=>{let f=Math.floor(a*100);f!==o&&(o=f,J(n,{progress:f/100,version:r.version}))}});w={app_id:n,handle:c,forced:!!e},K("start",n,r.version,e?"(forced)":""),c.promise.then(a=>{K("installed",n,r.version,`${Date.now()-s}ms`),J(n,{status:"installed",progress:1,version:r.version}),Ae(n,a)}).catch(a=>{var h;if(a instanceof Y){if(me.has(n))return;K("paused",n),U[n]-=1,T.unshift(n),J(n,{status:"queued",progress:0,version:r.version});return}let f=String((h=a==null?void 0:a.message)!=null?h:a);if(console.warn("[miniapp-queue] failed",n,f),U[n]<Wt){J(n,{status:"queued",progress:0,version:r.version,error:f}),setTimeout(()=>{var A;T.includes(n)||(w==null?void 0:w.app_id)===n||(T.push(n),G((A=z[n])!=null&&A.length?n:void 0))},jt);return}J(n,{status:"failed",progress:0,version:r.version,error:f}),Ae(n,x(n))}).finally(()=>{w=null;let a=T.find(f=>{var h;return(h=z[f])==null?void 0:h.length});G(a)})},ft=(e,{front:t=!1}={})=>{if((w==null?void 0:w.app_id)===e)return;let n=T.indexOf(e);if(n>=0){if(!t)return;T.splice(n,1)}t?T.unshift(e):T.push(e)},Qt=async e=>{let{host_id:t,client_token:n}=S(),r=new AbortController,s=setTimeout(()=>r.abort(),Vt);try{let o=`${_e}/api/hosts/${encodeURIComponent(t)}/miniapps?channel=${e}`,c=await fetch(o,{headers:{Authorization:`Bearer ${n}`,"Cache-Control":"no-cache"},signal:r.signal});if(!c.ok)throw new Error(`host list ${e} ${c.status}`);return(await c.json()).apps.map(a=>({...a,channel:e}))}finally{clearTimeout(s)}},ie=null,Oe=()=>(ie!=null||(ie=(async()=>{let e=Date.now();try{let t=await Promise.all(S().channels.map(Qt)),n={};[...t].reverse().flat().forEach(o=>{n[o.app_id]=o});let r=Object.keys(b.getState().catalog).filter(o=>!n[o]);S().storage.setString(gt,JSON.stringify(n)),b.setState({catalog:n}),await Promise.all(r.map(ht));let s=[];for(let o of Object.values(n))await Te(o)?J(o.app_id,{status:"installed",progress:1,version:o.version}):s.push(o);s.forEach(o=>{U[o.app_id]=0,J(o.app_id,{status:"queued",progress:0,version:o.version,error:void 0}),ft(o.app_id)}),K("catalog",Object.keys(n).length,"apps, outdated",s.map(o=>o.app_id),"removed",r,`${Date.now()-e}ms`),X({type:"sync_complete",app_ids:Object.keys(n),removed:r}),G()}catch(t){console.warn("[miniapp-queue] sync catalog failed",t==null?void 0:t.message)}finally{ie=null}})()),ie),ht=async e=>{var r,s,o,c;if(me.has(e))return;me.add(e);let t=T.indexOf(e);t>=0&&T.splice(t,1),(w==null?void 0:w.app_id)===e&&w.handle.cancel();let n=(c=(o=(r=b.getState().downloads[e])==null?void 0:r.version)!=null?o:(s=x(e))==null?void 0:s.version)!=null?c:"";J(e,{status:"uninstalling",progress:0,version:n}),await ct(e),he(e),b.setState(l=>{let a={...l.downloads};return delete a[e],{downloads:a}}),delete U[e],me.delete(e),Ae(e,null),K("uninstalled",e),X({type:"uninstalled",app_id:e})},Yt=e=>{let{pause_reasons:t}=b.getState();t.includes(e)||(b.setState({pause_reasons:[...t,e]}),K("pause",e),t.length===0&&X({type:"pause_change",paused:!0,reasons:[e]}),w&&!w.forced&&w.handle.cancel())},Gt=e=>{let{pause_reasons:t}=b.getState();if(!t.includes(e))return;let n=t.filter(r=>r!==e);b.setState({pause_reasons:n}),K("resume",e),n.length===0&&X({type:"pause_change",paused:!1,reasons:n}),G()},mt=e=>b.getState().catalog[e],ke=async e=>{let t=mt(e);if(!t)return;if(await Te(t))return x(e);let n=new Promise(r=>{var s;((s=z[e])!=null?s:z[e]=[]).push(r)});return(w==null?void 0:w.app_id)===e?w.forced=!0:(U[e]=0,ft(e,{front:!0}),w&&!w.forced?w.handle.cancel():G(e)),n};import{Fragment as Mt,jsx as E,jsxs as ae}from"react/jsx-runtime";var De=e=>(e!=null?e:"").replace(/\?[^#]*/,""),At=0,rn=()=>{let e=new Set;return{emit:t=>e.forEach(n=>n(t)),subscribe:t=>(e.add(t),()=>{e.delete(t)})}},on=Ne.memo(({instance_key:e,is_active:t,is_front:n,is_dark:r,reload_tick:s,web_at_top:o,splash:c,bridge:l,opaque_background:a,onWebLoadEnd:f})=>{var je,He;let h=L(null),A=L(!1),m=B(D,p=>p.instances[e]),d=m==null?void 0:m.app.app_id,O=m==null?void 0:m.app.manifest_url,M=m==null?void 0:m.context,u=m==null?void 0:m.url_params,[i,v]=Q(()=>d?x(d):null),[V,Z]=Q(!1),[_t,Be]=Q(0),[vt,ee]=Q(0),[St,k]=Q(!1),$=L(null),Je=p=>{$.current&&clearTimeout($.current),$.current=setTimeout(()=>{$.current=null,k(!0)},p)};F(()=>()=>{$.current&&clearTimeout($.current)},[]),F(()=>{if(!d||!t&&i)return;let p=!0;return Z(!1),(async()=>{let g=x(d),R=g?await de(g):!1;if(!p||(v(R?I=>!I||I.version!==g.version||I.permissions.join(",")!==g.permissions.join(",")?g:I:null),__DEV__&&Date.now()-At>1e4&&(At=Date.now(),await Oe()),!p))return;let W=await ke(d),j=W!==void 0?W:O?await lt(d,O):x(d);if(p){if(!j){Z(!0);return}v(I=>I!=null?I:j)}})(),()=>{p=!1}},[t,d,O,_t]),F(()=>ut(e,p=>h.current?(h.current.postMessage(p),!0):!1),[e]);let bt=B(b,p=>{let g=d?p.downloads[d]:void 0;return(g==null?void 0:g.status)==="installed"?g.version:void 0});F(()=>{if(t||!d||!i)return;let p=x(d);if(!p||p.version===i.version)return;let g=!0;return de(p).then(R=>{!g||!R||(N(`webview:${e}`,"\u0111\u1ED5i bundle (\u1EA9n)",i.version,"\u2192",p.version),v(p))}),()=>{g=!1}},[t,d,bt,i==null?void 0:i.version]),F(()=>{var R;let p=(R=S().keep_alive)==null?void 0:R.idle_close_ms;if(t||!p||p<=0)return;let g=setTimeout(()=>{he(e)},p);return()=>clearTimeout(g)},[t,e]),F(()=>{s>0&&(Z(!1),k(!1),ee(p=>p+1),Be(p=>p+1))},[s]);let Ve=L(t);F(()=>{var p;Ve.current!==t&&(Ve.current=t,A.current&&((p=h.current)==null||p.injectJavaScript(Ze(t?"resumed":"paused"))))},[t]);let pe=`${(je=i==null?void 0:i.version)!=null?je:"none"}:${(He=i==null?void 0:i.permissions.join(","))!=null?He:""}:${vt}`,te=we(()=>JSON.stringify([M!=null?M:{},u!=null?u:{}]),[M,u]),Me=we(()=>{var p;return ot(u!=null?u:{},(p=i==null?void 0:i.permissions)!=null?p:[])},[te,i==null?void 0:i.permissions]),xt=we(()=>nt(M!=null?M:{},Me)+Xe()+(S().debug?Ge():""),[Me]),ce=L(null),We=L(null);F(()=>{var g,R,W;if(!i)return;if(We.current!==pe){We.current=pe,ce.current=te;return}if(ce.current===te)return;let p=((R=JSON.parse((g=ce.current)!=null?g:"[]")[0])!=null?R:{}).org_id;if(ce.current=te,p===(M==null?void 0:M.org_id)&&A.current){k(!1),Je(1500),(W=h.current)==null||W.injectJavaScript(et(M!=null?M:{},Me));return}k(!1),ee(j=>j+1)},[te,i,pe]);let Et=Le(async p=>{var R,W,j,I,ye;let g=ze(p.nativeEvent.data);if(!g){if(d&&(l!=null&&l.onWebEvent))try{Promise.resolve(l.onWebEvent(p.nativeEvent.data,{app_id:d,instance_id:e})).catch(y=>{console.warn("[miniapp] onWebEvent l\u1ED7i",d,y)})}catch(y){console.warn("[miniapp] onWebEvent l\u1ED7i",d,y)}return}if(g.method==="log"){let{level:y,text:P}=g;N(`web:${e}`,y!=null?y:"log",P!=null?P:"");return}if(g.method==="pong"){$.current||k(!0);return}if(g.method==="touchAtTop"){o.emit(!!g.at_top);return}if(g.method==="contextApplied"){$.current&&clearTimeout($.current),$.current=null,k(!0);return}if(g.method==="ready"){A.current=!0,k(!0);let y=(R=D.getState().instances[e])==null?void 0:R.context;y&&((W=h.current)==null||W.injectJavaScript(be(y)));return}try{let y=await it(g,{getHostData:()=>{var P,H;return(H=(P=D.getState().instances[e])==null?void 0:P.host_data)!=null?H:{}},getPermissions:()=>{var P,H;return d?(H=(P=x(d))==null?void 0:P.permissions)!=null?H:[]:[]},is_dark:r,close:oe,app_id:d!=null?d:"",instance_id:e,options:l});g.id&&((j=h.current)==null||j.injectJavaScript(Qe(g.id,y)))}catch(y){if(!g.id)return;let P=y==null?void 0:y.code,H=y instanceof _?y:new _(typeof P=="string"?P:"HOST_ERROR",String((I=y==null?void 0:y.message)!=null?I:y));(ye=h.current)==null||ye.injectJavaScript(Ye(g.id,H))}},[e,r,d,o,l]),Tt=Le(()=>{Z(!1),ee(p=>p+1),Be(p=>p+1)},[]);return ae($e,{style:[Fe.absoluteFill,a&&{backgroundColor:r?"#09090B":"#FFFFFF"},!n&&C.behind],pointerEvents:t?"auto":"none",children:[i?E(nn,{ref:h,source:{uri:i.entry_uri},originWhitelist:["*"],allowingReadAccessToURL:`file://${i.dir}`,allowFileAccess:!0,allowFileAccessFromFileURLs:!0,allowUniversalAccessFromFileURLs:!0,injectedJavaScriptBeforeContentLoaded:xt,onMessage:Et,bounces:!1,overScrollMode:"never",onLoadStart:p=>{N(`webview:${e}`,"load start",De(p.nativeEvent.url)),A.current=!1,k(!1)},onError:p=>{N(`webview:${e}`,"load error",De(p.nativeEvent.url),p.nativeEvent.description),Z(!0),k(!1)},onLoadEnd:p=>{let g=p.nativeEvent.url;N(`webview:${e}`,"load end",De(g)),d&&(f==null||f({app_id:d,instance_id:e,url:g})),Je(1500)},onContentProcessDidTerminate:()=>{A.current=!1,k(!1),ee(p=>p+1)},onRenderProcessGone:()=>(A.current=!1,k(!1),ee(p=>p+1),!0),style:C.webview},pe):null,m&&E(an,{visible:!i||!St,interactive:V,children:E(sn,{splash:c,app:m.app,is_dark:r,error:V,has_bundle:!!i,retry:Tt})})]})}),sn=Ne.memo(({splash:e,app:t,is_dark:n,error:r,has_bundle:s,retry:o})=>{let c=e,l=Ce(t.app_id),a=r?"error":!s&&(l==null?void 0:l.status)==="downloading"?"downloading":"loading";return E(c,{app:t,is_dark:n,status:a,progress:a==="downloading"?l==null?void 0:l.progress:void 0,retry:o})}),an=({visible:e,interactive:t,children:n})=>{let r=L(new Ie.Value(e?1:0)).current,[s,o]=Q(e);return F(()=>{if(e){o(!0),r.setValue(1);return}let c=Ie.timing(r,{toValue:0,duration:180,useNativeDriver:!0});return c.start(({finished:l})=>{l&&o(!1)}),()=>c.stop()},[e,r]),s?E(Ie.View,{style:[Fe.absoluteFill,{opacity:r}],pointerEvents:t?"auto":"none",children:n}):null},yt=({app:e,is_dark:t,status:n,progress:r,retry:s})=>{let o=t?"#FAFAFA":"#18181B";return ae($e,{style:[C.splash,{backgroundColor:t?"#09090B":"#FFFFFF"}],children:[E($e,{style:[C.splash_icon,{backgroundColor:t?"#18181B":"#F4F4F5"}],children:e.icon?E(en,{source:{uri:e.icon},style:C.splash_icon_image}):E(se,{style:C.splash_letter,children:(e.name||"?").slice(0,1).toUpperCase()})}),E(se,{style:[C.splash_name,{color:o}],children:e.name}),n==="error"?ae(Mt,{children:[E(se,{style:C.splash_hint,children:"Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c mini app"}),E(tn,{activeOpacity:.7,style:[C.retry_button,{backgroundColor:t?"#27272A":"#F4F4F5"}],onPress:s,children:E(se,{style:[C.retry_text,{color:o}],children:"Th\u1EED l\u1EA1i"})})]}):ae(Mt,{children:[E(Xt,{style:C.splash_spinner,color:t?"#A1A1AA":"#71717A"}),n==="downloading"&&ae(se,{style:C.splash_hint,children:["\u0110ang t\u1EA3i mini app",r?` ${Math.round(r*100)}%`:"\u2026"]})]})]})},wt=(e,t)=>{let n=L(t),r=L(!1);__DEV__&&!r.current&&n.current!==t&&(r.current=!0,console.warn(`[miniapp] MiniAppHost prop "${e}" \u0111\u1ED5i gi\u1EEFa c\xE1c l\u1EA7n render \u2192 m\u1ECDi WebView b\u1ECB mount l\u1EA1i. Khai b\xE1o component b\xEAn ngo\xE0i render.`))},pn=({container:e,splash:t=yt,is_dark:n=!1,bridge:r,close_on_back:s=!0,opaque_background:o=!0,onWebLoadEnd:c})=>{wt("container",e),wt("splash",t);let l=e,a=B(D,i=>i.active_key),f=L(a);a&&(f.current=a);let h=B(D,i=>Object.keys(i.instances).join("|")),A=B(D,i=>{var v;return i.active_key?(v=i.instances[i.active_key])==null?void 0:v.app.name:void 0}),m=we(()=>h?h.split("|"):[],[h]),[d,O]=Q({}),M=L(rn()).current;F(()=>{if(!a||!s)return;let i=Zt.addEventListener("hardwareBackPress",()=>(oe(),!0));return()=>i.remove()},[a,s]);let u=Le(()=>{let i=D.getState().active_key;i&&O(v=>({...v,[i]:(v[i]||0)+1}))},[]);return m.length?E(l,{visible:!!a,title:A!=null?A:"",is_dark:n,close:oe,reload:u,subscribeWebAtTop:M.subscribe,children:m.map(i=>E(on,{instance_key:i,is_active:a===i,is_front:(a!=null?a:f.current)===i,is_dark:n,reload_tick:d[i]||0,web_at_top:M,splash:t,bridge:r,opaque_background:o,onWebLoadEnd:c},i))}):null},C=Fe.create({webview:{flex:1,backgroundColor:"transparent"},behind:{zIndex:-1},splash:{flex:1,alignItems:"center",justifyContent:"center",gap:12},splash_icon:{width:72,height:72,borderRadius:20,alignItems:"center",justifyContent:"center",overflow:"hidden"},splash_icon_image:{width:72,height:72},splash_letter:{fontSize:28,fontWeight:"700",color:"#1D4ED8"},splash_name:{fontSize:16,fontWeight:"600"},splash_hint:{color:"#71717A"},splash_spinner:{marginTop:8},retry_button:{marginTop:4,paddingHorizontal:20,paddingVertical:10,borderRadius:999},retry_text:{fontWeight:"600"}}),cn=Ne.memo(pn);export{yt as DefaultMiniAppSplash,_e as MINIAPP_PLATFORM_URL,cn as MiniAppHost,_ as MiniAppHostError,oe as closeMiniApp,Rt as configureMiniApp,Ct as createMmkvStorage,Pt as createRnfsFileSystem,ke as ensureMiniApp,x as getLocalMiniApp,mt as getMiniAppCatalogEntry,Kt as getMiniAppStatuses,Ut as onMiniAppEvent,Bt as openMiniApp,Yt as pauseMiniAppDownloads,Jt as preloadMiniApp,Gt as resumeMiniAppDownloads,$t as sendEventToWeb,Oe as syncMiniAppCatalog,ht as uninstallMiniApp,Ce as useMiniAppDownload,qt as useMiniAppDownloadsPaused};
45
+ true;`},at={partner:"partner_token",chatbox:"chatbox_token"},pt=(e,t)=>{let n={...e};for(let r of Object.values(at))t.includes(r)||delete n[r];return n},Ee=new Set,Ge=async(e,t)=>{if(Ee.has(e))throw new _("BUSY",`${e} \u0111ang ch\u1EA1y \u2014 ch\u1EDD l\u01B0\u1EE3t tr\u01B0\u1EDBc xong`);Ee.add(e);try{return await t()}finally{Ee.delete(e)}},Te=(e,t)=>{if(typeof e!="string"||!e)throw new _("INVALID_PARAMS",`Thi\u1EBFu ${t}`);return e},ct=async({method:e,params:t},{getHostData:n,getPermissions:r,is_dark:a,close:o,app_id:l,instance_id:s,options:p})=>{var m,d,k,w;let g=p==null?void 0:p.handlers,h={app_id:l,instance_id:s,close:o},M=()=>new _("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF \u1EE9ng d\u1EE5ng n\xE0y`);switch(e){case"requestPayment":{let u=g==null?void 0:g.requestPayment;if(!u)throw M();let i=t==null?void 0:t.amount;if(typeof i!="number"||!Number.isFinite(i)||i<=0)throw new _("INVALID_PARAMS","amount ph\u1EA3i l\xE0 s\u1ED1 > 0");let x={...t,amount:i,currency:Te(t==null?void 0:t.currency,"currency")};return Ge(e,()=>u(x,h))}case"printImage":{let u=g==null?void 0:g.printImage;if(!u)throw M();let i=Te(t==null?void 0:t.image,"image");await Ge(e,()=>u({image:i},h));return}case"openScreen":if(!(g!=null&&g.openScreen))throw M();await g.openScreen({screen:Te(t==null?void 0:t.screen,"screen"),params:t==null?void 0:t.params},h);return;case"closeApp":o();return;case"openWebview":{let u=String((m=t==null?void 0:t.url)!=null?m:"");if(!/^https?:\/\//i.test(u))throw new _("INVALID_PARAMS","url ph\u1EA3i l\xE0 http(s)");await(p!=null&&p.openUrl?p.openUrl(u):Dt.openURL(u));return}case"showToast":(k=p==null?void 0:p.showToast)==null||k.call(p,String((d=t==null?void 0:t.message)!=null?d:""));return;case"getSystemInfo":return{platform:Lt.OS==="ios"?"ios":"android",appVersion:(w=p==null?void 0:p.app_version)!=null?w:"",theme:a?"dark":"light"};case"getAccessToken":{let u=n().access_token;if(!u)throw new _("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return u}case"getToken":{let u=t==null?void 0:t.type;if(u==="access"){let q=n().access_token;if(!q)throw new _("HOST_ERROR","Mini app ch\u01B0a c\xF3 token cho page n\xE0y");return q}if(u!=="partner"&&u!=="chatbox")throw new _("HOST_ERROR",`Lo\u1EA1i token kh\xF4ng h\u1EE3p l\u1EC7: ${String(u)}`);let i=at[u];if(!r().includes(i))throw new _("PERMISSION_DENIED",`Mini app ch\u01B0a \u0111\u01B0\u1EE3c c\u1EA5p quy\u1EC1n ${i} (Console \u2192 Quy\u1EC1n l\u1EA5y token)`);let x=u==="partner"?n().partner_token:n().chatbox_token;if(!x)throw new _("HOST_ERROR",`Kh\xF4ng c\xF3 ${i}`);return x}case"getUserInfo":{let u=n().user;if(!u)throw new _("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin nh\xE2n vi\xEAn");return u}case"getPageInfo":{let u=n().page;if(!u)throw new _("HOST_ERROR","Kh\xF4ng l\u1EA5y \u0111\u01B0\u1EE3c th\xF4ng tin page");return u}case"sendMessage":case"insertText":throw new _("NOT_SUPPORTED",`${e} ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF phi\xEAn b\u1EA3n app n\xE0y`);default:throw new _("NOT_SUPPORTED",`API kh\xF4ng t\u1ED3n t\u1EA1i: ${e}`)}};var Pe=e=>`bundle:${e}`,Ce=()=>`${S().file_system.document_dir}/miniapps`,dt=(e,t,n="index.html",r=!1,a=[])=>{let o=`${Ce()}/${e}/${t}`;return{app_id:e,version:t,dir:o,entry_uri:`file://${o}/${n}`,context_update:r,permissions:a}},lt=e=>{var t;S().storage.setString(Pe(e.app_id),JSON.stringify({version:e.version,entry:e.entry,context_update:!!e.context_update,permissions:(t=e.permissions)!=null?t:[]}))},$t=(e,t)=>/^https?:\/\//.test(t)?t:`${e.replace(/[^/]*$/,"")}${t}`,b=e=>{let t=S().storage.getString(Pe(e));if(!t)return null;try{let{version:n,entry:r,context_update:a,permissions:o}=JSON.parse(t);return dt(e,n,r,!!a,Array.isArray(o)?o:[])}catch{return null}},fe=e=>S().file_system.exists(e.entry_uri.replace("file://","")),Oe=async e=>{let t=b(e.app_id);return(t==null?void 0:t.version)===e.version&&await fe(t)},Nt=async(e,t)=>{let n=S().file_system,r=`${Ce()}/${e}`,a=await n.listDir(r).catch(()=>[]);await Promise.all(a.filter(o=>!t.includes(o)).map(o=>n.remove(`${r}/${o}`).catch(()=>{})))},gt=async e=>{var t;await((t=se[e])==null?void 0:t.catch(()=>{})),S().storage.setString(Pe(e),""),await S().file_system.remove(`${Ce()}/${e}`).catch(()=>{})},ee=class extends Error{constructor(){super("cancelled"),this.name="MiniAppInstallCancelled"}},se={},ke=(e,{base_url:t,onProgress:n}={})=>{var m;let r=S().file_system,a=null,o=!1,l=`${r.cache_dir}/${e.app_id}-${e.version}.zip`,s=()=>{if(o)throw new ee},p=async()=>{var w;s();let d=b(e.app_id);if((d==null?void 0:d.version)===e.version&&await r.exists(d.dir))return lt(e),b(e.app_id);s();let k=r.download({url:t?$t(t,e.bundle_url):e.bundle_url,to_file:l,onProgress:(u,i)=>{var q;let x=i>0?i:(q=e.size)!=null?q:0;x>0&&(n==null||n(Math.min(1,u/x)))}});a=k;try{let{status:u}=await k.promise;if(s(),u!==200)throw new Error(`bundle ${u}`);if(e.sha256)if(r.sha256){if(await r.sha256(l)!==e.sha256)throw new Error("sha256 mismatch")}else B("b\u1ECF qua ki\u1EC3m tra sha256 (file_system kh\xF4ng c\xF3 sha256)",e.app_id);s();let i=dt(e.app_id,e.version,e.entry,!!e.context_update,(w=e.permissions)!=null?w:[]);return await r.remove(i.dir).catch(()=>{}),await r.mkdir(i.dir),await r.unzip(l,i.dir),lt(e),Nt(e.app_id,[e.version,d==null?void 0:d.version].filter(Boolean)),i}catch(u){throw o?new ee:u}finally{a=null,r.remove(l).catch(()=>{})}},h=((m=se[e.app_id])!=null?m:Promise.resolve()).catch(()=>{}).then(p),M=h.catch(()=>{});return se[e.app_id]=M,M.then(()=>{se[e.app_id]===M&&delete se[e.app_id]}),{promise:h,cancel:()=>{o=!0,a==null||a.cancel()}}},oe={},Ft=__DEV__?0:60*1e3,ut={},ft=(e,t)=>{var r,a;let n=b(e);return n&&Date.now()-((r=ut[t])!=null?r:0)<Ft?Promise.resolve(n):((a=oe[e])!=null||(oe[e]=(async()=>{let o=await fetch(t,{headers:{"Cache-Control":"no-cache"}});if(!o.ok)throw new Error(`manifest ${o.status}`);let l=await o.json(),s=await ke(l,{base_url:t}).promise;return ut[t]=Date.now(),s})().catch(o=>(console.warn("[miniapp] sync failed",e,o==null?void 0:o.message),b(e))).finally(()=>{oe[e]=void 0})),oe[e])};var he=new Map,ht=(e,t)=>(he.set(e,t),()=>{he.get(e)===t&&he.delete(e)}),Bt=(e,t)=>{let n=he.get(e);return n?n(t):!1};import{useRef as Jt,useSyncExternalStore as Vt}from"react";var Ae=e=>{let t=e,n=new Set;return{getState:()=>t,setState:r=>{let a=typeof r=="function"?r(t):r;t={...t,...a},n.forEach(o=>o())},subscribe:r=>(n.add(r),()=>{n.delete(r)})}},W=(e,t,n=Object.is)=>{let r=Jt(null),a=()=>{let o=e.getState(),l=r.current;if(l&&l.state===o&&l.selector===t)return l.value;let s=t(o),p=l&&n(l.value,s)?l.value:s;return r.current={state:o,selector:t,value:p},p};return Vt(e.subscribe,a)};var L=Ae({active_key:null,instances:{}}),At=({app:e,instance_id:t,context:n={},url_params:r={},host_data:a={}},o)=>{var s;let l=(s=S().keep_alive)==null?void 0:s.max_webviews;L.setState(p=>{let g=t!=null?t:e.app_id,h={...p.instances,[g]:{key:g,app:e,context:n,url_params:r,host_data:a,last_used_at:Date.now()}},M=Object.keys(h);return l&&l>0&&M.length>l&&M.filter(m=>m!==g).sort((m,d)=>h[m].last_used_at-h[d].last_used_at).slice(0,M.length-l).forEach(m=>{delete h[m]}),o?{active_key:g,instances:h}:{instances:h}})},Wt=e=>At(e,!0),jt=e=>At(e,!1),ie=()=>L.setState({active_key:null}),me=e=>{L.setState(t=>{if(t.active_key===e||!t.instances[e])return{};let n={...t.instances};return delete n[e],{instances:n}})};var mt="catalog",qt="paused_apps",Ht="removed_apps",Ut=10*1e3,Kt=2,zt=3e3,Yt=()=>{var e;try{return JSON.parse((e=S().storage.getString(mt))!=null?e:"{}")}catch{return{}}},v=Ae({catalog:{},downloads:{},pause_reasons:[]}),Mt=e=>{let t=new Set,n=()=>S().storage.setString(e,JSON.stringify([...t]));return{has:r=>t.has(r),values:()=>[...t],add:r=>t.has(r)?!1:(t.add(r),n(),!0),delete:r=>t.delete(r)?(n(),!0):!1,load:()=>{var r;t.clear();try{let a=JSON.parse((r=S().storage.getString(e))!=null?r:"[]");Array.isArray(a)&&a.forEach(o=>{typeof o=="string"&&t.add(o)})}catch{}}}},$=Mt(qt),K=Mt(Ht);Qe(()=>{$.load(),K.load();let e=Yt(),t={};Object.keys(e).filter(n=>!K.has(n)).forEach(n=>{let r=b(n);r?t[n]={status:"installed",progress:1,version:r.version,has_local:!0}:$.has(n)&&(t[n]={status:"paused",progress:0,version:e[n].version,has_local:!1})}),v.setState({catalog:e,downloads:t})});var De=e=>W(v,t=>e?t.downloads[e]:void 0),Qt=()=>W(v,e=>e.pause_reasons.length>0),J=(...e)=>B("queue",...e),E=[],j={},A=null,Me=new Set,G={},Ie=new Set,X=e=>{Ie.forEach(t=>{try{t(e)}catch(n){console.warn("[miniapp-queue] event listener error",n==null?void 0:n.message)}})},Gt=e=>(Ie.add(e),()=>{Ie.delete(e)}),Xt=()=>v.getState().downloads,C=(e,t)=>{let n=!!b(e),r=v.getState().downloads[e],a=t.status==="downloading"&&n?"updating":t.status,o={...r!=null?r:{status:"queued",progress:0},...t,...a?{status:a}:{},has_local:n};v.setState(l=>({downloads:{...l.downloads,[e]:o}})),(r==null?void 0:r.status)!==o.status||(r==null?void 0:r.version)!==o.version||(r==null?void 0:r.has_local)!==o.has_local?X({type:"status_change",app_id:e,state:o}):r.progress!==o.progress&&X({type:"progress",app_id:e,progress:o.progress,version:o.version})},we=(e,t)=>{var n;(n=G[e])==null||n.forEach(r=>r(t)),delete G[e]},Zt=()=>v.getState().pause_reasons.length>0,U=e=>{var s;if(A)return;let t=e?E.indexOf(e):Zt()?-1:E.findIndex(p=>!$.has(p));if(t<0||t>=E.length)return;let[n]=E.splice(t,1),r=v.getState().catalog[n];if(!r){we(n,b(n)),U();return}let a=Date.now();j[n]=((s=j[n])!=null?s:0)+1,C(n,{status:"downloading",progress:0,version:r.version,error:void 0});let o=0,l=ke(r,{onProgress:p=>{let g=Math.floor(p*100);g!==o&&(o=g,C(n,{progress:g/100,version:r.version}))}});A={app_id:n,handle:l,forced:!!e},J("start",n,r.version,e?"(forced)":""),l.promise.then(p=>{J("installed",n,r.version,`${Date.now()-a}ms`),C(n,{status:"installed",progress:1,version:r.version}),we(n,p)}).catch(p=>{var h;if(p instanceof ee){if(Me.has(n))return;J("paused",n),j[n]-=1,E.unshift(n),C(n,{status:$.has(n)?"paused":"queued",progress:0,version:r.version});return}let g=String((h=p==null?void 0:p.message)!=null?h:p);if(console.warn("[miniapp-queue] failed",n,g),j[n]<Kt){C(n,{status:"queued",progress:0,version:r.version,error:g}),setTimeout(()=>{var M;E.includes(n)||(A==null?void 0:A.app_id)===n||(E.push(n),U((M=G[n])!=null&&M.length?n:void 0))},zt);return}C(n,{status:"failed",progress:0,version:r.version,error:g}),we(n,b(n))}).finally(()=>{A=null;let p=E.find(g=>{var h;return(h=G[g])==null?void 0:h.length});U(p)})},ye=(e,{front:t=!1}={})=>{if((A==null?void 0:A.app_id)===e)return;let n=E.indexOf(e);if(n>=0){if(!t)return;E.splice(n,1)}t?E.unshift(e):E.push(e)},en=async e=>{let{host_id:t,client_token:n}=S(),r=new AbortController,a=setTimeout(()=>r.abort(),Ut);try{let o=`${xe}/api/hosts/${encodeURIComponent(t)}/miniapps?channel=${e}`,l=await fetch(o,{headers:{Authorization:`Bearer ${n}`,"Cache-Control":"no-cache"},signal:r.signal});if(!l.ok)throw new Error(`host list ${e} ${l.status}`);return(await l.json()).apps.map(p=>({...p,channel:e}))}finally{clearTimeout(a)}},ae=null,Le=()=>(ae!=null||(ae=(async()=>{var t;let e=Date.now();try{let n=await Promise.all(S().channels.map(en)),r={};[...n].reverse().flat().forEach(s=>{r[s.app_id]=s});let a=Object.keys(v.getState().catalog).filter(s=>!r[s]);S().storage.setString(mt,JSON.stringify(r)),v.setState({catalog:r}),await Promise.all(a.map(s=>wt(s,{by_user:!1}))),a.forEach(s=>K.delete(s));let o=Object.keys(r).filter(s=>!K.has(s)),l=[];for(let s of o.map(p=>r[p]))await Oe(s)?C(s.app_id,{status:"installed",progress:1,version:s.version}):l.push(s);return l.forEach(s=>{j[s.app_id]=0,C(s.app_id,{status:$.has(s.app_id)?"paused":"queued",progress:0,version:s.version,error:void 0}),ye(s.app_id)}),J("catalog",o.length,"apps, outdated",l.map(s=>s.app_id),"removed",a,`${Date.now()-e}ms`),X({type:"sync_complete",app_ids:o,removed:a}),U(),{ok:!0,app_ids:o,removed:a}}catch(n){let r=String((n==null?void 0:n.name)==="AbortError"?"timeout":(t=n==null?void 0:n.message)!=null?t:n);return console.warn("[miniapp-queue] sync catalog failed",r),X({type:"sync_failed",error:r}),{ok:!1,error:r}}finally{ae=null}})()),ae),wt=async(e,{by_user:t})=>{var a,o,l,s;if(t&&K.add(e),Me.has(e))return;Me.add(e),$.delete(e);let n=E.indexOf(e);n>=0&&E.splice(n,1),(A==null?void 0:A.app_id)===e&&A.handle.cancel();let r=(s=(l=(a=v.getState().downloads[e])==null?void 0:a.version)!=null?l:(o=b(e))==null?void 0:o.version)!=null?s:"";C(e,{status:"uninstalling",progress:0,version:r}),await gt(e),me(e),v.setState(p=>{let g={...p.downloads};return delete g[e],{downloads:g}}),delete j[e],Me.delete(e),we(e,null),J("uninstalled",e,t?"(user)":"(not in list)"),X({type:"uninstalled",app_id:e})},tn=e=>wt(e,{by_user:!0}),nn=e=>{let t=ve(e);return t?(K.delete(e),(A==null?void 0:A.app_id)===e||E.includes(e)||(j[e]=0,C(e,{status:$.has(e)?"paused":"queued",progress:0,version:t.version,error:void 0}),ye(e),U(),J("restore",e)),!0):!1},rn=e=>{if($.has(e))return;if($.add(e),J("pause app",e),(A==null?void 0:A.app_id)===e&&!A.forced){A.handle.cancel();return}let t=v.getState().downloads[e];E.includes(e)&&t&&C(e,{status:"paused",progress:0,version:t.version})},on=e=>{if(!$.delete(e))return;J("resume app",e);let t=v.getState().downloads[e];(t==null?void 0:t.status)==="paused"&&!E.includes(e)&&ve(e)&&(j[e]=0,ye(e)),E.includes(e)&&t&&C(e,{status:"queued",progress:0,version:t.version}),U()},sn=e=>{let{pause_reasons:t}=v.getState();t.includes(e)||(v.setState({pause_reasons:[...t,e]}),J("pause",e),t.length===0&&X({type:"pause_change",paused:!0,reasons:[e]}),A&&!A.forced&&A.handle.cancel())},an=e=>{let{pause_reasons:t}=v.getState();if(!t.includes(e))return;let n=t.filter(r=>r!==e);v.setState({pause_reasons:n}),J("resume",e),n.length===0&&X({type:"pause_change",paused:!1,reasons:n}),U()},pn=()=>Object.values(v.getState().catalog).map(e=>({...e,installed:!!b(e.app_id),removed_by_user:K.has(e.app_id)})),ve=e=>v.getState().catalog[e],$e=async e=>{let t=ve(e);if(!t)return;if($.delete(e),K.delete(e),await Oe(t))return b(e);let n=new Promise(r=>{var a;((a=G[e])!=null?a:G[e]=[]).push(r)});return(A==null?void 0:A.app_id)===e?A.forced=!0:(j[e]=0,ye(e,{front:!0}),A&&!A.forced?A.handle.cancel():U(e)),n};import{Fragment as St,jsx as T,jsxs as ce}from"react/jsx-runtime";var Fe=e=>(e!=null?e:"").replace(/\?[^#]*/,""),yt=0,fn=()=>{let e=new Set;return{emit:t=>e.forEach(n=>n(t)),subscribe:t=>(e.add(t),()=>{e.delete(t)})}},hn=Ve.memo(({instance_key:e,is_active:t,is_front:n,is_dark:r,reload_tick:a,web_at_top:o,splash:l,bridge:s,opaque_background:p,onWebLoadEnd:g})=>{var Ke,ze;let h=N(null),M=N(!1),m=W(L,c=>c.instances[e]),d=m==null?void 0:m.app.app_id,k=m==null?void 0:m.app.manifest_url,w=m==null?void 0:m.context,u=m==null?void 0:m.url_params,[i,x]=Z(()=>d?b(d):null),[q,te]=Z(!1),[bt,je]=Z(0),[xt,ne]=Z(0),[Et,I]=Z(!1),F=N(null),qe=c=>{F.current&&clearTimeout(F.current),F.current=setTimeout(()=>{F.current=null,I(!0)},c)};V(()=>()=>{F.current&&clearTimeout(F.current)},[]),V(()=>{if(!d||!t&&i)return;let c=!0;return te(!1),(async()=>{let f=b(d),R=f?await fe(f):!1;if(!c||(x(R?D=>!D||D.version!==f.version||D.permissions.join(",")!==f.permissions.join(",")?f:D:null),__DEV__&&Date.now()-yt>1e4&&(yt=Date.now(),await Le()),!c))return;let H=await $e(d),z=H!==void 0?H:k?await ft(d,k):b(d);if(c){if(!z){te(!0);return}x(D=>D!=null?D:z)}})(),()=>{c=!1}},[t,d,k,bt]),V(()=>ht(e,c=>h.current?(h.current.postMessage(c),!0):!1),[e]);let Tt=W(v,c=>{let f=d?c.downloads[d]:void 0;return(f==null?void 0:f.status)==="installed"?f.version:void 0});V(()=>{if(t||!d||!i)return;let c=b(d);if(!c||c.version===i.version)return;let f=!0;return fe(c).then(R=>{!f||!R||(B(`webview:${e}`,"\u0111\u1ED5i bundle (\u1EA9n)",i.version,"\u2192",c.version),x(c))}),()=>{f=!1}},[t,d,Tt,i==null?void 0:i.version]),V(()=>{var R;let c=(R=S().keep_alive)==null?void 0:R.idle_close_ms;if(t||!c||c<=0)return;let f=setTimeout(()=>{me(e)},c);return()=>clearTimeout(f)},[t,e]),V(()=>{a>0&&(te(!1),I(!1),ne(c=>c+1),je(c=>c+1))},[a]);let He=N(t);V(()=>{var c;He.current!==t&&(He.current=t,M.current&&((c=h.current)==null||c.injectJavaScript(rt(t?"resumed":"paused"))))},[t]);let le=`${(Ke=i==null?void 0:i.version)!=null?Ke:"none"}:${(ze=i==null?void 0:i.permissions.join(","))!=null?ze:""}:${xt}`,re=Se(()=>JSON.stringify([w!=null?w:{},u!=null?u:{}]),[w,u]),_e=Se(()=>{var c;return pt(u!=null?u:{},(c=i==null?void 0:i.permissions)!=null?c:[])},[re,i==null?void 0:i.permissions]),Rt=Se(()=>it(w!=null?w:{},_e)+nt()+(S().debug?tt():""),[_e]),ue=N(null),Ue=N(null);V(()=>{var f,R,H;if(!i)return;if(Ue.current!==le){Ue.current=le,ue.current=re;return}if(ue.current===re)return;let c=((R=JSON.parse((f=ue.current)!=null?f:"[]")[0])!=null?R:{}).org_id;if(ue.current=re,c===(w==null?void 0:w.org_id)&&M.current){I(!1),qe(1500),(H=h.current)==null||H.injectJavaScript(ot(w!=null?w:{},_e));return}I(!1),ne(z=>z+1)},[re,i,le]);let Pt=Be(async c=>{var R,H,z,D,be;let f=Xe(c.nativeEvent.data);if(!f){if(d&&(s!=null&&s.onWebEvent))try{Promise.resolve(s.onWebEvent(c.nativeEvent.data,{app_id:d,instance_id:e})).catch(y=>{console.warn("[miniapp] onWebEvent l\u1ED7i",d,y)})}catch(y){console.warn("[miniapp] onWebEvent l\u1ED7i",d,y)}return}if(f.method==="log"){let{level:y,text:P}=f;B(`web:${e}`,y!=null?y:"log",P!=null?P:"");return}if(f.method==="pong"){F.current||I(!0);return}if(f.method==="touchAtTop"){o.emit(!!f.at_top);return}if(f.method==="contextApplied"){F.current&&clearTimeout(F.current),F.current=null,I(!0);return}if(f.method==="ready"){M.current=!0,I(!0);let y=(R=L.getState().instances[e])==null?void 0:R.context;y&&((H=h.current)==null||H.injectJavaScript(Re(y)));return}try{let y=await ct(f,{getHostData:()=>{var P,Y;return(Y=(P=L.getState().instances[e])==null?void 0:P.host_data)!=null?Y:{}},getPermissions:()=>{var P,Y;return d?(Y=(P=b(d))==null?void 0:P.permissions)!=null?Y:[]:[]},is_dark:r,close:ie,app_id:d!=null?d:"",instance_id:e,options:s});f.id&&((z=h.current)==null||z.injectJavaScript(Ze(f.id,y)))}catch(y){if(!f.id)return;let P=y==null?void 0:y.code,Y=y instanceof _?y:new _(typeof P=="string"?P:"HOST_ERROR",String((D=y==null?void 0:y.message)!=null?D:y));(be=h.current)==null||be.injectJavaScript(et(f.id,Y))}},[e,r,d,o,s]),Ct=Be(()=>{te(!1),ne(c=>c+1),je(c=>c+1)},[]);return ce(Je,{style:[We.absoluteFill,p&&{backgroundColor:r?"#09090B":"#FFFFFF"},!n&&O.behind],pointerEvents:t?"auto":"none",children:[i?T(gn,{ref:h,source:{uri:i.entry_uri},originWhitelist:["*"],allowingReadAccessToURL:`file://${i.dir}`,allowFileAccess:!0,allowFileAccessFromFileURLs:!0,allowUniversalAccessFromFileURLs:!0,injectedJavaScriptBeforeContentLoaded:Rt,onMessage:Pt,bounces:!1,overScrollMode:"never",onLoadStart:c=>{B(`webview:${e}`,"load start",Fe(c.nativeEvent.url)),M.current=!1,I(!1)},onError:c=>{B(`webview:${e}`,"load error",Fe(c.nativeEvent.url),c.nativeEvent.description),te(!0),I(!1)},onLoadEnd:c=>{let f=c.nativeEvent.url;B(`webview:${e}`,"load end",Fe(f)),d&&(g==null||g({app_id:d,instance_id:e,url:f})),qe(1500)},onContentProcessDidTerminate:()=>{M.current=!1,I(!1),ne(c=>c+1)},onRenderProcessGone:()=>(M.current=!1,I(!1),ne(c=>c+1),!0),style:O.webview},le):null,m&&T(mn,{visible:!i||!Et,interactive:q,children:T(An,{splash:l,app:m.app,is_dark:r,error:q,has_bundle:!!i,retry:Ct})})]})}),An=Ve.memo(({splash:e,app:t,is_dark:n,error:r,has_bundle:a,retry:o})=>{let l=e,s=De(t.app_id),p=r?"error":!a&&(s==null?void 0:s.status)==="downloading"?"downloading":"loading";return T(l,{app:t,is_dark:n,status:p,progress:p==="downloading"?s==null?void 0:s.progress:void 0,retry:o})}),mn=({visible:e,interactive:t,children:n})=>{let r=N(new Ne.Value(e?1:0)).current,[a,o]=Z(e);return V(()=>{if(e){o(!0),r.setValue(1);return}let l=Ne.timing(r,{toValue:0,duration:180,useNativeDriver:!0});return l.start(({finished:s})=>{s&&o(!1)}),()=>l.stop()},[e,r]),a?T(Ne.View,{style:[We.absoluteFill,{opacity:r}],pointerEvents:t?"auto":"none",children:n}):null},_t=({app:e,is_dark:t,status:n,progress:r,retry:a})=>{let o=t?"#FAFAFA":"#18181B";return ce(Je,{style:[O.splash,{backgroundColor:t?"#09090B":"#FFFFFF"}],children:[T(Je,{style:[O.splash_icon,{backgroundColor:t?"#18181B":"#F4F4F5"}],children:e.icon?T(un,{source:{uri:e.icon},style:O.splash_icon_image}):T(pe,{style:O.splash_letter,children:(e.name||"?").slice(0,1).toUpperCase()})}),T(pe,{style:[O.splash_name,{color:o}],children:e.name}),n==="error"?ce(St,{children:[T(pe,{style:O.splash_hint,children:"Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c mini app"}),T(dn,{activeOpacity:.7,style:[O.retry_button,{backgroundColor:t?"#27272A":"#F4F4F5"}],onPress:a,children:T(pe,{style:[O.retry_text,{color:o}],children:"Th\u1EED l\u1EA1i"})})]}):ce(St,{children:[T(cn,{style:O.splash_spinner,color:t?"#A1A1AA":"#71717A"}),n==="downloading"&&ce(pe,{style:O.splash_hint,children:["\u0110ang t\u1EA3i mini app",r?` ${Math.round(r*100)}%`:"\u2026"]})]})]})},vt=(e,t)=>{let n=N(t),r=N(!1);__DEV__&&!r.current&&n.current!==t&&(r.current=!0,console.warn(`[miniapp] MiniAppHost prop "${e}" \u0111\u1ED5i gi\u1EEFa c\xE1c l\u1EA7n render \u2192 m\u1ECDi WebView b\u1ECB mount l\u1EA1i. Khai b\xE1o component b\xEAn ngo\xE0i render.`))},Mn=({container:e,splash:t=_t,is_dark:n=!1,bridge:r,close_on_back:a=!0,opaque_background:o=!0,onWebLoadEnd:l})=>{vt("container",e),vt("splash",t);let s=e,p=W(L,i=>i.active_key),g=N(p);p&&(g.current=p);let h=W(L,i=>Object.keys(i.instances).join("|")),M=W(L,i=>{var x;return i.active_key?(x=i.instances[i.active_key])==null?void 0:x.app.name:void 0}),m=Se(()=>h?h.split("|"):[],[h]),[d,k]=Z({}),w=N(fn()).current;V(()=>{if(!p||!a)return;let i=ln.addEventListener("hardwareBackPress",()=>(ie(),!0));return()=>i.remove()},[p,a]);let u=Be(()=>{let i=L.getState().active_key;i&&k(x=>({...x,[i]:(x[i]||0)+1}))},[]);return m.length?T(s,{visible:!!p,title:M!=null?M:"",is_dark:n,close:ie,reload:u,subscribeWebAtTop:w.subscribe,children:m.map(i=>T(hn,{instance_key:i,is_active:p===i,is_front:(p!=null?p:g.current)===i,is_dark:n,reload_tick:d[i]||0,web_at_top:w,splash:t,bridge:r,opaque_background:o,onWebLoadEnd:l},i))}):null},O=We.create({webview:{flex:1,backgroundColor:"transparent"},behind:{zIndex:-1},splash:{flex:1,alignItems:"center",justifyContent:"center",gap:12},splash_icon:{width:72,height:72,borderRadius:20,alignItems:"center",justifyContent:"center",overflow:"hidden"},splash_icon_image:{width:72,height:72},splash_letter:{fontSize:28,fontWeight:"700",color:"#1D4ED8"},splash_name:{fontSize:16,fontWeight:"600"},splash_hint:{color:"#71717A"},splash_spinner:{marginTop:8},retry_button:{marginTop:4,paddingHorizontal:20,paddingVertical:10,borderRadius:999},retry_text:{fontWeight:"600"}}),wn=Ve.memo(Mn);export{_t as DefaultMiniAppSplash,xe as MINIAPP_PLATFORM_URL,wn as MiniAppHost,_ as MiniAppHostError,ie as closeMiniApp,Ot as configureMiniApp,It as createMmkvStorage,kt as createRnfsFileSystem,$e as ensureMiniApp,b as getLocalMiniApp,pn as getMiniAppCatalog,ve as getMiniAppCatalogEntry,Xt as getMiniAppStatuses,Gt as onMiniAppEvent,Wt as openMiniApp,rn as pauseMiniApp,sn as pauseMiniAppDownloads,jt as preloadMiniApp,nn as restoreMiniApp,on as resumeMiniApp,an as resumeMiniAppDownloads,Bt as sendEventToWeb,Le as syncMiniAppCatalog,tn as uninstallMiniApp,De as useMiniAppDownload,Qt as useMiniAppDownloadsPaused};
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "@retion-miniapp/react-native",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Host chạy Retion Mini App (bundle web) trong app React Native — chỉ cần react-native-webview",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/vanqui123/retion-miniapp-react-native.git"
9
+ },
10
+ "homepage": "https://github.com/vanqui123/retion-miniapp-react-native/blob/main/docs/MINIAPP_README.md",
11
+ "bugs": {
12
+ "url": "https://github.com/vanqui123/retion-miniapp-react-native/issues"
13
+ },
6
14
  "keywords": [
7
15
  "react-native",
8
16
  "mini-app",
@@ -44,7 +52,21 @@
44
52
  "peerDependencies": {
45
53
  "react": ">=18",
46
54
  "react-native": ">=0.72",
47
- "react-native-webview": ">=13"
55
+ "react-native-webview": ">=13",
56
+ "react-native-fs": ">=2.20",
57
+ "react-native-mmkv": ">=3",
58
+ "react-native-zip-archive": ">=6"
59
+ },
60
+ "peerDependenciesMeta": {
61
+ "react-native-fs": {
62
+ "optional": true
63
+ },
64
+ "react-native-mmkv": {
65
+ "optional": true
66
+ },
67
+ "react-native-zip-archive": {
68
+ "optional": true
69
+ }
48
70
  },
49
71
  "devDependencies": {
50
72
  "@types/react": "^19.2.0",