Mini Apps: Support reload events (#3953)
This commit is contained in:
parent
65b7fd3e38
commit
5dc23f05fe
@ -5,6 +5,7 @@ import type { WebAppInboundEvent, WebAppOutboundEvent } from '../../../../types/
|
||||
|
||||
import { extractCurrentThemeParams } from '../../../../util/themeStyle';
|
||||
|
||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||
import useWindowSize from '../../../../hooks/useWindowSize';
|
||||
|
||||
const SCROLLBAR_STYLE = `* {
|
||||
@ -27,6 +28,8 @@ const SCROLLBAR_STYLE = `* {
|
||||
background-color: transparent;
|
||||
}`;
|
||||
|
||||
const RELOAD_TIMEOUT = 500;
|
||||
|
||||
const useWebAppFrame = (
|
||||
ref: React.RefObject<HTMLIFrameElement>,
|
||||
isOpen: boolean,
|
||||
@ -41,6 +44,8 @@ const useWebAppFrame = (
|
||||
closeWebApp,
|
||||
} = getActions();
|
||||
|
||||
const isReloadSupported = useRef<boolean>(false);
|
||||
const reloadTimeout = useRef<ReturnType<typeof setTimeout>>();
|
||||
const ignoreEventsRef = useRef<boolean>(false);
|
||||
const lastFrameSizeRef = useRef<{ width: number; height: number; isResizing?: boolean }>();
|
||||
const windowSize = useWindowSize();
|
||||
@ -59,19 +64,33 @@ const useWebAppFrame = (
|
||||
};
|
||||
}, [onLoad, ref, isOpen]);
|
||||
|
||||
const reloadFrame = useCallback((url: string) => {
|
||||
const sendEvent = useCallback((event: WebAppOutboundEvent) => {
|
||||
if (!ref.current?.contentWindow) return;
|
||||
ref.current.contentWindow.postMessage(JSON.stringify(event), '*');
|
||||
}, [ref]);
|
||||
|
||||
const forceReloadFrame = useLastCallback((url: string) => {
|
||||
if (!ref.current) return;
|
||||
const frame = ref.current;
|
||||
frame.src = 'about:blank';
|
||||
frame.addEventListener('load', () => {
|
||||
frame.src = url;
|
||||
}, { once: true });
|
||||
}, [ref]);
|
||||
});
|
||||
|
||||
const sendEvent = useCallback((event: WebAppOutboundEvent) => {
|
||||
if (!ref.current?.contentWindow) return;
|
||||
ref.current.contentWindow.postMessage(JSON.stringify(event), '*');
|
||||
}, [ref]);
|
||||
const reloadFrame = useCallback((url: string) => {
|
||||
if (isReloadSupported.current) {
|
||||
sendEvent({
|
||||
eventType: 'reload_iframe',
|
||||
});
|
||||
reloadTimeout.current = setTimeout(() => {
|
||||
forceReloadFrame(url);
|
||||
}, RELOAD_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
forceReloadFrame(url);
|
||||
}, [sendEvent]);
|
||||
|
||||
const sendViewport = useCallback((isNonStable?: boolean) => {
|
||||
if (!ref.current) {
|
||||
@ -133,6 +152,11 @@ const useWebAppFrame = (
|
||||
if (eventType === 'iframe_ready') {
|
||||
const scrollbarColor = getComputedStyle(document.body).getPropertyValue('--color-scrollbar');
|
||||
sendCustomStyle(SCROLLBAR_STYLE.replace(/%SCROLLBAR_COLOR%/g, scrollbarColor));
|
||||
isReloadSupported.current = Boolean(eventData.reload_supported);
|
||||
}
|
||||
|
||||
if (eventType === 'iframe_will_reload') {
|
||||
clearTimeout(reloadTimeout.current);
|
||||
}
|
||||
|
||||
if (eventType === 'web_app_data_send') {
|
||||
|
||||
@ -9,6 +9,11 @@ export type PopupOptions = {
|
||||
};
|
||||
|
||||
export type WebAppInboundEvent = {
|
||||
eventType: 'iframe_ready';
|
||||
eventData: {
|
||||
reload_supported?: boolean;
|
||||
};
|
||||
} | {
|
||||
eventType: 'web_app_data_send';
|
||||
eventData: {
|
||||
data: string;
|
||||
@ -100,8 +105,8 @@ export type WebAppInboundEvent = {
|
||||
};
|
||||
} | {
|
||||
eventType: 'web_app_request_viewport' | 'web_app_request_theme' | 'web_app_ready' | 'web_app_expand'
|
||||
| 'web_app_request_phone' | 'web_app_close' | 'iframe_ready' | 'web_app_close_scan_qr_popup'
|
||||
| 'web_app_request_write_access' | 'web_app_request_phone';
|
||||
| 'web_app_request_phone' | 'web_app_close' | 'web_app_close_scan_qr_popup'
|
||||
| 'web_app_request_write_access' | 'web_app_request_phone' | 'iframe_will_reload';
|
||||
eventData: null;
|
||||
};
|
||||
|
||||
@ -176,5 +181,6 @@ export type WebAppOutboundEvent = {
|
||||
error: string;
|
||||
});
|
||||
} | {
|
||||
eventType: 'main_button_pressed' | 'back_button_pressed' | 'settings_button_pressed' | 'scan_qr_popup_closed';
|
||||
eventType: 'main_button_pressed' | 'back_button_pressed' | 'settings_button_pressed' | 'scan_qr_popup_closed'
|
||||
| 'reload_iframe';
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user