@coxwave/tap-sdk 0.0.6 → 0.0.8
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/README.md +80 -108
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +75 -70
- package/dist/index.d.ts +75 -70
- package/dist/index.global.js +4 -8
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +4 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/index.ts +0 -285
package/package.json
CHANGED
package/index.ts
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
import ChatBodyMaker from "./chatBody";
|
|
2
|
-
import FloatingButtonMaker from "./floatingButton";
|
|
3
|
-
import { TapIframeBridge } from "./services/tap-iframe-bridge";
|
|
4
|
-
import { EventManager } from "./services/event-manager";
|
|
5
|
-
import showPopupWithHtml from "./popUpImage";
|
|
6
|
-
|
|
7
|
-
import InitGA from "./ga";
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
AlarmMessageInstanceType,
|
|
11
|
-
ChatApiParamsType,
|
|
12
|
-
TapSDKType,
|
|
13
|
-
CustomStylesType,
|
|
14
|
-
ShortcutKeyType,
|
|
15
|
-
SeekTimelineParamsType,
|
|
16
|
-
} from "./types";
|
|
17
|
-
|
|
18
|
-
class TapSDK {
|
|
19
|
-
private pluginKey: string;
|
|
20
|
-
private iframeBridge: TapIframeBridge;
|
|
21
|
-
public events: EventManager;
|
|
22
|
-
|
|
23
|
-
private chatBody: HTMLElement | null = null;
|
|
24
|
-
private chatBodyMaker: ChatBodyMaker;
|
|
25
|
-
private floatingButtonMaker: FloatingButtonMaker;
|
|
26
|
-
private shortcutKey: ShortcutKeyType = {
|
|
27
|
-
openChat: { key: "/", modifier: "" },
|
|
28
|
-
sendChat: { key: "Enter", modifier: "" },
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
private isProd: boolean;
|
|
32
|
-
private isLocal: boolean;
|
|
33
|
-
|
|
34
|
-
private isOpen: boolean;
|
|
35
|
-
private isPdfOpen: boolean;
|
|
36
|
-
|
|
37
|
-
constructor({ pluginKey, isProd = false, isLocal = false }: TapSDKType) {
|
|
38
|
-
// protocol
|
|
39
|
-
this.pluginKey = pluginKey;
|
|
40
|
-
this.iframeBridge = new TapIframeBridge({
|
|
41
|
-
hostClientUrl: window.location.origin,
|
|
42
|
-
pluginKey: this.pluginKey,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// events
|
|
46
|
-
this.events = new EventManager(this.iframeBridge);
|
|
47
|
-
|
|
48
|
-
// render
|
|
49
|
-
this.floatingButtonMaker = new FloatingButtonMaker();
|
|
50
|
-
this.chatBodyMaker = new ChatBodyMaker();
|
|
51
|
-
|
|
52
|
-
// ga log
|
|
53
|
-
this.isProd = isProd;
|
|
54
|
-
this.isLocal = isLocal;
|
|
55
|
-
|
|
56
|
-
// state
|
|
57
|
-
this.isOpen = false;
|
|
58
|
-
this.isPdfOpen = false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
#isClient() {
|
|
62
|
-
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private setIsOpen(isOpen: boolean) {
|
|
66
|
-
this.isOpen = isOpen;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
private setIsPdfOpen(isPdfOpen: boolean) {
|
|
70
|
-
this.isPdfOpen = isPdfOpen;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private sendChatMessage(): void {
|
|
74
|
-
const messageType = this.isOpen ? "chat:close" : "chat:open";
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const result = this.iframeBridge.postToTap({
|
|
78
|
-
type: messageType,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
if (!result) {
|
|
82
|
-
console.error(`[TapSDK] Failed to send ${messageType} message`);
|
|
83
|
-
} else {
|
|
84
|
-
}
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.error("[TapSDK] Error sending chat message:", error);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType) {
|
|
91
|
-
this.iframeBridge.postToTap({
|
|
92
|
-
type: "timeline:seek",
|
|
93
|
-
clipId,
|
|
94
|
-
clipPlayHead,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async initChat({
|
|
99
|
-
chatApiParams,
|
|
100
|
-
customStyles,
|
|
101
|
-
shortcutKey,
|
|
102
|
-
}: {
|
|
103
|
-
chatApiParams: ChatApiParamsType;
|
|
104
|
-
customStyles?: CustomStylesType;
|
|
105
|
-
shortcutKey?: ShortcutKeyType;
|
|
106
|
-
}) {
|
|
107
|
-
if (!this.#isClient()) {
|
|
108
|
-
console.error(
|
|
109
|
-
"[TapSDK] Not running in client environment: window is not defined"
|
|
110
|
-
);
|
|
111
|
-
throw new Error("not client: window is not defined");
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
this.shortcutKey = {
|
|
115
|
-
openChat: shortcutKey?.openChat ?? this.shortcutKey.openChat,
|
|
116
|
-
sendChat: shortcutKey?.sendChat ?? this.shortcutKey.sendChat,
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// chat body render
|
|
120
|
-
if (!this.chatBody) {
|
|
121
|
-
const createdChatBody = this.chatBodyMaker.createChatBody({
|
|
122
|
-
...(customStyles?.chatBody && {
|
|
123
|
-
customChatBody: customStyles.chatBody,
|
|
124
|
-
}),
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
if (!createdChatBody) {
|
|
128
|
-
console.error("[TapSDK] Failed to create chat body");
|
|
129
|
-
throw new Error("Failed to create chat body");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
this.chatBody = createdChatBody;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// chat iframe
|
|
136
|
-
if (!this.iframeBridge.hasIframe()) {
|
|
137
|
-
await this.iframeBridge.renderIframe({
|
|
138
|
-
chatBody: this.chatBody,
|
|
139
|
-
isProd: this.isProd,
|
|
140
|
-
isLocal: this.isLocal,
|
|
141
|
-
});
|
|
142
|
-
} else {
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
const initiatedMessage = await this.iframeBridge.performHandshake(
|
|
147
|
-
{
|
|
148
|
-
chatApiParams,
|
|
149
|
-
customStyles,
|
|
150
|
-
shortcutKey: this.shortcutKey,
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
retryInterval: 500,
|
|
154
|
-
maxRetries: 10,
|
|
155
|
-
timeout: 10000,
|
|
156
|
-
}
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// Initialize GA with the received gaId
|
|
161
|
-
new InitGA({ gaId: initiatedMessage.gaId });
|
|
162
|
-
} catch (error) {
|
|
163
|
-
console.error("[TapSDK] Handshake failed:", error);
|
|
164
|
-
throw new Error(
|
|
165
|
-
`Chat initialization failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// floating button render
|
|
170
|
-
this.floatingButtonMaker.render({
|
|
171
|
-
...(customStyles?.floatingButton && {
|
|
172
|
-
customFloatingButton: customStyles.floatingButton,
|
|
173
|
-
}),
|
|
174
|
-
});
|
|
175
|
-
this.floatingButtonMaker.addClickEvent({
|
|
176
|
-
callback: () => {
|
|
177
|
-
|
|
178
|
-
// Check if iframe exists before sending message
|
|
179
|
-
if (!this.iframeBridge.hasIframe()) {
|
|
180
|
-
console.warn("[TapSDK] Iframe not available, attempting to reinitialize...");
|
|
181
|
-
// Try to recreate iframe if it's missing
|
|
182
|
-
this.iframeBridge.renderIframe({
|
|
183
|
-
chatBody: this.chatBody!,
|
|
184
|
-
isProd: this.isProd,
|
|
185
|
-
isLocal: this.isLocal,
|
|
186
|
-
}).then(() => {
|
|
187
|
-
this.sendChatMessage();
|
|
188
|
-
}).catch((error) => {
|
|
189
|
-
console.error("[TapSDK] Failed to recreate iframe:", error);
|
|
190
|
-
});
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
this.sendChatMessage();
|
|
195
|
-
},
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
this.floatingButtonMaker.addAlarmClickEvent({
|
|
199
|
-
callback: (messageInfo: AlarmMessageInstanceType) => {
|
|
200
|
-
this.iframeBridge.postToTap({ type: "chat:open", isAlarm: true });
|
|
201
|
-
this.iframeBridge.postToTap({ type: "alarm:click", messageInfo });
|
|
202
|
-
},
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
this.iframeBridge.listenToTap("chat:opened", () => {
|
|
206
|
-
this.setIsOpen(true);
|
|
207
|
-
this.chatBodyMaker.toggleVisibility(this.isOpen);
|
|
208
|
-
this.floatingButtonMaker.alarmRemove();
|
|
209
|
-
});
|
|
210
|
-
this.iframeBridge.listenToTap("chat:closed", () => {
|
|
211
|
-
this.setIsOpen(false);
|
|
212
|
-
this.chatBodyMaker.toggleVisibility(this.isOpen);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// alarm
|
|
216
|
-
this.iframeBridge.listenToTap("alarm:fadeIn", (data) => {
|
|
217
|
-
if (this.isOpen) return;
|
|
218
|
-
this.floatingButtonMaker.alarmFadeIn(data.messageInfo);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// popUp
|
|
222
|
-
this.iframeBridge.listenToTap("popUp:open", (data) => {
|
|
223
|
-
showPopupWithHtml({
|
|
224
|
-
htmlString: data.popUpInfo.html,
|
|
225
|
-
callback: () => this.iframeBridge.postToTap({ type: "popUp:close" }),
|
|
226
|
-
...(customStyles?.chatBody && { customStyles: customStyles.chatBody }),
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
// pdf Open
|
|
231
|
-
this.iframeBridge.listenToTap("pdf:open", () => {
|
|
232
|
-
this.setIsPdfOpen(true);
|
|
233
|
-
this.chatBodyMaker.resizeChatBody(this.isPdfOpen, customStyles?.chatBody);
|
|
234
|
-
this.iframeBridge.postToTap({ type: "pdf:enlarged" });
|
|
235
|
-
});
|
|
236
|
-
this.iframeBridge.listenToTap("pdf:close", () => {
|
|
237
|
-
this.setIsPdfOpen(false);
|
|
238
|
-
this.chatBodyMaker.resizeChatBody(this.isPdfOpen, customStyles?.chatBody);
|
|
239
|
-
this.iframeBridge.postToTap({ type: "pdf:shrinked" });
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// if dev, attach alaram:fadeIn event
|
|
243
|
-
if (this.isLocal) {
|
|
244
|
-
this.iframeBridge.listenToTap("alarm:fadeIn", (data) => {
|
|
245
|
-
this.floatingButtonMaker.alarmFadeIn(data.messageInfo);
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
removeChat() {
|
|
251
|
-
if (!this.chatBody) throw new Error("chatBody is not initialized");
|
|
252
|
-
|
|
253
|
-
this.chatBodyMaker.removeChatBody();
|
|
254
|
-
this.floatingButtonMaker.alarmRemove();
|
|
255
|
-
this.iframeBridge.removeIframe();
|
|
256
|
-
this.chatBody = null;
|
|
257
|
-
this.isOpen = false;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* @deprecated use `seekTimeline` method. gotta be expired at v1.0.0
|
|
262
|
-
*/
|
|
263
|
-
postChatInfo({
|
|
264
|
-
clipId,
|
|
265
|
-
clipPlayHead,
|
|
266
|
-
}: {
|
|
267
|
-
clipId: string;
|
|
268
|
-
clipPlayHead: number;
|
|
269
|
-
}) {
|
|
270
|
-
this.seekTimeline({ clipId, clipPlayHead });
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* @deprecated use `events.onTimelineSeek` method. gotta be expired at v1.0.0
|
|
275
|
-
*/
|
|
276
|
-
getTimelineInfo({
|
|
277
|
-
callback,
|
|
278
|
-
}: {
|
|
279
|
-
callback: (clipPlayHead: number, clipId: string) => void;
|
|
280
|
-
}) {
|
|
281
|
-
this.events.onTimelineSeek(callback);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
export default TapSDK;
|