postMessage without serialization
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
export interface User {
|
||||
export type User = {
|
||||
name: string;
|
||||
id: string;
|
||||
picture: string;
|
||||
@@ -7,15 +7,10 @@ export interface User {
|
||||
block: boolean;
|
||||
verified: boolean;
|
||||
email_subscription?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
/** data which is used on user-info page */
|
||||
export interface UserInfo {
|
||||
id: User['id'];
|
||||
name: string | '';
|
||||
isDefaultPicture: boolean;
|
||||
picture: string;
|
||||
}
|
||||
export type UserInfo = Pick<User, 'id' | 'name' | 'picture'>;
|
||||
|
||||
export interface BlockedUser {
|
||||
id: string;
|
||||
|
||||
@@ -4,8 +4,6 @@ import type { UserInfo } from './types';
|
||||
|
||||
export const userInfo: UserInfo = parseQuery();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const isDefaultPicture = ((userInfo.isDefaultPicture as any) as string) !== '1';
|
||||
export const id = userInfo.id;
|
||||
export const name = userInfo.name;
|
||||
export const picture = userInfo.picture;
|
||||
|
||||
@@ -75,9 +75,11 @@ class AuthPanelComponent extends Component<Props, State> {
|
||||
toggleUserInfoVisibility = () => {
|
||||
const { user } = this.props;
|
||||
|
||||
if (window.parent && user) {
|
||||
postMessage({ isUserInfoShown: true, user });
|
||||
if (user === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
postMessage({ isUserInfoShown: true, user });
|
||||
};
|
||||
|
||||
renderAuthorized = (user: User) => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import b from 'bem-react-helper';
|
||||
import { Theme } from 'common/types';
|
||||
import { sleep } from 'utils/sleep';
|
||||
import { Button } from 'components/button';
|
||||
import { parseMessage } from 'utils/postMessage';
|
||||
|
||||
type Props = RenderableProps<{
|
||||
title: string;
|
||||
@@ -133,12 +134,14 @@ export class Dropdown extends Component<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
receiveMessage(e: { data: string | object }) {
|
||||
receiveMessage(event: MessageEvent<{ clickOutside?: boolean }>) {
|
||||
try {
|
||||
const data = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
|
||||
const data = parseMessage(event);
|
||||
|
||||
if (!data || !data.clickOutside || !this.state.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.clickOutside) return;
|
||||
if (!this.state.isActive) return;
|
||||
this.setState(
|
||||
{
|
||||
contentTranslateX: 0,
|
||||
|
||||
@@ -4,7 +4,7 @@ import b from 'bem-react-helper';
|
||||
import { IntlShape, useIntl, FormattedMessage, defineMessages } from 'react-intl';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import type { Sorting } from 'common/types';
|
||||
import type { Sorting, Theme } from 'common/types';
|
||||
import type { StoreState } from 'store';
|
||||
import {
|
||||
COMMENT_NODE_CLASSNAME_PREFIX,
|
||||
@@ -39,7 +39,7 @@ import { ConnectedComment as Comment } from 'components/comment/connected-commen
|
||||
import { uploadImage, getPreview } from 'common/api';
|
||||
import { isUserAnonymous } from 'utils/isUserAnonymous';
|
||||
import { bindActions } from 'utils/actionBinder';
|
||||
import { postMessage } from 'utils/postMessage';
|
||||
import { postMessage, parseMessage } from 'utils/postMessage';
|
||||
import { useActions } from 'hooks/useAction';
|
||||
import { setCollapse } from 'store/thread/actions';
|
||||
import { logout } from 'components/auth/auth.api';
|
||||
@@ -177,13 +177,10 @@ export class Root extends Component<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
onMessage(event: { data: string | object }) {
|
||||
if (!event.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
onMessage(event: MessageEvent<{ theme?: Theme }>) {
|
||||
try {
|
||||
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
||||
const data = parseMessage(event);
|
||||
|
||||
if (data.theme && THEMES.includes(data.theme)) {
|
||||
this.props.setTheme(data.theme);
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,5 +1,6 @@
|
||||
import type { UserInfo, Theme } from 'common/types';
|
||||
import { BASE_URL, NODE_ID, COMMENT_NODE_CLASSNAME_PREFIX } from 'common/constants.config';
|
||||
import { parseMessage, ParentMessage } from 'utils/postMessage';
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
@@ -199,9 +200,7 @@ function createInstance(config: typeof window.remark_config) {
|
||||
this.closeEl.innerHTML = '✖';
|
||||
this.closeEl.onclick = () => this.close();
|
||||
}
|
||||
const queryUserInfo = `${query}&page=user-info&&id=${user.id}&name=${user.name}&picture=${
|
||||
user.picture || ''
|
||||
}&isDefaultPicture=${user.isDefaultPicture || 0}`;
|
||||
const queryUserInfo = `${query}&page=user-info&&id=${user.id}&name=${user.name}&picture=${user.picture || ''}`;
|
||||
const iframe = createFrame({ host: BASE_URL, query: queryUserInfo, height: '100%', margin: '0' });
|
||||
this.node.appendChild(iframe);
|
||||
this.iframe = iframe;
|
||||
@@ -265,9 +264,10 @@ function createInstance(config: typeof window.remark_config) {
|
||||
},
|
||||
};
|
||||
|
||||
function receiveMessages(event: { data?: string }): void {
|
||||
function receiveMessages(event: MessageEvent<ParentMessage>): void {
|
||||
try {
|
||||
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
||||
const data = parseMessage(event);
|
||||
|
||||
if (data.remarkIframeHeight) {
|
||||
iframe.style.height = `${data.remarkIframeHeight}px`;
|
||||
}
|
||||
@@ -278,7 +278,7 @@ function createInstance(config: typeof window.remark_config) {
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(data, 'isUserInfoShown')) {
|
||||
if (data.isUserInfoShown) {
|
||||
userInfo.init(data.user || {});
|
||||
userInfo.init(data.user);
|
||||
} else {
|
||||
userInfo.close();
|
||||
}
|
||||
@@ -297,25 +297,25 @@ function createInstance(config: typeof window.remark_config) {
|
||||
if (hash.indexOf(`#${COMMENT_NODE_CLASSNAME_PREFIX}`) === 0) {
|
||||
if (e) e.preventDefault();
|
||||
|
||||
iframe.contentWindow!.postMessage(JSON.stringify({ hash }), '*');
|
||||
iframe.contentWindow!.postMessage({ hash }, '*');
|
||||
}
|
||||
}
|
||||
|
||||
function postTitleToIframe(title: string) {
|
||||
if (iframe.contentWindow) {
|
||||
iframe.contentWindow.postMessage(JSON.stringify({ title }), '*');
|
||||
iframe.contentWindow.postMessage({ title }, '*');
|
||||
}
|
||||
}
|
||||
|
||||
function postClickOutsideToIframe(e: MouseEvent) {
|
||||
if (iframe.contentWindow && !iframe.contains(e.target as Node)) {
|
||||
iframe.contentWindow.postMessage(JSON.stringify({ clickOutside: true }), '*');
|
||||
iframe.contentWindow.postMessage({ clickOutside: true }, '*');
|
||||
}
|
||||
}
|
||||
|
||||
function changeTheme(theme: Theme) {
|
||||
if (iframe.contentWindow) {
|
||||
iframe.contentWindow.postMessage(JSON.stringify({ theme }), '*');
|
||||
iframe.contentWindow.postMessage({ theme }, '*');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,42 @@
|
||||
import { User } from 'common/types';
|
||||
import type { Theme, UserInfo } from 'common/types';
|
||||
|
||||
export type Message =
|
||||
| { inited: true }
|
||||
| {
|
||||
isUserInfoShown: true;
|
||||
user: User;
|
||||
}
|
||||
| { isUserInfoShown: false }
|
||||
| { scrollTo: number }
|
||||
| { remarkIframeHeight: number };
|
||||
export type ParentMessage = {
|
||||
inited?: true;
|
||||
scrollTo?: number;
|
||||
remarkIframeHeight?: number;
|
||||
} & (
|
||||
| { isUserInfoShown: true; user: UserInfo }
|
||||
| { isUserInfoShown: false; user?: never }
|
||||
| { isUserInfoShown?: never; user?: never }
|
||||
);
|
||||
|
||||
export type ChildMessage = {
|
||||
theme?: Theme;
|
||||
};
|
||||
|
||||
type AllMessages = ParentMessage & ChildMessage;
|
||||
|
||||
/**
|
||||
* Sends message to parent window
|
||||
*
|
||||
* @returns request success of fail
|
||||
*/
|
||||
export function postMessage(data: Message): boolean {
|
||||
export function postMessage(data: AllMessages): boolean {
|
||||
if (!window.parent || window.parent === window) return false;
|
||||
window.parent.postMessage(JSON.stringify(data), '*');
|
||||
window.parent.postMessage(data, '*');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses data from post message that was received in iframe
|
||||
*
|
||||
* @param evt post message event
|
||||
* @returns
|
||||
*/
|
||||
export function parseMessage<T>({ data }: MessageEvent<T>): T {
|
||||
if (typeof data !== 'object' || data === null || Array.isArray(data)) {
|
||||
return {} as T;
|
||||
}
|
||||
|
||||
return data as T;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
setInterval(function () {
|
||||
if (document.body.offsetHeight !== lastHeight && document.body.offsetHeight > 22) {
|
||||
lastHeight = document.body.offsetHeight;
|
||||
window.parent.postMessage(JSON.stringify({ remarkIframeHeight: lastHeight }), '*');
|
||||
window.parent.postMessage({ remarkIframeHeight: lastHeight }, '*');
|
||||
}
|
||||
}, 200);
|
||||
|
||||
@@ -142,7 +142,9 @@
|
||||
|
||||
function receiveMessages(event) {
|
||||
try {
|
||||
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
||||
const data = event.data;
|
||||
const isObj = typeof data === 'object' && data !== null && !Array.isArray(data);
|
||||
if (!isObj) return;
|
||||
const isItHash = data.hash && data.hash.indexOf('#') === 0;
|
||||
|
||||
if (isItHash) {
|
||||
@@ -170,7 +172,7 @@
|
||||
return c;
|
||||
}, {});
|
||||
|
||||
window.parent.postMessage(JSON.stringify({ inited: true }), '*');
|
||||
window.parent.postMessage({ inited: true }, '*');
|
||||
</script>
|
||||
<script>
|
||||
(function (d) {
|
||||
|
||||
Reference in New Issue
Block a user