Embedded Frames
Общие замечания
Важно! Чтобы встроенное приложение поддерживало Cookies, они должны при установке иметь свойства secure=true
и SameSite=None
Изменения на стороне Меты
На странице META размещаем такой код
<script type="meta/js" id="token" internal>
function main(env, vm, OAuthService) {
// генерируем токен авторизации
vm.accessToken = OAuthService.getAccessToken(env.userId, ['userinfo.profile']);
}
</script>
<!--
baseUrl - посадочная
accessToken - токен авторизации, доступен в amp.garpun.com так как он переведен на общую авторизацию account.garpun.com
minAbsHeightDiff - минимальное изменение высоты на которое сработает ресайз iframe. Будет зависеть от вашего случая
handleUrls - набор правил переадресации, чтобы например при клите со списка алгоритмов внутри iframe мы могли открыть алгоритм не внутри iframe, а как url меты, т.е. карточку алгоритма в meta приложении
-->
<elem id="garpunUrl" name="me-iframe" order="0"
attrs='{
"baseUrl":"https://amp.garpun.com/interface/clients/algorithms/?adHandsClientId=${env.objectId}",
"accessToken":"${pvm.data.token.vm.accessToken}",
"minAbsHeightDiff": 90,
"handleUrls": [
{"regexp": "add-algorithm\\?algorithmId=(\\d+)", "goTo": "/card?e=182&o=$1&a=${env.applicationId}"}
]
}'
></elem>
Изменение на стороне встраиваемого сайта
Встраивание многостраничных сайтов (на примере amp.garpun.com)
Пример на основе интеграции старого Garpun в новое META-приложение
В Garpun мы разместили код
<script type="text/javascript">
function inIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
document.addEventListener("DOMContentLoaded", function () {
if (inIframe()) {
// Это мы использовали чтобы убрать ненужные кнопки
document.body.classList.add("garpunEmbedded");
}
document.body.classList.remove("garpunLoading");
});
//
(metaframewatcher = window.metaframewatcher || []).push({
height_classes: ['t_window', 'cover', 'stickyWrap', 'mainBox']
});
if (inIframe()) {
// Это не относится к задаче встраивания напрямую, но наверняка будет полезно для GTM для отключения виджетов поддержки и пр
window['IS_EMBED_MODE'] = true;
// Размещаем загрузки интеграционного скрипта
(function() {
var lt = document.createElement('script');
lt.type ='text/javascript';
lt.src = 'https://app.garpun.com/_b/meta-element/iframe/content-watcher.js';
var sc = document.getElementsByTagName('script')[0];
if ( sc ) sc.parentNode.insertBefore(lt, sc);
else document.documentElement.firstChild.appendChild(lt);
})();
}
</script>
Встраивание одностраничных сайтов
Одностраничные сайты (в нашем случае таких много на NextJS) загружают внешний скрипт content-watcher.js
только при загрузке приложения, из-за чего он не может
полноценно работать, т.к.страницы динамически переключаются и их DOM перестраивается. Соответственно, не работает биндинг на события элементов для отслеживания изменения их размеров
Чтобы это обойти, был создан компонент MetaFrame:
'use client'
import 'antd/dist/reset.css';
import {useEffect} from "react";
import { useResizeDetector } from 'react-resize-detector';
const MetaFrame = ({children}: {children: React.ReactNode}) => {
const { width, height, ref } = useResizeDetector();
useEffect(() => {
if (window.parent) {
window.parent.postMessage({type: 'icwHeight', height: height}, '*');
}
}, [height])
useEffect(() => {
//Первичный запуск
if (window.parent) {
window.parent.postMessage({'type': 'icwHandshake', 'url': window.location.href}, '*');
}
}, []);
return (
<div ref={ref}>
{children}
</div>
)
}
export default MetaFrame;
В него необходимо обернуть область контента. В моем случае он размещается сразу внутри body:
<body>
<MetaFrame>
{children}
</MetaFrame>
</body>