mirror of
https://github.com/wassname/talk.git
synced 2026-07-04 15:06:44 +08:00
Integrate with embed
This commit is contained in:
@@ -5,9 +5,9 @@ import {
|
||||
Decorator,
|
||||
withAutoHeight,
|
||||
withClickEvent,
|
||||
withCommentID,
|
||||
withEventEmitter,
|
||||
withIOSSafariWidthWorkaround,
|
||||
withSetCommentID,
|
||||
} from "./decorators";
|
||||
import PymControl from "./PymControl";
|
||||
import { ensureEndSlash } from "./utils";
|
||||
@@ -15,6 +15,7 @@ import { ensureEndSlash } from "./utils";
|
||||
interface CreatePymControlConfig {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
title?: string;
|
||||
eventEmitter: EventEmitter2;
|
||||
id: string;
|
||||
@@ -26,13 +27,14 @@ export function createPymControl(config: CreatePymControlConfig) {
|
||||
withIOSSafariWidthWorkaround,
|
||||
withAutoHeight,
|
||||
withClickEvent,
|
||||
withCommentID,
|
||||
withSetCommentID,
|
||||
withEventEmitter(config.eventEmitter),
|
||||
];
|
||||
|
||||
const query = qs.stringify({
|
||||
assetID: config.assetID,
|
||||
assetURL: config.assetURL,
|
||||
commentID: config.commentID,
|
||||
});
|
||||
const url = `${ensureEndSlash(config.rootURL)}stream.html?${query}`;
|
||||
return new PymControl({
|
||||
@@ -73,6 +75,7 @@ export type StreamInterface = ReturnType<typeof createStreamInterface>;
|
||||
export interface CreateConfig {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
title?: string;
|
||||
eventEmitter: EventEmitter2;
|
||||
id: string;
|
||||
|
||||
@@ -4,7 +4,7 @@ export type CleanupCallback = () => void;
|
||||
export type Decorator = (pym: pym.Parent) => CleanupCallback | void;
|
||||
export { default as withAutoHeight } from "./withAutoHeight";
|
||||
export { default as withClickEvent } from "./withClickEvent";
|
||||
export { default as withCommentID } from "./withCommentID";
|
||||
export { default as withSetCommentID } from "./withSetCommentID";
|
||||
export { default as withEventEmitter } from "./withEventEmitter";
|
||||
export {
|
||||
default as withIOSSafariWidthWorkaround,
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import qs from "query-string";
|
||||
|
||||
import { buildURL } from "../utils";
|
||||
import { Decorator } from "./";
|
||||
|
||||
const withCommentID: Decorator = pym => {
|
||||
// Remove the comment id from the query.
|
||||
pym.onMessage("view-all-comments", () => {
|
||||
const search = qs.stringify({
|
||||
...qs.parse(location.search),
|
||||
commentId: undefined,
|
||||
});
|
||||
|
||||
// Remove the commentId url param.
|
||||
const url = buildURL({ search });
|
||||
|
||||
// Change the url.
|
||||
window.history.replaceState({}, document.title, url);
|
||||
});
|
||||
|
||||
// Add the permalink comment id to the query.
|
||||
pym.onMessage("view-comment", (id: string) => {
|
||||
const search = qs.stringify({
|
||||
...qs.parse(location.search),
|
||||
commentId: id,
|
||||
});
|
||||
|
||||
// Remove the commentId url param.
|
||||
const url = buildURL({ search });
|
||||
|
||||
// Change the url.
|
||||
window.history.replaceState({}, document.title, url);
|
||||
});
|
||||
};
|
||||
|
||||
export default withCommentID;
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
import withCommentID from "./withCommentID";
|
||||
import withSetCommentID from "./withSetCommentID";
|
||||
|
||||
it("should add commentID", () => {
|
||||
const previousLocation = location.toString();
|
||||
const previousState = window.history.state;
|
||||
const fakePym = {
|
||||
onMessage: (type: string, callback: (id: string) => void) => {
|
||||
if (type === "view-comment") {
|
||||
if (type === "setCommentID") {
|
||||
callback("comment-id");
|
||||
}
|
||||
},
|
||||
};
|
||||
withCommentID(fakePym as any);
|
||||
withSetCommentID(fakePym as any);
|
||||
expect(location.toString()).toBe("http://localhost/?commentId=comment-id");
|
||||
window.history.replaceState(previousState, document.title, previousLocation);
|
||||
});
|
||||
@@ -25,12 +25,12 @@ it("should remove commentID", () => {
|
||||
);
|
||||
const fakePym = {
|
||||
onMessage: (type: string, callback: () => void) => {
|
||||
if (type === "view-all-comments") {
|
||||
if (type === "setCommentID") {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
};
|
||||
withCommentID(fakePym as any);
|
||||
withSetCommentID(fakePym as any);
|
||||
expect(location.toString()).toBe("http://localhost/");
|
||||
window.history.replaceState(previousState, document.title, previousLocation);
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import qs from "query-string";
|
||||
|
||||
import { buildURL } from "../utils";
|
||||
import { Decorator } from "./";
|
||||
|
||||
const withSetCommentID: Decorator = pym => {
|
||||
// Add the permalink comment id to the query.
|
||||
pym.onMessage("setCommentID", (id: string) => {
|
||||
const search = qs.stringify({
|
||||
...qs.parse(location.search),
|
||||
commentID: id || undefined,
|
||||
});
|
||||
|
||||
// Remove the commentId url param.
|
||||
const url = buildURL({ search });
|
||||
|
||||
// Change the url.
|
||||
window.history.replaceState({}, document.title, url);
|
||||
});
|
||||
};
|
||||
|
||||
export default withSetCommentID;
|
||||
@@ -6,6 +6,7 @@ import createStreamInterface from "./Stream";
|
||||
export interface Config {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
rootURL?: string;
|
||||
id?: string;
|
||||
events?: (eventEmitter: EventEmitter2) => void;
|
||||
@@ -23,6 +24,7 @@ export function render(config: Config = {}) {
|
||||
return createStreamInterface({
|
||||
assetID: config.assetID || query.assetID,
|
||||
assetURL: config.assetURL || query.assetURL,
|
||||
commentID: config.commentID || query.commentID,
|
||||
id: config.id || "talk-embed-stream",
|
||||
rootURL: config.rootURL || location.origin,
|
||||
eventEmitter,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "recompose";
|
||||
import { Environment } from "relay-runtime";
|
||||
|
||||
import { withContext } from "../bootstrap";
|
||||
import { TalkContext, withContext } from "../bootstrap";
|
||||
|
||||
/**
|
||||
* createMutationContainer creates a HOC that
|
||||
@@ -18,10 +18,14 @@ import { withContext } from "../bootstrap";
|
||||
*/
|
||||
function createMutationContainer<T extends string, I, R>(
|
||||
propName: T,
|
||||
commit: (environment: Environment, input: I) => Promise<R>
|
||||
commit: (
|
||||
environment: Environment,
|
||||
input: I,
|
||||
context: TalkContext
|
||||
) => Promise<R>
|
||||
): InferableComponentEnhancer<{ [P in T]: (input: I) => Promise<R> }> {
|
||||
return compose(
|
||||
withContext(({ relayEnvironment }) => ({ relayEnvironment })),
|
||||
withContext(context => ({ context })),
|
||||
hoistStatics((BaseComponent: React.ComponentType<any>) => {
|
||||
class CreateMutationContainer extends React.Component<any> {
|
||||
public static displayName = wrapDisplayName(
|
||||
@@ -30,7 +34,11 @@ function createMutationContainer<T extends string, I, R>(
|
||||
);
|
||||
|
||||
private commit = (input: I) => {
|
||||
return commit(this.props.relayEnvironment, input);
|
||||
return commit(
|
||||
this.props.context.relayEnvironment,
|
||||
input,
|
||||
this.props.context
|
||||
);
|
||||
};
|
||||
|
||||
public render() {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
|
||||
import { Typography } from "talk-ui/components";
|
||||
|
||||
export interface LogoProps {
|
||||
className?: string;
|
||||
gutterBottom?: boolean;
|
||||
}
|
||||
|
||||
const Logo: StatelessComponent<LogoProps> = props => {
|
||||
return (
|
||||
<Localized id="stream-logo">
|
||||
<Typography variant="heading1" gutterBottom={props.gutterBottom}>
|
||||
Talk NEO
|
||||
</Typography>
|
||||
</Localized>
|
||||
);
|
||||
};
|
||||
|
||||
export default Logo;
|
||||
@@ -4,7 +4,6 @@
|
||||
margin: calc(0.5 * var(--spacing-unit)) auto;
|
||||
}
|
||||
|
||||
.comment,
|
||||
.commentNotFound {
|
||||
margin: calc(5 * var(--spacing-unit)) auto;
|
||||
.button {
|
||||
margin-bottom: calc(2 * var(--spacing-unit));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { StatelessComponent } from "react";
|
||||
|
||||
import Logo from "talk-stream/components/Logo";
|
||||
import { Button, Flex, Typography } from "talk-ui/components";
|
||||
|
||||
import CommentContainer from "../containers/CommentContainer";
|
||||
@@ -17,44 +16,25 @@ const PermalinkView: StatelessComponent<PermalinkViewProps> = ({
|
||||
comment,
|
||||
onShowAllComments,
|
||||
}) => {
|
||||
if (comment) {
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<Logo />
|
||||
{assetURL && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={onShowAllComments}
|
||||
fullWidth
|
||||
>
|
||||
Show all Comments
|
||||
</Button>
|
||||
)}
|
||||
<Flex direction="column" className={styles.comment}>
|
||||
<CommentContainer data={comment} />
|
||||
</Flex>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<Logo />
|
||||
<Typography className={styles.commentNotFound}>
|
||||
Comment not found
|
||||
</Typography>
|
||||
{assetURL && (
|
||||
<Button
|
||||
variant="filled"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
window.location.href = assetURL;
|
||||
}}
|
||||
onClick={onShowAllComments}
|
||||
className={styles.button}
|
||||
fullWidth
|
||||
>
|
||||
Show all Comments
|
||||
</Button>
|
||||
)}
|
||||
{!comment && <Typography>Comment not found</Typography>}
|
||||
{comment && (
|
||||
<Flex direction="column">
|
||||
<CommentContainer data={comment} />
|
||||
</Flex>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Button, Flex } from "talk-ui/components";
|
||||
import CommentContainer from "../containers/CommentContainer";
|
||||
import PostCommentFormContainer from "../containers/PostCommentFormContainer";
|
||||
import ReplyListContainer from "../containers/ReplyListContainer";
|
||||
import Logo from "./Logo";
|
||||
import * as styles from "./Stream.css";
|
||||
|
||||
export interface StreamProps {
|
||||
@@ -22,7 +21,6 @@ export interface StreamProps {
|
||||
const Stream: StatelessComponent<StreamProps> = props => {
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<Logo gutterBottom />
|
||||
<PostCommentFormContainer assetID={props.assetID} />
|
||||
<Flex
|
||||
direction="column"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { commitLocalUpdate, Environment } from "relay-runtime";
|
||||
|
||||
import { TalkContext } from "talk-framework/lib/bootstrap";
|
||||
import { createMutationContainer } from "talk-framework/lib/relay";
|
||||
import { LOCAL_ID } from "talk-framework/lib/relay/withLocalStateContainer";
|
||||
|
||||
@@ -8,10 +10,18 @@ export interface SetCommentIDInput {
|
||||
|
||||
export type SetCommentIDMutation = (input: SetCommentIDInput) => Promise<void>;
|
||||
|
||||
async function commit(environment: Environment, input: SetCommentIDInput) {
|
||||
async function commit(
|
||||
environment: Environment,
|
||||
input: SetCommentIDInput,
|
||||
{ pym }: TalkContext
|
||||
) {
|
||||
return commitLocalUpdate(environment, store => {
|
||||
const record = store.get(LOCAL_ID)!;
|
||||
record.setValue(input.id, "commentID");
|
||||
if (pym) {
|
||||
// This sets the comment id on the parent url.
|
||||
pym.sendMessage("setCommentID", input.id || "");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,9 @@ export class ClickOutside extends React.Component<ClickOutsideProps> {
|
||||
}
|
||||
}
|
||||
|
||||
const ClickOutsideWithContext: StatelessComponent<Props> = props => (
|
||||
const ClickOutsideWithContext: StatelessComponent<
|
||||
ClickOutsideProps
|
||||
> = props => (
|
||||
<UIContext.Consumer>
|
||||
{({ registerClickFarAway }) => (
|
||||
<ClickOutside {...props} registerClickFarAway={registerClickFarAway} />
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default as ClickOutside, ClickFarAwayRegister } from "./ClickOutside";
|
||||
export { default, ClickFarAwayRegister } from "./ClickOutside";
|
||||
|
||||
Reference in New Issue
Block a user