Files
talk/src/core/client/embed/StreamEmbed.ts
T
Kiwi 106a5d36ed [next] Embed plus (#1877)
* Implement StreamEmbed instance and rename library to coral

* Add article & articleButton.html, only show embed htmls in production

* Respect assetURL

* Add tests

* Add parseHashQuery

* Fix permalink query and integration tests

* Fix permalink URL

* Remove optionalparams from pym

* Scroll when showing permalink view

* Implement autoRender

* AutoRender immediately when render permalink

* Add test for `showPermalink` event

* Add comment
2018-09-21 22:43:28 +00:00

128 lines
3.1 KiB
TypeScript

import { EventEmitter2 } from "eventemitter2";
import qs from "query-string";
import {
Decorator,
withAutoHeight,
withClickEvent,
withEventEmitter,
withIOSSafariWidthWorkaround,
withPymStorage,
withSetCommentID,
} from "./decorators";
import onIntersect from "./onIntersect";
import PymControl, {
defaultPymControlFactory,
PymControlFactory,
} from "./PymControl";
import { ensureEndSlash } from "./utils";
export interface StreamEmbedConfig {
assetID?: string;
assetURL?: string;
commentID?: string;
autoRender?: boolean;
title: string;
eventEmitter: EventEmitter2;
id: string;
rootURL: string;
}
export class StreamEmbed {
private config: StreamEmbedConfig;
private pymControl?: PymControl;
private pymControlFactory: PymControlFactory;
constructor(
config: StreamEmbedConfig,
pymControlFactory = defaultPymControlFactory
) {
this.config = config;
this.pymControlFactory = pymControlFactory;
if (config.commentID) {
// Delay emit of `showPermalink` event to allow
// user enough time to setup event listeners.
setTimeout(() => config.eventEmitter.emit("showPermalink"), 0);
}
if (config.autoRender) {
if (config.commentID) {
this.render();
} else {
onIntersect(document.getElementById(config.id)!, () => {
if (!this.rendered) {
this.render();
}
});
}
}
}
private assertRendered() {
if (!this.pymControl) {
throw new Error("Stream Embed must be rendered first");
}
}
public on(eventName: string, callback: (data: any) => void) {
return this.config.eventEmitter.on(eventName, callback);
}
public off(eventName: string, callback: (data: any) => void) {
return this.config.eventEmitter.off(eventName, callback);
}
public login(token: string) {
this.assertRendered();
this.pymControl!.sendMessage("login", token);
}
public logout() {
this.assertRendered();
this.pymControl!.sendMessage("logout");
}
public remove() {
this.assertRendered();
this.pymControl!.remove();
this.pymControl = undefined;
}
get rendered() {
return !!this.pymControl;
}
public render() {
if (this.pymControl) {
throw new Error("Stream Embed already rendered");
}
const streamDecorators: ReadonlyArray<Decorator> = [
withIOSSafariWidthWorkaround,
withAutoHeight,
withClickEvent,
withSetCommentID,
withEventEmitter(this.config.eventEmitter),
withPymStorage(localStorage, "localStorage"),
withPymStorage(sessionStorage, "sessionStorage"),
];
const query = qs.stringify({
assetID: this.config.assetID,
assetURL: this.config.assetURL,
commentID: this.config.commentID,
});
const url = `${ensureEndSlash(this.config.rootURL)}stream.html${
query ? `?${query}` : ""
}`;
this.pymControl = this.pymControlFactory({
id: this.config.id,
title: this.config.title,
decorators: streamDecorators,
url,
});
}
}
export default function createStreamEmbed(config: StreamEmbedConfig) {
return new StreamEmbed(config);
}