@botonic/react 0.36.0-alpha.1 → 0.36.1-alpha.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/lib/cjs/contexts.d.ts +8 -4
- package/lib/cjs/contexts.js +4 -1
- package/lib/cjs/contexts.js.map +1 -1
- package/lib/cjs/webchat/webview/index.js +4 -1
- package/lib/cjs/webchat/webview/index.js.map +1 -1
- package/lib/cjs/webview-app.js +114 -63
- package/lib/cjs/webview-app.js.map +1 -1
- package/lib/esm/contexts.d.ts +8 -4
- package/lib/esm/contexts.js +4 -1
- package/lib/esm/contexts.js.map +1 -1
- package/lib/esm/webchat/webview/index.js +5 -2
- package/lib/esm/webchat/webview/index.js.map +1 -1
- package/lib/esm/webview-app.js +115 -64
- package/lib/esm/webview-app.js.map +1 -1
- package/package.json +3 -3
- package/src/contexts.tsx +14 -6
- package/src/webchat/webview/index.tsx +12 -5
- package/src/webview-app.tsx +140 -71
package/lib/cjs/contexts.d.ts
CHANGED
|
@@ -7,8 +7,12 @@ export interface CloseWebviewOptions {
|
|
|
7
7
|
path?: string;
|
|
8
8
|
params?: Record<string, any>;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
params: Record<string, any>;
|
|
10
|
+
export interface WebviewRequestContextType {
|
|
11
|
+
params: Record<string, string>;
|
|
13
12
|
session: Partial<CoreSession>;
|
|
14
|
-
|
|
13
|
+
getUserCountry: () => string;
|
|
14
|
+
getUserLocale: () => string;
|
|
15
|
+
getSystemLocale: () => string;
|
|
16
|
+
closeWebview: (options?: CloseWebviewOptions) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare const WebviewRequestContext: import("react").Context<WebviewRequestContextType>;
|
package/lib/cjs/contexts.js
CHANGED
|
@@ -19,8 +19,11 @@ exports.RequestContext = (0, react_1.createContext)({
|
|
|
19
19
|
plugins: {},
|
|
20
20
|
});
|
|
21
21
|
exports.WebviewRequestContext = (0, react_1.createContext)({
|
|
22
|
-
closeWebview: () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return undefined; }),
|
|
23
22
|
params: {},
|
|
24
23
|
session: {},
|
|
24
|
+
getUserCountry: () => '',
|
|
25
|
+
getUserLocale: () => '',
|
|
26
|
+
getSystemLocale: () => '',
|
|
27
|
+
closeWebview: () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return undefined; }),
|
|
25
28
|
});
|
|
26
29
|
//# sourceMappingURL=contexts.js.map
|
package/lib/cjs/contexts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contexts.js","sourceRoot":"","sources":["../../src/contexts.tsx"],"names":[],"mappings":";;;;AACA,iCAAqC;AAIxB,QAAA,cAAc,GAAG,IAAA,qBAAa,EAAgB;IACzD,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE;IACxB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;IACzB,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;IAC/B,aAAa,EAAE,GAAG,EAAE,CAAC,SAAS;IAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;IAChC,MAAM,EAAE,EAAE;IACV,YAAY,EAAE,CAAC;IACf,aAAa,EAAE,CAAC;IAChB,KAAK,EAAE,EAAe;IACtB,OAAO,EAAE,EAAiB;IAC1B,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,EAAE;CACZ,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"contexts.js","sourceRoot":"","sources":["../../src/contexts.tsx"],"names":[],"mappings":";;;;AACA,iCAAqC;AAIxB,QAAA,cAAc,GAAG,IAAA,qBAAa,EAAgB;IACzD,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE;IACxB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;IACzB,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;IAC/B,aAAa,EAAE,GAAG,EAAE,CAAC,SAAS;IAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;IAChC,MAAM,EAAE,EAAE;IACV,YAAY,EAAE,CAAC;IACf,aAAa,EAAE,CAAC;IAChB,KAAK,EAAE,EAAe;IACtB,OAAO,EAAE,EAAiB;IAC1B,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,EAAE;CACZ,CAAC,CAAA;AAiBW,QAAA,qBAAqB,GAAG,IAAA,qBAAa,EAA4B;IAC5E,MAAM,EAAE,EAA4B;IACpC,OAAO,EAAE,EAA0B;IACnC,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE;IACxB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;IACzB,YAAY,EAAE,GAAS,EAAE,0DAAC,OAAA,SAAS,CAAA,GAAA;CACpC,CAAC,CAAA"}
|
|
@@ -12,9 +12,12 @@ const styles_1 = require("./styles");
|
|
|
12
12
|
const WebviewContainer = () => {
|
|
13
13
|
const { closeWebview, getThemeProperty, webchatState } = (0, react_1.useContext)(context_1.WebchatContext);
|
|
14
14
|
const webviewRequestContext = {
|
|
15
|
-
closeWebview: (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return yield closeWebview(options); }),
|
|
16
15
|
params: webchatState.webviewParams || {},
|
|
17
16
|
session: webchatState.session || {},
|
|
17
|
+
getUserCountry: () => { var _a, _b; return ((_b = (_a = webchatState.session) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.country) || ''; },
|
|
18
|
+
getUserLocale: () => { var _a, _b; return ((_b = (_a = webchatState.session) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.locale) || ''; },
|
|
19
|
+
getSystemLocale: () => { var _a, _b; return ((_b = (_a = webchatState.session) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.system_locale) || ''; },
|
|
20
|
+
closeWebview: (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return yield closeWebview(options); }),
|
|
18
21
|
};
|
|
19
22
|
const Webview = webchatState.webview;
|
|
20
23
|
const close = (e) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/webchat/webview/index.tsx"],"names":[],"mappings":";;;;;AACA,iCAAoD;AAEpD,+CAAgD;AAChD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/webchat/webview/index.tsx"],"names":[],"mappings":";;;;;AACA,iCAAoD;AAEpD,+CAAgD;AAChD,6CAIuB;AACvB,wCAA2C;AAC3C,qCAAwC;AACxC,qCAKiB;AAEV,MAAM,gBAAgB,GAAG,GAAG,EAAE;IACnC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,GACpD,IAAA,kBAAU,EAAC,wBAAc,CAAC,CAAA;IAE5B,MAAM,qBAAqB,GAA8B;QACvD,MAAM,EAAE,YAAY,CAAC,aAAa,IAAK,EAA6B;QACpE,OAAO,EAAE,YAAY,CAAC,OAAO,IAAK,EAA2B;QAC7D,cAAc,EAAE,GAAG,EAAE,eAAC,OAAA,CAAA,MAAA,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,0CAAE,OAAO,KAAI,EAAE,CAAA,EAAA;QAC/D,aAAa,EAAE,GAAG,EAAE,eAAC,OAAA,CAAA,MAAA,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,0CAAE,MAAM,KAAI,EAAE,CAAA,EAAA;QAC7D,eAAe,EAAE,GAAG,EAAE,eAAC,OAAA,CAAA,MAAA,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,0CAAE,aAAa,KAAI,EAAE,CAAA,EAAA;QACtE,YAAY,EAAE,CAAO,OAA6B,EAAE,EAAE,0DACpD,OAAA,MAAM,YAAY,CAAC,OAAO,CAAC,CAAA,GAAA;KAC9B,CAAA;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,OAAuC,CAAA;IAEpE,MAAM,KAAK,GAAG,CAAO,CAAM,EAAE,EAAE;QAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAA;YAClD,MAAM,YAAY,EAAE,CAAA;SACrB;IACH,CAAC,CAAA,CAAA;IAED,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;QAEhD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IAClE,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,iGAAiG;IACjG,2FAA2F;IAC3F,MAAM,cAAc,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAA;IAElD,OAAO,CACL,uBAAC,gCAAqB,CAAC,QAAQ,kBAAC,KAAK,EAAE,qBAAqB,gBAC1D,wBAAC,sBAAa,kBACZ,IAAI,EAAE,iBAAK,CAAC,OAAO,EACnB,KAAK,oBACA,gBAAgB,CAAC,mBAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,kBAG7D,uBAAC,sBAAa,KAAG,EACjB,uBAAC,6BAAoB,cAClB,cAAc,CAAC,CAAC,CAAC,CAChB,uBAAC,oBAAW,IAAC,GAAG,EAAE,OAAO,GAAI,CAC9B,CAAC,CAAC,CAAC,CACF,uBAAC,yBAAgB,cACf,uBAAC,OAAO,KAAG,GACM,CACpB,GACoB,KACT,IACe,CAClC,CAAA;AACH,CAAC,CAAA;AAtDY,QAAA,gBAAgB,oBAsD5B"}
|
package/lib/cjs/webview-app.js
CHANGED
|
@@ -17,39 +17,73 @@ var WebviewUrlParams;
|
|
|
17
17
|
WebviewUrlParams["UserId"] = "user_id";
|
|
18
18
|
WebviewUrlParams["HubtypeApiUrl"] = "hubtype_api_url";
|
|
19
19
|
})(WebviewUrlParams || (WebviewUrlParams = {}));
|
|
20
|
+
const DEFAULT_HUBTYPE_API_URL = 'https://api.hubtype.com';
|
|
20
21
|
class App extends react_1.default.Component {
|
|
21
22
|
constructor(props) {
|
|
22
23
|
super(props);
|
|
24
|
+
this.hubtypeApiUrl = DEFAULT_HUBTYPE_API_URL;
|
|
23
25
|
this.url = new URL(window.location.href);
|
|
24
|
-
this.botId = this.url.searchParams.get(WebviewUrlParams.BotId);
|
|
25
|
-
this.userId = this.url.searchParams.get(WebviewUrlParams.UserId);
|
|
26
|
-
this.hubtypeApiUrl =
|
|
27
|
-
this.url.searchParams.get(WebviewUrlParams.HubtypeApiUrl) ||
|
|
28
|
-
'https://api.hubtype.com';
|
|
29
26
|
this.state = {
|
|
30
27
|
session: null,
|
|
31
28
|
params: {},
|
|
32
29
|
};
|
|
33
30
|
}
|
|
34
31
|
componentDidMount() {
|
|
32
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
yield this.initializeApp();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
initializeApp() {
|
|
35
37
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
36
38
|
try {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
this.
|
|
39
|
+
const botId = this.url.searchParams.get(WebviewUrlParams.BotId);
|
|
40
|
+
const chatId = this.url.searchParams.get(WebviewUrlParams.UserId);
|
|
41
|
+
const hubtypeApiUrl = this.url.searchParams.get(WebviewUrlParams.HubtypeApiUrl);
|
|
42
|
+
if (botId && chatId && hubtypeApiUrl) {
|
|
43
|
+
const session = yield this.getBotSessionContextFromExternalApi(hubtypeApiUrl, botId, chatId);
|
|
44
|
+
this.hubtypeApiUrl = hubtypeApiUrl;
|
|
45
|
+
this.setState({
|
|
46
|
+
session,
|
|
47
|
+
params: this.getParamsFromUrl(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const session = this.getBotSessionContextFromUrl();
|
|
52
|
+
this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL;
|
|
53
|
+
this.setState({
|
|
54
|
+
session,
|
|
55
|
+
params: this.getParamsFromUrl(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
40
58
|
}
|
|
41
59
|
catch (error) {
|
|
42
|
-
console.error('
|
|
60
|
+
console.error('Failed to initialize app:', error);
|
|
61
|
+
const session = this.getBotSessionContextFromUrl();
|
|
62
|
+
this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL;
|
|
63
|
+
this.setState({
|
|
64
|
+
session,
|
|
65
|
+
params: this.getParamsFromUrl(),
|
|
66
|
+
});
|
|
43
67
|
}
|
|
44
68
|
});
|
|
45
69
|
}
|
|
46
|
-
|
|
70
|
+
getBotSessionContextFromExternalApi(hubtypeApiUrl, botId, userId) {
|
|
47
71
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
48
|
-
const url = `${
|
|
72
|
+
const url = `${hubtypeApiUrl}/external/v2/conversational_apps/${botId}/users/${userId}/context/`;
|
|
49
73
|
const response = yield axios_1.default.get(url);
|
|
50
74
|
return response.data;
|
|
51
75
|
});
|
|
52
76
|
}
|
|
77
|
+
getBotSessionContextFromUrl() {
|
|
78
|
+
const urlContext = this.url.searchParams.get(WebviewUrlParams.Context);
|
|
79
|
+
try {
|
|
80
|
+
return JSON.parse(urlContext || '{}');
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error('Failed to parse session context from URL:', error);
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
53
87
|
getParamsFromUrl() {
|
|
54
88
|
const keysToExclude = [
|
|
55
89
|
WebviewUrlParams.Context,
|
|
@@ -57,17 +91,62 @@ class App extends react_1.default.Component {
|
|
|
57
91
|
WebviewUrlParams.UserId,
|
|
58
92
|
WebviewUrlParams.HubtypeApiUrl,
|
|
59
93
|
];
|
|
60
|
-
|
|
61
|
-
.filter(([key
|
|
62
|
-
.reduce((
|
|
63
|
-
|
|
64
|
-
return
|
|
94
|
+
return Array.from(this.url.searchParams.entries())
|
|
95
|
+
.filter(([key]) => !keysToExclude.includes(key))
|
|
96
|
+
.reduce((params, [key, value]) => {
|
|
97
|
+
params[key] = value;
|
|
98
|
+
return params;
|
|
65
99
|
}, {});
|
|
66
|
-
|
|
100
|
+
}
|
|
101
|
+
closeWebviewForProvider(provider, session, payload) {
|
|
102
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const { user } = session;
|
|
104
|
+
switch (provider) {
|
|
105
|
+
case core_1.PROVIDER.WHATSAPP:
|
|
106
|
+
location.href = `https://wa.me/${user.unformatted_phone_number}`;
|
|
107
|
+
break;
|
|
108
|
+
case core_1.PROVIDER.TELEGRAM:
|
|
109
|
+
location.href = `https://t.me/${user.imp_id}`;
|
|
110
|
+
break;
|
|
111
|
+
case core_1.PROVIDER.APPLE:
|
|
112
|
+
location.href = `https://bcrw.apple.com/urn:biz:${user.imp_id}`;
|
|
113
|
+
break;
|
|
114
|
+
case core_1.PROVIDER.TWITTER:
|
|
115
|
+
location.href = `https://twitter.com/messages/compose?recipient_id=${user.imp_id}`;
|
|
116
|
+
break;
|
|
117
|
+
case core_1.PROVIDER.INSTAGRAM:
|
|
118
|
+
window.close();
|
|
119
|
+
break;
|
|
120
|
+
case core_1.PROVIDER.FACEBOOK:
|
|
121
|
+
try {
|
|
122
|
+
window.MessengerExtensions.requestCloseBrowser(() => { }, // success callback
|
|
123
|
+
() => window.close() // error callback
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
window.close();
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
case core_1.PROVIDER.WEBCHAT:
|
|
131
|
+
try {
|
|
132
|
+
yield parent.postMessage('botonicCloseWebview', '*');
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('Failed to send close message to parent:', error);
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
default:
|
|
139
|
+
console.warn(`Unknown provider: ${provider}`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
67
142
|
}
|
|
68
143
|
close(options) {
|
|
69
144
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
70
|
-
|
|
145
|
+
if (!this.state.session) {
|
|
146
|
+
console.error('No session available for closing webview');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let payload = (options === null || options === void 0 ? void 0 : options.payload) || null;
|
|
71
150
|
if (options === null || options === void 0 ? void 0 : options.path) {
|
|
72
151
|
payload = `__PATH_PAYLOAD__${options.path}`;
|
|
73
152
|
}
|
|
@@ -75,58 +154,31 @@ class App extends react_1.default.Component {
|
|
|
75
154
|
if (options === null || options === void 0 ? void 0 : options.params) {
|
|
76
155
|
payload = `${payload}?${(0, core_1.params2queryString)(options.params)}`;
|
|
77
156
|
}
|
|
78
|
-
const session = this.state.session;
|
|
79
157
|
try {
|
|
80
|
-
const url = `${this.hubtypeApiUrl}/v1/bots/${this.
|
|
81
|
-
|
|
82
|
-
|
|
158
|
+
const url = `${this.hubtypeApiUrl}/v1/bots/${this.state.session.bot.id}/send_postback/`;
|
|
159
|
+
const data = {
|
|
160
|
+
payload,
|
|
161
|
+
chat_id: this.state.session.user.id,
|
|
162
|
+
};
|
|
83
163
|
yield axios_1.default.post(url, data);
|
|
84
164
|
}
|
|
85
|
-
catch (
|
|
86
|
-
console.
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const provider = this.state.session.user.provider;
|
|
90
|
-
const impId = this.state.session.user.imp_id;
|
|
91
|
-
if (provider === core_1.PROVIDER.WHATSAPP) {
|
|
92
|
-
const phone_number = this.state.session.user.unformatted_phone_number;
|
|
93
|
-
location.href = 'https://wa.me/' + phone_number;
|
|
94
|
-
}
|
|
95
|
-
if (provider === core_1.PROVIDER.TELEGRAM) {
|
|
96
|
-
location.href = 'https://t.me/' + impId;
|
|
97
|
-
}
|
|
98
|
-
if (provider === core_1.PROVIDER.APPLE) {
|
|
99
|
-
location.href = 'https://bcrw.apple.com/urn:biz:' + impId;
|
|
100
|
-
}
|
|
101
|
-
if (provider === core_1.PROVIDER.TWITTER) {
|
|
102
|
-
location.href =
|
|
103
|
-
'https://twitter.com/messages/compose?recipient_id=' + impId;
|
|
104
|
-
}
|
|
105
|
-
if (provider === core_1.PROVIDER.INSTAGRAM) {
|
|
106
|
-
window.close();
|
|
107
|
-
}
|
|
108
|
-
if (provider === core_1.PROVIDER.FACEBOOK) {
|
|
109
|
-
try {
|
|
110
|
-
window.MessengerExtensions.requestCloseBrowser(function success() { }, function error(err) {
|
|
111
|
-
window.close();
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
catch (e) {
|
|
115
|
-
window.close();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (provider === core_1.PROVIDER.WEBCHAT) {
|
|
119
|
-
try {
|
|
120
|
-
yield parent.postMessage('botonicCloseWebview', '*');
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.error('Failed to send postback:', error);
|
|
121
167
|
}
|
|
122
|
-
catch (e) { }
|
|
123
168
|
}
|
|
169
|
+
yield this.closeWebviewForProvider(this.state.session.user.provider, this.state.session, payload);
|
|
124
170
|
});
|
|
125
171
|
}
|
|
126
172
|
render() {
|
|
173
|
+
if (!this.state.session) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
127
176
|
const webviewRequestContext = {
|
|
128
|
-
|
|
129
|
-
|
|
177
|
+
params: this.state.params,
|
|
178
|
+
session: this.state.session,
|
|
179
|
+
getUserCountry: () => this.state.session.user.country,
|
|
180
|
+
getUserLocale: () => this.state.session.user.locale,
|
|
181
|
+
getSystemLocale: () => this.state.session.system_locale,
|
|
130
182
|
closeWebview: this.close.bind(this),
|
|
131
183
|
};
|
|
132
184
|
return ((0, jsx_runtime_1.jsx)(contexts_1.WebviewRequestContext.Provider, Object.assign({ value: webviewRequestContext }, { children: this.props.webviews.map((Webview, i) => ((0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: `/${Webview.name}`, component: Webview }, i))) })));
|
|
@@ -139,8 +191,7 @@ class WebviewApp {
|
|
|
139
191
|
}
|
|
140
192
|
render(dest) {
|
|
141
193
|
const component = ((0, jsx_runtime_1.jsx)(react_router_dom_1.BrowserRouter, { children: (0, jsx_runtime_1.jsx)(App, { webviews: this.webviews, locales: this.locales }) }));
|
|
142
|
-
const
|
|
143
|
-
const reactRoot = (0, client_1.createRoot)(container);
|
|
194
|
+
const reactRoot = (0, client_1.createRoot)(dest);
|
|
144
195
|
reactRoot.render(component);
|
|
145
196
|
}
|
|
146
197
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webview-app.js","sourceRoot":"","sources":["../../src/webview-app.tsx"],"names":[],"mappings":";;;;;AAAA,cAAc;AACd,wCAAqE;AACrE,0DAAyB;AACzB,0DAAyB;AACzB,6CAA6C;AAC7C,uDAAuD;AAEvD,
|
|
1
|
+
{"version":3,"file":"webview-app.js","sourceRoot":"","sources":["../../src/webview-app.tsx"],"names":[],"mappings":"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"}
|
package/lib/esm/contexts.d.ts
CHANGED
|
@@ -7,8 +7,12 @@ export interface CloseWebviewOptions {
|
|
|
7
7
|
path?: string;
|
|
8
8
|
params?: Record<string, any>;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
params: Record<string, any>;
|
|
10
|
+
export interface WebviewRequestContextType {
|
|
11
|
+
params: Record<string, string>;
|
|
13
12
|
session: Partial<CoreSession>;
|
|
14
|
-
|
|
13
|
+
getUserCountry: () => string;
|
|
14
|
+
getUserLocale: () => string;
|
|
15
|
+
getSystemLocale: () => string;
|
|
16
|
+
closeWebview: (options?: CloseWebviewOptions) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare const WebviewRequestContext: import("react").Context<WebviewRequestContextType>;
|
package/lib/esm/contexts.js
CHANGED
|
@@ -16,8 +16,11 @@ export const RequestContext = createContext({
|
|
|
16
16
|
plugins: {},
|
|
17
17
|
});
|
|
18
18
|
export const WebviewRequestContext = createContext({
|
|
19
|
-
closeWebview: () => __awaiter(void 0, void 0, void 0, function* () { return undefined; }),
|
|
20
19
|
params: {},
|
|
21
20
|
session: {},
|
|
21
|
+
getUserCountry: () => '',
|
|
22
|
+
getUserLocale: () => '',
|
|
23
|
+
getSystemLocale: () => '',
|
|
24
|
+
closeWebview: () => __awaiter(void 0, void 0, void 0, function* () { return undefined; }),
|
|
22
25
|
});
|
|
23
26
|
//# sourceMappingURL=contexts.js.map
|
package/lib/esm/contexts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contexts.js","sourceRoot":"","sources":["../../src/contexts.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAIrC,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAgB;IACzD,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE;IACxB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;IACzB,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;IAC/B,aAAa,EAAE,GAAG,EAAE,CAAC,SAAS;IAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;IAChC,MAAM,EAAE,EAAE;IACV,YAAY,EAAE,CAAC;IACf,aAAa,EAAE,CAAC;IAChB,KAAK,EAAE,EAAe;IACtB,OAAO,EAAE,EAAiB;IAC1B,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,EAAE;CACZ,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"contexts.js","sourceRoot":"","sources":["../../src/contexts.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAIrC,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAgB;IACzD,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE;IACxB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;IACzB,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;IAC/B,aAAa,EAAE,GAAG,EAAE,CAAC,SAAS;IAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;IAChC,MAAM,EAAE,EAAE;IACV,YAAY,EAAE,CAAC;IACf,aAAa,EAAE,CAAC;IAChB,KAAK,EAAE,EAAe;IACtB,OAAO,EAAE,EAAiB;IAC1B,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,EAAE;CACZ,CAAC,CAAA;AAiBF,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAA4B;IAC5E,MAAM,EAAE,EAA4B;IACpC,OAAO,EAAE,EAA0B;IACnC,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE;IACxB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;IACzB,YAAY,EAAE,GAAS,EAAE,kDAAC,OAAA,SAAS,CAAA,GAAA;CACpC,CAAC,CAAA"}
|
|
@@ -2,16 +2,19 @@ import { __awaiter } from "tslib";
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useContext, useEffect } from 'react';
|
|
4
4
|
import { ROLES, WEBCHAT } from '../../constants';
|
|
5
|
-
import { WebviewRequestContext } from '../../contexts';
|
|
5
|
+
import { WebviewRequestContext, } from '../../contexts';
|
|
6
6
|
import { WebchatContext } from '../context';
|
|
7
7
|
import { WebviewHeader } from './header';
|
|
8
8
|
import { StyledFrame, StyledFrameAsDiv, StyledWebview, StyledWebviewContent, } from './styles';
|
|
9
9
|
export const WebviewContainer = () => {
|
|
10
10
|
const { closeWebview, getThemeProperty, webchatState } = useContext(WebchatContext);
|
|
11
11
|
const webviewRequestContext = {
|
|
12
|
-
closeWebview: (options) => __awaiter(void 0, void 0, void 0, function* () { return yield closeWebview(options); }),
|
|
13
12
|
params: webchatState.webviewParams || {},
|
|
14
13
|
session: webchatState.session || {},
|
|
14
|
+
getUserCountry: () => { var _a, _b; return ((_b = (_a = webchatState.session) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.country) || ''; },
|
|
15
|
+
getUserLocale: () => { var _a, _b; return ((_b = (_a = webchatState.session) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.locale) || ''; },
|
|
16
|
+
getSystemLocale: () => { var _a, _b; return ((_b = (_a = webchatState.session) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.system_locale) || ''; },
|
|
17
|
+
closeWebview: (options) => __awaiter(void 0, void 0, void 0, function* () { return yield closeWebview(options); }),
|
|
15
18
|
};
|
|
16
19
|
const Webview = webchatState.webview;
|
|
17
20
|
const close = (e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/webchat/webview/index.tsx"],"names":[],"mappings":";;AACA,OAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/webchat/webview/index.tsx"],"names":[],"mappings":";;AACA,OAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAEL,qBAAqB,GAEtB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,oBAAoB,GACrB,MAAM,UAAU,CAAA;AAEjB,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE;IACnC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,GACpD,UAAU,CAAC,cAAc,CAAC,CAAA;IAE5B,MAAM,qBAAqB,GAA8B;QACvD,MAAM,EAAE,YAAY,CAAC,aAAa,IAAK,EAA6B;QACpE,OAAO,EAAE,YAAY,CAAC,OAAO,IAAK,EAA2B;QAC7D,cAAc,EAAE,GAAG,EAAE,eAAC,OAAA,CAAA,MAAA,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,0CAAE,OAAO,KAAI,EAAE,CAAA,EAAA;QAC/D,aAAa,EAAE,GAAG,EAAE,eAAC,OAAA,CAAA,MAAA,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,0CAAE,MAAM,KAAI,EAAE,CAAA,EAAA;QAC7D,eAAe,EAAE,GAAG,EAAE,eAAC,OAAA,CAAA,MAAA,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,0CAAE,aAAa,KAAI,EAAE,CAAA,EAAA;QACtE,YAAY,EAAE,CAAO,OAA6B,EAAE,EAAE,kDACpD,OAAA,MAAM,YAAY,CAAC,OAAO,CAAC,CAAA,GAAA;KAC9B,CAAA;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,OAAuC,CAAA;IAEpE,MAAM,KAAK,GAAG,CAAO,CAAM,EAAE,EAAE;QAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAA;YAClD,MAAM,YAAY,EAAE,CAAA;SACrB;IACH,CAAC,CAAA,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;QAEhD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IAClE,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,iGAAiG;IACjG,2FAA2F;IAC3F,MAAM,cAAc,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAA;IAElD,OAAO,CACL,KAAC,qBAAqB,CAAC,QAAQ,kBAAC,KAAK,EAAE,qBAAqB,gBAC1D,MAAC,aAAa,kBACZ,IAAI,EAAE,KAAK,CAAC,OAAO,EACnB,KAAK,oBACA,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,kBAG7D,KAAC,aAAa,KAAG,EACjB,KAAC,oBAAoB,cAClB,cAAc,CAAC,CAAC,CAAC,CAChB,KAAC,WAAW,IAAC,GAAG,EAAE,OAAO,GAAI,CAC9B,CAAC,CAAC,CAAC,CACF,KAAC,gBAAgB,cACf,KAAC,OAAO,KAAG,GACM,CACpB,GACoB,KACT,IACe,CAClC,CAAA;AACH,CAAC,CAAA"}
|
package/lib/esm/webview-app.js
CHANGED
|
@@ -6,7 +6,7 @@ import axios from 'axios';
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { createRoot } from 'react-dom/client';
|
|
8
8
|
import { BrowserRouter, Route } from 'react-router-dom';
|
|
9
|
-
import { WebviewRequestContext } from './contexts';
|
|
9
|
+
import { WebviewRequestContext, } from './contexts';
|
|
10
10
|
var WebviewUrlParams;
|
|
11
11
|
(function (WebviewUrlParams) {
|
|
12
12
|
WebviewUrlParams["Context"] = "context";
|
|
@@ -14,39 +14,73 @@ var WebviewUrlParams;
|
|
|
14
14
|
WebviewUrlParams["UserId"] = "user_id";
|
|
15
15
|
WebviewUrlParams["HubtypeApiUrl"] = "hubtype_api_url";
|
|
16
16
|
})(WebviewUrlParams || (WebviewUrlParams = {}));
|
|
17
|
+
const DEFAULT_HUBTYPE_API_URL = 'https://api.hubtype.com';
|
|
17
18
|
class App extends React.Component {
|
|
18
19
|
constructor(props) {
|
|
19
20
|
super(props);
|
|
21
|
+
this.hubtypeApiUrl = DEFAULT_HUBTYPE_API_URL;
|
|
20
22
|
this.url = new URL(window.location.href);
|
|
21
|
-
this.botId = this.url.searchParams.get(WebviewUrlParams.BotId);
|
|
22
|
-
this.userId = this.url.searchParams.get(WebviewUrlParams.UserId);
|
|
23
|
-
this.hubtypeApiUrl =
|
|
24
|
-
this.url.searchParams.get(WebviewUrlParams.HubtypeApiUrl) ||
|
|
25
|
-
'https://api.hubtype.com';
|
|
26
23
|
this.state = {
|
|
27
24
|
session: null,
|
|
28
25
|
params: {},
|
|
29
26
|
};
|
|
30
27
|
}
|
|
31
28
|
componentDidMount() {
|
|
29
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
yield this.initializeApp();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
initializeApp() {
|
|
32
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
35
|
try {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
this.
|
|
36
|
+
const botId = this.url.searchParams.get(WebviewUrlParams.BotId);
|
|
37
|
+
const chatId = this.url.searchParams.get(WebviewUrlParams.UserId);
|
|
38
|
+
const hubtypeApiUrl = this.url.searchParams.get(WebviewUrlParams.HubtypeApiUrl);
|
|
39
|
+
if (botId && chatId && hubtypeApiUrl) {
|
|
40
|
+
const session = yield this.getBotSessionContextFromExternalApi(hubtypeApiUrl, botId, chatId);
|
|
41
|
+
this.hubtypeApiUrl = hubtypeApiUrl;
|
|
42
|
+
this.setState({
|
|
43
|
+
session,
|
|
44
|
+
params: this.getParamsFromUrl(),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const session = this.getBotSessionContextFromUrl();
|
|
49
|
+
this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL;
|
|
50
|
+
this.setState({
|
|
51
|
+
session,
|
|
52
|
+
params: this.getParamsFromUrl(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
37
55
|
}
|
|
38
56
|
catch (error) {
|
|
39
|
-
console.error('
|
|
57
|
+
console.error('Failed to initialize app:', error);
|
|
58
|
+
const session = this.getBotSessionContextFromUrl();
|
|
59
|
+
this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL;
|
|
60
|
+
this.setState({
|
|
61
|
+
session,
|
|
62
|
+
params: this.getParamsFromUrl(),
|
|
63
|
+
});
|
|
40
64
|
}
|
|
41
65
|
});
|
|
42
66
|
}
|
|
43
|
-
|
|
67
|
+
getBotSessionContextFromExternalApi(hubtypeApiUrl, botId, userId) {
|
|
44
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
const url = `${
|
|
69
|
+
const url = `${hubtypeApiUrl}/external/v2/conversational_apps/${botId}/users/${userId}/context/`;
|
|
46
70
|
const response = yield axios.get(url);
|
|
47
71
|
return response.data;
|
|
48
72
|
});
|
|
49
73
|
}
|
|
74
|
+
getBotSessionContextFromUrl() {
|
|
75
|
+
const urlContext = this.url.searchParams.get(WebviewUrlParams.Context);
|
|
76
|
+
try {
|
|
77
|
+
return JSON.parse(urlContext || '{}');
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('Failed to parse session context from URL:', error);
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
50
84
|
getParamsFromUrl() {
|
|
51
85
|
const keysToExclude = [
|
|
52
86
|
WebviewUrlParams.Context,
|
|
@@ -54,17 +88,62 @@ class App extends React.Component {
|
|
|
54
88
|
WebviewUrlParams.UserId,
|
|
55
89
|
WebviewUrlParams.HubtypeApiUrl,
|
|
56
90
|
];
|
|
57
|
-
|
|
58
|
-
.filter(([key
|
|
59
|
-
.reduce((
|
|
60
|
-
|
|
61
|
-
return
|
|
91
|
+
return Array.from(this.url.searchParams.entries())
|
|
92
|
+
.filter(([key]) => !keysToExclude.includes(key))
|
|
93
|
+
.reduce((params, [key, value]) => {
|
|
94
|
+
params[key] = value;
|
|
95
|
+
return params;
|
|
62
96
|
}, {});
|
|
63
|
-
|
|
97
|
+
}
|
|
98
|
+
closeWebviewForProvider(provider, session, payload) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
const { user } = session;
|
|
101
|
+
switch (provider) {
|
|
102
|
+
case PROVIDER.WHATSAPP:
|
|
103
|
+
location.href = `https://wa.me/${user.unformatted_phone_number}`;
|
|
104
|
+
break;
|
|
105
|
+
case PROVIDER.TELEGRAM:
|
|
106
|
+
location.href = `https://t.me/${user.imp_id}`;
|
|
107
|
+
break;
|
|
108
|
+
case PROVIDER.APPLE:
|
|
109
|
+
location.href = `https://bcrw.apple.com/urn:biz:${user.imp_id}`;
|
|
110
|
+
break;
|
|
111
|
+
case PROVIDER.TWITTER:
|
|
112
|
+
location.href = `https://twitter.com/messages/compose?recipient_id=${user.imp_id}`;
|
|
113
|
+
break;
|
|
114
|
+
case PROVIDER.INSTAGRAM:
|
|
115
|
+
window.close();
|
|
116
|
+
break;
|
|
117
|
+
case PROVIDER.FACEBOOK:
|
|
118
|
+
try {
|
|
119
|
+
window.MessengerExtensions.requestCloseBrowser(() => { }, // success callback
|
|
120
|
+
() => window.close() // error callback
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
window.close();
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
case PROVIDER.WEBCHAT:
|
|
128
|
+
try {
|
|
129
|
+
yield parent.postMessage('botonicCloseWebview', '*');
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error('Failed to send close message to parent:', error);
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
console.warn(`Unknown provider: ${provider}`);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
64
139
|
}
|
|
65
140
|
close(options) {
|
|
66
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
-
|
|
142
|
+
if (!this.state.session) {
|
|
143
|
+
console.error('No session available for closing webview');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
let payload = (options === null || options === void 0 ? void 0 : options.payload) || null;
|
|
68
147
|
if (options === null || options === void 0 ? void 0 : options.path) {
|
|
69
148
|
payload = `__PATH_PAYLOAD__${options.path}`;
|
|
70
149
|
}
|
|
@@ -72,58 +151,31 @@ class App extends React.Component {
|
|
|
72
151
|
if (options === null || options === void 0 ? void 0 : options.params) {
|
|
73
152
|
payload = `${payload}?${params2queryString(options.params)}`;
|
|
74
153
|
}
|
|
75
|
-
const session = this.state.session;
|
|
76
154
|
try {
|
|
77
|
-
const url = `${this.hubtypeApiUrl}/v1/bots/${this.
|
|
78
|
-
|
|
79
|
-
|
|
155
|
+
const url = `${this.hubtypeApiUrl}/v1/bots/${this.state.session.bot.id}/send_postback/`;
|
|
156
|
+
const data = {
|
|
157
|
+
payload,
|
|
158
|
+
chat_id: this.state.session.user.id,
|
|
159
|
+
};
|
|
80
160
|
yield axios.post(url, data);
|
|
81
161
|
}
|
|
82
|
-
catch (
|
|
83
|
-
console.
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const provider = this.state.session.user.provider;
|
|
87
|
-
const impId = this.state.session.user.imp_id;
|
|
88
|
-
if (provider === PROVIDER.WHATSAPP) {
|
|
89
|
-
const phone_number = this.state.session.user.unformatted_phone_number;
|
|
90
|
-
location.href = 'https://wa.me/' + phone_number;
|
|
91
|
-
}
|
|
92
|
-
if (provider === PROVIDER.TELEGRAM) {
|
|
93
|
-
location.href = 'https://t.me/' + impId;
|
|
94
|
-
}
|
|
95
|
-
if (provider === PROVIDER.APPLE) {
|
|
96
|
-
location.href = 'https://bcrw.apple.com/urn:biz:' + impId;
|
|
97
|
-
}
|
|
98
|
-
if (provider === PROVIDER.TWITTER) {
|
|
99
|
-
location.href =
|
|
100
|
-
'https://twitter.com/messages/compose?recipient_id=' + impId;
|
|
101
|
-
}
|
|
102
|
-
if (provider === PROVIDER.INSTAGRAM) {
|
|
103
|
-
window.close();
|
|
104
|
-
}
|
|
105
|
-
if (provider === PROVIDER.FACEBOOK) {
|
|
106
|
-
try {
|
|
107
|
-
window.MessengerExtensions.requestCloseBrowser(function success() { }, function error(err) {
|
|
108
|
-
window.close();
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
catch (e) {
|
|
112
|
-
window.close();
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (provider === PROVIDER.WEBCHAT) {
|
|
116
|
-
try {
|
|
117
|
-
yield parent.postMessage('botonicCloseWebview', '*');
|
|
162
|
+
catch (error) {
|
|
163
|
+
console.error('Failed to send postback:', error);
|
|
118
164
|
}
|
|
119
|
-
catch (e) { }
|
|
120
165
|
}
|
|
166
|
+
yield this.closeWebviewForProvider(this.state.session.user.provider, this.state.session, payload);
|
|
121
167
|
});
|
|
122
168
|
}
|
|
123
169
|
render() {
|
|
170
|
+
if (!this.state.session) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
124
173
|
const webviewRequestContext = {
|
|
125
|
-
|
|
126
|
-
|
|
174
|
+
params: this.state.params,
|
|
175
|
+
session: this.state.session,
|
|
176
|
+
getUserCountry: () => this.state.session.user.country,
|
|
177
|
+
getUserLocale: () => this.state.session.user.locale,
|
|
178
|
+
getSystemLocale: () => this.state.session.system_locale,
|
|
127
179
|
closeWebview: this.close.bind(this),
|
|
128
180
|
};
|
|
129
181
|
return (_jsx(WebviewRequestContext.Provider, Object.assign({ value: webviewRequestContext }, { children: this.props.webviews.map((Webview, i) => (_jsx(Route, { path: `/${Webview.name}`, component: Webview }, i))) })));
|
|
@@ -136,8 +188,7 @@ export class WebviewApp {
|
|
|
136
188
|
}
|
|
137
189
|
render(dest) {
|
|
138
190
|
const component = (_jsx(BrowserRouter, { children: _jsx(App, { webviews: this.webviews, locales: this.locales }) }));
|
|
139
|
-
const
|
|
140
|
-
const reactRoot = createRoot(container);
|
|
191
|
+
const reactRoot = createRoot(dest);
|
|
141
192
|
reactRoot.render(component);
|
|
142
193
|
}
|
|
143
194
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webview-app.js","sourceRoot":"","sources":["../../src/webview-app.tsx"],"names":[],"mappings":";;AAAA,cAAc;AACd,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAW,MAAM,eAAe,CAAA;AACrE,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAEvD,OAAO,
|
|
1
|
+
{"version":3,"file":"webview-app.js","sourceRoot":"","sources":["../../src/webview-app.tsx"],"names":[],"mappings":";;AAAA,cAAc;AACd,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAW,MAAM,eAAe,CAAA;AACrE,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAEvD,OAAO,EAEL,qBAAqB,GAEtB,MAAM,YAAY,CAAA;AAEnB,IAAK,gBAKJ;AALD,WAAK,gBAAgB;IACnB,uCAAmB,CAAA;IACnB,oCAAgB,CAAA;IAChB,sCAAkB,CAAA;IAClB,qDAAiC,CAAA;AACnC,CAAC,EALI,gBAAgB,KAAhB,gBAAgB,QAKpB;AAED,MAAM,uBAAuB,GAAG,yBAAyB,CAAA;AAEzD,MAAM,GAAI,SAAQ,KAAK,CAAC,SAAS;IAI/B,YAAY,KAAK;QACf,KAAK,CAAC,KAAK,CAAC,CAAA;QAHN,kBAAa,GAAW,uBAAuB,CAAA;QAIrD,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK,GAAG;YACX,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,EAAE;SACX,CAAA;IACH,CAAC;IAEK,iBAAiB;;YACrB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAA;QAC5B,CAAC;KAAA;IAEa,aAAa;;YACzB,IAAI;gBACF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;gBAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAA;gBACjE,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAC7C,gBAAgB,CAAC,aAAa,CAC/B,CAAA;gBAED,IAAI,KAAK,IAAI,MAAM,IAAI,aAAa,EAAE;oBACpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,mCAAmC,CAC5D,aAAa,EACb,KAAK,EACL,MAAM,CACP,CAAA;oBACD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;oBAClC,IAAI,CAAC,QAAQ,CAAC;wBACZ,OAAO;wBACP,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE;qBAChC,CAAC,CAAA;iBACH;qBAAM;oBACL,MAAM,OAAO,GAAG,IAAI,CAAC,2BAA2B,EAAE,CAAA;oBAClD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,IAAI,uBAAuB,CAAA;oBACpE,IAAI,CAAC,QAAQ,CAAC;wBACZ,OAAO;wBACP,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE;qBAChC,CAAC,CAAA;iBACH;aACF;YAAC,OAAO,KAAK,EAAE;gBACd,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAA;gBACjD,MAAM,OAAO,GAAG,IAAI,CAAC,2BAA2B,EAAE,CAAA;gBAClD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,IAAI,uBAAuB,CAAA;gBACpE,IAAI,CAAC,QAAQ,CAAC;oBACZ,OAAO;oBACP,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE;iBAChC,CAAC,CAAA;aACH;QACH,CAAC;KAAA;IAEa,mCAAmC,CAC/C,aAAqB,EACrB,KAAa,EACb,MAAc;;YAEd,MAAM,GAAG,GAAG,GAAG,aAAa,oCAAoC,KAAK,UAAU,MAAM,WAAW,CAAA;YAChG,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACrC,OAAO,QAAQ,CAAC,IAAI,CAAA;QACtB,CAAC;KAAA;IAEO,2BAA2B;QACjC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;QACtE,IAAI;YACF,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,IAAI,CAAC,CAAA;SACtC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAA;YACjE,OAAO,EAAE,CAAA;SACV;IACH,CAAC;IAEO,gBAAgB;QACtB,MAAM,aAAa,GAAG;YACpB,gBAAgB,CAAC,OAAO;YACxB,gBAAgB,CAAC,KAAK;YACtB,gBAAgB,CAAC,MAAM;YACvB,gBAAgB,CAAC,aAAa;SAC/B,CAAA;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;aAC/C,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aAC/C,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;YACnB,OAAO,MAAM,CAAA;QACf,CAAC,EAAE,EAAE,CAAC,CAAA;IACV,CAAC;IAEa,uBAAuB,CACnC,QAAgB,EAChB,OAAgB,EAChB,OAAgB;;YAEhB,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;YAExB,QAAQ,QAAQ,EAAE;gBAChB,KAAK,QAAQ,CAAC,QAAQ;oBACpB,QAAQ,CAAC,IAAI,GAAG,iBAAiB,IAAI,CAAC,wBAAwB,EAAE,CAAA;oBAChE,MAAK;gBACP,KAAK,QAAQ,CAAC,QAAQ;oBACpB,QAAQ,CAAC,IAAI,GAAG,gBAAgB,IAAI,CAAC,MAAM,EAAE,CAAA;oBAC7C,MAAK;gBACP,KAAK,QAAQ,CAAC,KAAK;oBACjB,QAAQ,CAAC,IAAI,GAAG,kCAAkC,IAAI,CAAC,MAAM,EAAE,CAAA;oBAC/D,MAAK;gBACP,KAAK,QAAQ,CAAC,OAAO;oBACnB,QAAQ,CAAC,IAAI,GAAG,qDAAqD,IAAI,CAAC,MAAM,EAAE,CAAA;oBAClF,MAAK;gBACP,KAAK,QAAQ,CAAC,SAAS;oBACrB,MAAM,CAAC,KAAK,EAAE,CAAA;oBACd,MAAK;gBACP,KAAK,QAAQ,CAAC,QAAQ;oBACpB,IAAI;wBACF,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,CAC5C,GAAG,EAAE,GAAE,CAAC,EAAE,mBAAmB;wBAC7B,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,iBAAiB;yBACvC,CAAA;qBACF;oBAAC,OAAO,KAAK,EAAE;wBACd,MAAM,CAAC,KAAK,EAAE,CAAA;qBACf;oBACD,MAAK;gBACP,KAAK,QAAQ,CAAC,OAAO;oBACnB,IAAI;wBACF,MAAM,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAA;qBACrD;oBAAC,OAAO,KAAK,EAAE;wBACd,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAA;qBAChE;oBACD,MAAK;gBACP;oBACE,OAAO,CAAC,IAAI,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAA;aAChD;QACH,CAAC;KAAA;IAEK,KAAK,CAAC,OAA6B;;YACvC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;gBACvB,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAA;gBACzD,OAAM;aACP;YAED,IAAI,OAAO,GAAG,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,KAAI,IAAI,CAAA;YAEtC,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,EAAE;gBACjB,OAAO,GAAG,mBAAmB,OAAO,CAAC,IAAI,EAAE,CAAA;aAC5C;YAED,IAAI,OAAO,EAAE;gBACX,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,EAAE;oBACnB,OAAO,GAAG,GAAG,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAA;iBAC7D;gBAED,IAAI;oBACF,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,YAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,iBAAiB,CAAA;oBACvF,MAAM,IAAI,GAAG;wBACX,OAAO;wBACP,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;qBACpC,CAAA;oBACD,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;iBAC5B;gBAAC,OAAO,KAAK,EAAE;oBACd,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAA;iBACjD;aACF;YAED,MAAM,IAAI,CAAC,uBAAuB,CAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAChC,IAAI,CAAC,KAAK,CAAC,OAAO,EAClB,OAAO,CACR,CAAA;QACH,CAAC;KAAA;IAED,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;YACvB,OAAO,IAAI,CAAA;SACZ;QAED,MAAM,qBAAqB,GAA8B;YACvD,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;YACzB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO;YAC3B,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO;YACrD,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM;YACnD,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa;YACvD,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;SACpC,CAAA;QAED,OAAO,CACL,KAAC,qBAAqB,CAAC,QAAQ,kBAAC,KAAK,EAAE,qBAAqB,gBACzD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CACvC,KAAC,KAAK,IAAS,IAAI,EAAE,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,OAAO,IAA/C,CAAC,CAAkD,CAChE,CAAC,IAC6B,CAClC,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,UAAU;IACrB,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,MAAM,CAAC,IAAI;QACT,MAAM,SAAS,GAAG,CAChB,KAAC,aAAa,cACZ,KAAC,GAAG,IAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,GAAI,GACzC,CACjB,CAAA;QACD,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAClC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC7B,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botonic/react",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.1-alpha.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Build Chatbots using React",
|
|
6
6
|
"main": "./lib/cjs",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"lint_core": "../../node_modules/.bin/eslint_d --cache --quiet '.*.js' '*.js' 'src/**/*.js*' --fix"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@botonic/core": "^0.36.0
|
|
24
|
-
"axios": "^1.
|
|
23
|
+
"@botonic/core": "^0.36.0",
|
|
24
|
+
"axios": "^1.10.0",
|
|
25
25
|
"emoji-picker-react": "^4.12.0",
|
|
26
26
|
"lodash.merge": "^4.6.2",
|
|
27
27
|
"markdown-it": "^12.3.2",
|
package/src/contexts.tsx
CHANGED
|
@@ -25,12 +25,20 @@ export interface CloseWebviewOptions {
|
|
|
25
25
|
params?: Record<string, any>
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
params: Record<string, any>
|
|
28
|
+
export interface WebviewRequestContextType {
|
|
29
|
+
params: Record<string, string>
|
|
31
30
|
session: Partial<CoreSession>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
getUserCountry: () => string
|
|
32
|
+
getUserLocale: () => string
|
|
33
|
+
getSystemLocale: () => string
|
|
34
|
+
closeWebview: (options?: CloseWebviewOptions) => Promise<void>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const WebviewRequestContext = createContext<WebviewRequestContextType>({
|
|
38
|
+
params: {} as Record<string, string>,
|
|
35
39
|
session: {} as Partial<CoreSession>,
|
|
40
|
+
getUserCountry: () => '',
|
|
41
|
+
getUserLocale: () => '',
|
|
42
|
+
getSystemLocale: () => '',
|
|
43
|
+
closeWebview: async () => undefined,
|
|
36
44
|
})
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Session as CoreSession } from '@botonic/core'
|
|
2
2
|
import React, { useContext, useEffect } from 'react'
|
|
3
3
|
|
|
4
4
|
import { ROLES, WEBCHAT } from '../../constants'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CloseWebviewOptions,
|
|
7
|
+
WebviewRequestContext,
|
|
8
|
+
WebviewRequestContextType,
|
|
9
|
+
} from '../../contexts'
|
|
6
10
|
import { WebchatContext } from '../context'
|
|
7
11
|
import { WebviewHeader } from './header'
|
|
8
12
|
import {
|
|
@@ -16,11 +20,14 @@ export const WebviewContainer = () => {
|
|
|
16
20
|
const { closeWebview, getThemeProperty, webchatState } =
|
|
17
21
|
useContext(WebchatContext)
|
|
18
22
|
|
|
19
|
-
const webviewRequestContext = {
|
|
23
|
+
const webviewRequestContext: WebviewRequestContextType = {
|
|
24
|
+
params: webchatState.webviewParams || ({} as Record<string, string>),
|
|
25
|
+
session: webchatState.session || ({} as Partial<CoreSession>),
|
|
26
|
+
getUserCountry: () => webchatState.session?.user?.country || '',
|
|
27
|
+
getUserLocale: () => webchatState.session?.user?.locale || '',
|
|
28
|
+
getSystemLocale: () => webchatState.session?.user?.system_locale || '',
|
|
20
29
|
closeWebview: async (options?: CloseWebviewOptions) =>
|
|
21
30
|
await closeWebview(options),
|
|
22
|
-
params: webchatState.webviewParams || ({} as Record<string, any>),
|
|
23
|
-
session: webchatState.session || ({} as Partial<CoreSession>),
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
const Webview = webchatState.webview as string | React.ComponentType
|
package/src/webview-app.tsx
CHANGED
|
@@ -5,7 +5,11 @@ import React from 'react'
|
|
|
5
5
|
import { createRoot } from 'react-dom/client'
|
|
6
6
|
import { BrowserRouter, Route } from 'react-router-dom'
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
CloseWebviewOptions,
|
|
10
|
+
WebviewRequestContext,
|
|
11
|
+
WebviewRequestContextType,
|
|
12
|
+
} from './contexts'
|
|
9
13
|
|
|
10
14
|
enum WebviewUrlParams {
|
|
11
15
|
Context = 'context',
|
|
@@ -14,21 +18,15 @@ enum WebviewUrlParams {
|
|
|
14
18
|
HubtypeApiUrl = 'hubtype_api_url',
|
|
15
19
|
}
|
|
16
20
|
|
|
21
|
+
const DEFAULT_HUBTYPE_API_URL = 'https://api.hubtype.com'
|
|
22
|
+
|
|
17
23
|
class App extends React.Component {
|
|
18
24
|
private url: URL
|
|
19
|
-
private
|
|
20
|
-
private userId: string
|
|
21
|
-
private hubtypeApiUrl: string
|
|
22
|
-
private state: { session: Session; params: Record<string, string> }
|
|
25
|
+
private hubtypeApiUrl: string = DEFAULT_HUBTYPE_API_URL
|
|
23
26
|
|
|
24
27
|
constructor(props) {
|
|
25
28
|
super(props)
|
|
26
29
|
this.url = new URL(window.location.href)
|
|
27
|
-
this.botId = this.url.searchParams.get(WebviewUrlParams.BotId)
|
|
28
|
-
this.userId = this.url.searchParams.get(WebviewUrlParams.UserId)
|
|
29
|
-
this.hubtypeApiUrl =
|
|
30
|
-
this.url.searchParams.get(WebviewUrlParams.HubtypeApiUrl) ||
|
|
31
|
-
'https://api.hubtype.com'
|
|
32
30
|
this.state = {
|
|
33
31
|
session: null,
|
|
34
32
|
params: {},
|
|
@@ -36,39 +34,134 @@ class App extends React.Component {
|
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
async componentDidMount() {
|
|
37
|
+
await this.initializeApp()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private async initializeApp() {
|
|
39
41
|
try {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
this.
|
|
42
|
+
const botId = this.url.searchParams.get(WebviewUrlParams.BotId)
|
|
43
|
+
const chatId = this.url.searchParams.get(WebviewUrlParams.UserId)
|
|
44
|
+
const hubtypeApiUrl = this.url.searchParams.get(
|
|
45
|
+
WebviewUrlParams.HubtypeApiUrl
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
if (botId && chatId && hubtypeApiUrl) {
|
|
49
|
+
const session = await this.getBotSessionContextFromExternalApi(
|
|
50
|
+
hubtypeApiUrl,
|
|
51
|
+
botId,
|
|
52
|
+
chatId
|
|
53
|
+
)
|
|
54
|
+
this.hubtypeApiUrl = hubtypeApiUrl
|
|
55
|
+
this.setState({
|
|
56
|
+
session,
|
|
57
|
+
params: this.getParamsFromUrl(),
|
|
58
|
+
})
|
|
59
|
+
} else {
|
|
60
|
+
const session = this.getBotSessionContextFromUrl()
|
|
61
|
+
this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL
|
|
62
|
+
this.setState({
|
|
63
|
+
session,
|
|
64
|
+
params: this.getParamsFromUrl(),
|
|
65
|
+
})
|
|
66
|
+
}
|
|
43
67
|
} catch (error) {
|
|
44
|
-
console.error('
|
|
68
|
+
console.error('Failed to initialize app:', error)
|
|
69
|
+
const session = this.getBotSessionContextFromUrl()
|
|
70
|
+
this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL
|
|
71
|
+
this.setState({
|
|
72
|
+
session,
|
|
73
|
+
params: this.getParamsFromUrl(),
|
|
74
|
+
})
|
|
45
75
|
}
|
|
46
76
|
}
|
|
47
77
|
|
|
48
|
-
async
|
|
49
|
-
|
|
78
|
+
private async getBotSessionContextFromExternalApi(
|
|
79
|
+
hubtypeApiUrl: string,
|
|
80
|
+
botId: string,
|
|
81
|
+
userId: string
|
|
82
|
+
) {
|
|
83
|
+
const url = `${hubtypeApiUrl}/external/v2/conversational_apps/${botId}/users/${userId}/context/`
|
|
50
84
|
const response = await axios.get(url)
|
|
51
85
|
return response.data
|
|
52
86
|
}
|
|
53
87
|
|
|
54
|
-
|
|
88
|
+
private getBotSessionContextFromUrl() {
|
|
89
|
+
const urlContext = this.url.searchParams.get(WebviewUrlParams.Context)
|
|
90
|
+
try {
|
|
91
|
+
return JSON.parse(urlContext || '{}')
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('Failed to parse session context from URL:', error)
|
|
94
|
+
return {}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private getParamsFromUrl() {
|
|
55
99
|
const keysToExclude = [
|
|
56
100
|
WebviewUrlParams.Context,
|
|
57
101
|
WebviewUrlParams.BotId,
|
|
58
102
|
WebviewUrlParams.UserId,
|
|
59
103
|
WebviewUrlParams.HubtypeApiUrl,
|
|
60
104
|
]
|
|
61
|
-
|
|
62
|
-
.filter(([key
|
|
63
|
-
.reduce((
|
|
64
|
-
|
|
65
|
-
return
|
|
105
|
+
return Array.from(this.url.searchParams.entries())
|
|
106
|
+
.filter(([key]) => !keysToExclude.includes(key))
|
|
107
|
+
.reduce((params, [key, value]) => {
|
|
108
|
+
params[key] = value
|
|
109
|
+
return params
|
|
66
110
|
}, {})
|
|
67
|
-
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private async closeWebviewForProvider(
|
|
114
|
+
provider: string,
|
|
115
|
+
session: Session,
|
|
116
|
+
payload?: string
|
|
117
|
+
) {
|
|
118
|
+
const { user } = session
|
|
119
|
+
|
|
120
|
+
switch (provider) {
|
|
121
|
+
case PROVIDER.WHATSAPP:
|
|
122
|
+
location.href = `https://wa.me/${user.unformatted_phone_number}`
|
|
123
|
+
break
|
|
124
|
+
case PROVIDER.TELEGRAM:
|
|
125
|
+
location.href = `https://t.me/${user.imp_id}`
|
|
126
|
+
break
|
|
127
|
+
case PROVIDER.APPLE:
|
|
128
|
+
location.href = `https://bcrw.apple.com/urn:biz:${user.imp_id}`
|
|
129
|
+
break
|
|
130
|
+
case PROVIDER.TWITTER:
|
|
131
|
+
location.href = `https://twitter.com/messages/compose?recipient_id=${user.imp_id}`
|
|
132
|
+
break
|
|
133
|
+
case PROVIDER.INSTAGRAM:
|
|
134
|
+
window.close()
|
|
135
|
+
break
|
|
136
|
+
case PROVIDER.FACEBOOK:
|
|
137
|
+
try {
|
|
138
|
+
window.MessengerExtensions.requestCloseBrowser(
|
|
139
|
+
() => {}, // success callback
|
|
140
|
+
() => window.close() // error callback
|
|
141
|
+
)
|
|
142
|
+
} catch (error) {
|
|
143
|
+
window.close()
|
|
144
|
+
}
|
|
145
|
+
break
|
|
146
|
+
case PROVIDER.WEBCHAT:
|
|
147
|
+
try {
|
|
148
|
+
await parent.postMessage('botonicCloseWebview', '*')
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.error('Failed to send close message to parent:', error)
|
|
151
|
+
}
|
|
152
|
+
break
|
|
153
|
+
default:
|
|
154
|
+
console.warn(`Unknown provider: ${provider}`)
|
|
155
|
+
}
|
|
68
156
|
}
|
|
69
157
|
|
|
70
158
|
async close(options?: CloseWebviewOptions) {
|
|
71
|
-
|
|
159
|
+
if (!this.state.session) {
|
|
160
|
+
console.error('No session available for closing webview')
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let payload = options?.payload || null
|
|
72
165
|
|
|
73
166
|
if (options?.path) {
|
|
74
167
|
payload = `__PATH_PAYLOAD__${options.path}`
|
|
@@ -79,59 +172,36 @@ class App extends React.Component {
|
|
|
79
172
|
payload = `${payload}?${params2queryString(options.params)}`
|
|
80
173
|
}
|
|
81
174
|
|
|
82
|
-
const session = this.state.session
|
|
83
175
|
try {
|
|
84
|
-
const url = `${this.hubtypeApiUrl}/v1/bots/${this.
|
|
85
|
-
|
|
86
|
-
|
|
176
|
+
const url = `${this.hubtypeApiUrl}/v1/bots/${this.state.session.bot.id}/send_postback/`
|
|
177
|
+
const data = {
|
|
178
|
+
payload,
|
|
179
|
+
chat_id: this.state.session.user.id,
|
|
180
|
+
}
|
|
87
181
|
await axios.post(url, data)
|
|
88
|
-
} catch (
|
|
89
|
-
console.
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error('Failed to send postback:', error)
|
|
90
184
|
}
|
|
91
185
|
}
|
|
92
186
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
if (provider === PROVIDER.TELEGRAM) {
|
|
100
|
-
location.href = 'https://t.me/' + impId
|
|
101
|
-
}
|
|
102
|
-
if (provider === PROVIDER.APPLE) {
|
|
103
|
-
location.href = 'https://bcrw.apple.com/urn:biz:' + impId
|
|
104
|
-
}
|
|
105
|
-
if (provider === PROVIDER.TWITTER) {
|
|
106
|
-
location.href =
|
|
107
|
-
'https://twitter.com/messages/compose?recipient_id=' + impId
|
|
108
|
-
}
|
|
109
|
-
if (provider === PROVIDER.INSTAGRAM) {
|
|
110
|
-
window.close()
|
|
111
|
-
}
|
|
112
|
-
if (provider === PROVIDER.FACEBOOK) {
|
|
113
|
-
try {
|
|
114
|
-
window.MessengerExtensions.requestCloseBrowser(
|
|
115
|
-
function success() {},
|
|
116
|
-
function error(err) {
|
|
117
|
-
window.close()
|
|
118
|
-
}
|
|
119
|
-
)
|
|
120
|
-
} catch (e) {
|
|
121
|
-
window.close()
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (provider === PROVIDER.WEBCHAT) {
|
|
125
|
-
try {
|
|
126
|
-
await parent.postMessage('botonicCloseWebview', '*')
|
|
127
|
-
} catch (e) {}
|
|
128
|
-
}
|
|
187
|
+
await this.closeWebviewForProvider(
|
|
188
|
+
this.state.session.user.provider,
|
|
189
|
+
this.state.session,
|
|
190
|
+
payload
|
|
191
|
+
)
|
|
129
192
|
}
|
|
130
193
|
|
|
131
194
|
render() {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
195
|
+
if (!this.state.session) {
|
|
196
|
+
return null
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const webviewRequestContext: WebviewRequestContextType = {
|
|
200
|
+
params: this.state.params,
|
|
201
|
+
session: this.state.session,
|
|
202
|
+
getUserCountry: () => this.state.session.user.country,
|
|
203
|
+
getUserLocale: () => this.state.session.user.locale,
|
|
204
|
+
getSystemLocale: () => this.state.session.system_locale,
|
|
135
205
|
closeWebview: this.close.bind(this),
|
|
136
206
|
}
|
|
137
207
|
|
|
@@ -157,8 +227,7 @@ export class WebviewApp {
|
|
|
157
227
|
<App webviews={this.webviews} locales={this.locales} />
|
|
158
228
|
</BrowserRouter>
|
|
159
229
|
)
|
|
160
|
-
const
|
|
161
|
-
const reactRoot = createRoot(container)
|
|
230
|
+
const reactRoot = createRoot(dest)
|
|
162
231
|
reactRoot.render(component)
|
|
163
232
|
}
|
|
164
233
|
}
|