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 { extractCurrentThemeParams } from '../../../../util/themeStyle';
|
||||||
|
|
||||||
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
import useWindowSize from '../../../../hooks/useWindowSize';
|
import useWindowSize from '../../../../hooks/useWindowSize';
|
||||||
|
|
||||||
const SCROLLBAR_STYLE = `* {
|
const SCROLLBAR_STYLE = `* {
|
||||||
@ -27,6 +28,8 @@ const SCROLLBAR_STYLE = `* {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
const RELOAD_TIMEOUT = 500;
|
||||||
|
|
||||||
const useWebAppFrame = (
|
const useWebAppFrame = (
|
||||||
ref: React.RefObject<HTMLIFrameElement>,
|
ref: React.RefObject<HTMLIFrameElement>,
|
||||||
isOpen: boolean,
|
isOpen: boolean,
|
||||||
@ -41,6 +44,8 @@ const useWebAppFrame = (
|
|||||||
closeWebApp,
|
closeWebApp,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
|
const isReloadSupported = useRef<boolean>(false);
|
||||||
|
const reloadTimeout = useRef<ReturnType<typeof setTimeout>>();
|
||||||
const ignoreEventsRef = useRef<boolean>(false);
|
const ignoreEventsRef = useRef<boolean>(false);
|
||||||
const lastFrameSizeRef = useRef<{ width: number; height: number; isResizing?: boolean }>();
|
const lastFrameSizeRef = useRef<{ width: number; height: number; isResizing?: boolean }>();
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
@ -59,19 +64,33 @@ const useWebAppFrame = (
|
|||||||
};
|
};
|
||||||
}, [onLoad, ref, isOpen]);
|
}, [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;
|
if (!ref.current) return;
|
||||||
const frame = ref.current;
|
const frame = ref.current;
|
||||||
frame.src = 'about:blank';
|
frame.src = 'about:blank';
|
||||||
frame.addEventListener('load', () => {
|
frame.addEventListener('load', () => {
|
||||||
frame.src = url;
|
frame.src = url;
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
}, [ref]);
|
});
|
||||||
|
|
||||||
const sendEvent = useCallback((event: WebAppOutboundEvent) => {
|
const reloadFrame = useCallback((url: string) => {
|
||||||
if (!ref.current?.contentWindow) return;
|
if (isReloadSupported.current) {
|
||||||
ref.current.contentWindow.postMessage(JSON.stringify(event), '*');
|
sendEvent({
|
||||||
}, [ref]);
|
eventType: 'reload_iframe',
|
||||||
|
});
|
||||||
|
reloadTimeout.current = setTimeout(() => {
|
||||||
|
forceReloadFrame(url);
|
||||||
|
}, RELOAD_TIMEOUT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forceReloadFrame(url);
|
||||||
|
}, [sendEvent]);
|
||||||
|
|
||||||
const sendViewport = useCallback((isNonStable?: boolean) => {
|
const sendViewport = useCallback((isNonStable?: boolean) => {
|
||||||
if (!ref.current) {
|
if (!ref.current) {
|
||||||
@ -133,6 +152,11 @@ const useWebAppFrame = (
|
|||||||
if (eventType === 'iframe_ready') {
|
if (eventType === 'iframe_ready') {
|
||||||
const scrollbarColor = getComputedStyle(document.body).getPropertyValue('--color-scrollbar');
|
const scrollbarColor = getComputedStyle(document.body).getPropertyValue('--color-scrollbar');
|
||||||
sendCustomStyle(SCROLLBAR_STYLE.replace(/%SCROLLBAR_COLOR%/g, scrollbarColor));
|
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') {
|
if (eventType === 'web_app_data_send') {
|
||||||
|
|||||||
@ -9,6 +9,11 @@ export type PopupOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type WebAppInboundEvent = {
|
export type WebAppInboundEvent = {
|
||||||
|
eventType: 'iframe_ready';
|
||||||
|
eventData: {
|
||||||
|
reload_supported?: boolean;
|
||||||
|
};
|
||||||
|
} | {
|
||||||
eventType: 'web_app_data_send';
|
eventType: 'web_app_data_send';
|
||||||
eventData: {
|
eventData: {
|
||||||
data: string;
|
data: string;
|
||||||
@ -100,8 +105,8 @@ export type WebAppInboundEvent = {
|
|||||||
};
|
};
|
||||||
} | {
|
} | {
|
||||||
eventType: 'web_app_request_viewport' | 'web_app_request_theme' | 'web_app_ready' | 'web_app_expand'
|
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_phone' | 'web_app_close' | 'web_app_close_scan_qr_popup'
|
||||||
| 'web_app_request_write_access' | 'web_app_request_phone';
|
| 'web_app_request_write_access' | 'web_app_request_phone' | 'iframe_will_reload';
|
||||||
eventData: null;
|
eventData: null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,5 +181,6 @@ export type WebAppOutboundEvent = {
|
|||||||
error: string;
|
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