flutter-webview-bridge
Version:
A TypeScript/React bridge for seamless communication between Flutter WebView and web applications
160 lines (159 loc) • 6.77 kB
JavaScript
/**
* @fileoverview Provides a bridge for communication between web applications and Flutter WebView.
* This script captures a MessagePort sent from Flutter and facilitates two-way communication.
*
* @singleton
*/
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
/**
* Manages the MessagePort connection with the Flutter host.
*/
var FlutterBridge = /** @class */ (function () {
/**
* Initializes the bridge and starts listening for the port from Flutter.
*/
function FlutterBridge(options) {
if (options === void 0) { options = {}; }
var _this = this;
this.port = null;
this.subscribers = new Set();
this.options = __assign({ debug: false, captureCommand: "capturePort", confirmationMessage: "portReceived" }, options);
if (typeof window !== "undefined") {
this.log("Инициализация FlutterBridge, подписка на window message");
window.addEventListener("message", this.capturePort.bind(this));
if (this.options.debug) {
// Дополнительная отладка - слушаем ВСЕ сообщения
window.addEventListener("message", function (event) {
var _a;
_this.log("Получено window message:", {
data: event.data,
origin: event.origin,
source: event.source ? "present" : "null",
ports: ((_a = event.ports) === null || _a === void 0 ? void 0 : _a.length) || 0,
});
});
}
}
else {
this.warn("window недоступен (SSR?)");
}
}
/**
* Captures the MessagePort sent from Flutter.
*/
FlutterBridge.prototype.capturePort = function (event) {
var _a;
if (this.options.debug) {
this.log("Проверка сообщения на capturePort:", {
data: event.data,
hasPorts: event.ports && event.ports.length > 0,
portsCount: ((_a = event.ports) === null || _a === void 0 ? void 0 : _a.length) || 0,
});
}
if (event.data === this.options.captureCommand &&
event.ports &&
event.ports.length > 0) {
this.log("✅ Flutter message port captured!");
this.port = event.ports[0];
this.port.onmessage = this.handleMessage.bind(this);
// Уведомляем Flutter, что порт получен
this.port.postMessage(this.options.confirmationMessage);
this.log("\u041E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435 '".concat(this.options.confirmationMessage, "'"));
}
else if (this.options.debug) {
this.log("❌ Сообщение не соответствует критериям capturePort");
}
};
/**
* Handles incoming messages from the Flutter port and notifies subscribers.
*/
FlutterBridge.prototype.handleMessage = function (event) {
this.log("Message received from Flutter:", event.data);
this.subscribers.forEach(function (callback) { return callback(event.data); });
};
/**
* Sends a message to the Flutter application.
*/
FlutterBridge.prototype.sendMessage = function (data) {
if (this.options.debug) {
this.log("Попытка отправки сообщения:", {
data: data,
hasPort: !!this.port,
portState: this.port ? "active" : "null",
});
}
if (this.port) {
this.log("✅ Отправка сообщения во Flutter");
this.port.postMessage(data);
}
else {
this.warn("❌ Flutter port not initialized. Cannot send message.");
if (this.options.debug) {
this.warn("Возможные причины:");
this.warn("1. Flutter еще не отправил порт");
this.warn("2. Сообщение от Flutter имеет неправильный формат");
this.warn("3. Проблема с timing - сообщение отправляется слишком рано");
}
}
};
/**
* Subscribes a callback to listen for messages from Flutter.
*/
FlutterBridge.prototype.subscribe = function (callback) {
var _this = this;
this.subscribers.add(callback);
this.log("\u041F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D. \u0412\u0441\u0435\u0433\u043E: ".concat(this.subscribers.size));
return function () {
_this.subscribers.delete(callback);
_this.log("\u041F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A \u0443\u0434\u0430\u043B\u0435\u043D. \u041E\u0441\u0442\u0430\u043B\u043E\u0441\u044C: ".concat(_this.subscribers.size));
};
};
/**
* Проверяет состояние подключения
*/
FlutterBridge.prototype.getConnectionStatus = function () {
return {
hasPort: !!this.port,
subscribersCount: this.subscribers.size,
};
};
/**
* Проверяет, инициализирован ли порт
*/
FlutterBridge.prototype.isConnected = function () {
return !!this.port;
};
/**
* Отключает bridge и очищает все подписки
*/
FlutterBridge.prototype.disconnect = function () {
if (this.port) {
this.port.close();
this.port = null;
}
this.subscribers.clear();
this.log("Bridge отключен");
};
FlutterBridge.prototype.log = function (message, data) {
if (this.options.debug) {
console.log("[FlutterBridge] ".concat(message), data || "");
}
};
FlutterBridge.prototype.warn = function (message) {
console.warn("[FlutterBridge] ".concat(message));
};
return FlutterBridge;
}());
export { FlutterBridge };
// Export a singleton instance of the bridge with debug enabled by default
export var flutterBridge = new FlutterBridge({ debug: false });