Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions frontend/block/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
"icon": "format-chat",
"description": "Matrix client",
"attributes": {
"instanceId": {
"type": "string",
"default": ""
},
"defaultHomeserver": {
"type": "string",
"default": ""
Expand Down
23 changes: 20 additions & 3 deletions frontend/block/edit.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useBlockProps } from "@wordpress/block-editor";
import { ResizableBox } from "@wordpress/components";
import { WPElement } from '@wordpress/element';
import { useEffect, WPElement } from '@wordpress/element';
import { getIframeUrl } from "../app";
import { Block, BlockProps, parseAttributes } from "../components/block";
import './editor.scss';
Expand All @@ -11,13 +11,30 @@ interface Props {
setAttributes: Function,
}

let instanceIds: string[] = [];

export default function Edit(props: Props): WPElement {
const { attributes, setAttributes } = props;
const parsedAttributes = parseAttributes(attributes);

// Set instanceId if it's not set, or if it already exists on the page (which happens when the block is duplicated).
useEffect(() => {
// @ts-ignore
let { instanceId } = attributes;
const hasInstanceId = instanceId && instanceId !== "";
const isInstanceIdDuplicated = hasInstanceId && instanceIds.includes(instanceId);

if (!hasInstanceId || isInstanceIdDuplicated) {
instanceId = (Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)).toString();
setAttributes({ instanceId });
}

instanceIds.push(instanceId);
}, []);

const parsedAttributes = parseAttributes(attributes);
const blockProps: BlockProps = {
focusable: true,
attributes,
attributes: parsedAttributes,
iframeUrl: getIframeUrl(),
};

Expand Down
9 changes: 8 additions & 1 deletion frontend/block/view.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BlockProps, renderBlock } from "../app";
import { parseAttributes } from "../components/block";

window.addEventListener('DOMContentLoaded', () => {
renderAllBlocks().catch(error => {
Expand All @@ -13,10 +14,16 @@ async function renderAllBlocks() {
const containers = <HTMLCollectionOf<HTMLElement>>document.getElementsByClassName('wp-block-automattic-chatrix');
for (const container of containers) {
const config = getConfigFromDataAttribute(container);
const attributes = parseAttributes(config.attributes);
const props: BlockProps = {
attributes: config.attributes,
attributes: attributes,
};

if (!attributes.instanceId) {
// In earlier versions of the block, there was no instanceId attribute, so it can be undefined.
console.warn('Chatrix block is missing the instanceId attribute. Re-save the page to fix this.');
}

renderBlock(container, props);
}
}
Expand Down
31 changes: 22 additions & 9 deletions frontend/components/block/attributes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Unit, ValueWithUnit } from "./unit";

interface Attributes {
export interface BlockAttributes {
instanceId: string,
defaultHomeserver?: string,
roomId?: string,
height?: Height,
Expand All @@ -10,15 +11,27 @@ interface Attributes {
borderColor?: string,
}

export function parseAttributes(attributes): Attributes {
export function parseAttributes(attributes): BlockAttributes {
const {
instanceId,
defaultHomeserver,
roomId,
height,
borderWidth,
borderRadius,
borderStyle,
borderColor,
} = attributes;

return {
defaultHomeserver: attributes.defaultHomeserver ?? '',
roomId: attributes.roomId ?? '',
height: attributes.height ? new Height(attributes.height.value, attributes.height.unit) : undefined,
borderWidth: attributes.borderWidth ? new BorderWidth(attributes.borderWidth.value, attributes.borderWidth.unit) : undefined,
borderRadius: attributes.borderRadius ? new BorderRadius(attributes.borderRadius.value, attributes.borderRadius.unit) : undefined,
borderStyle: attributes.borderStyle,
borderColor: attributes.borderColor,
instanceId,
defaultHomeserver: defaultHomeserver ?? '',
roomId: roomId ?? '',
height: height ? new Height(height.value, height.unit) : undefined,
borderWidth: borderWidth ? new BorderWidth(borderWidth.value, borderWidth.unit) : undefined,
borderRadius: borderRadius ? new BorderRadius(borderRadius.value, borderRadius.unit) : undefined,
borderStyle,
borderColor,
};
}

Expand Down
35 changes: 23 additions & 12 deletions frontend/components/block/block.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
import { Chat, ChatProps } from "../chat";
import { parseAttributes } from "./attributes";
import { BlockAttributes } from "./attributes";

export interface BlockProps {
focusable?: boolean,
attributes: object,
attributes: BlockAttributes,
iframeUrl: URL,
}

export function Block(props: BlockProps) {
const attributes = parseAttributes(props.attributes);
const { focusable, iframeUrl } = props;
const {
instanceId,
defaultHomeserver,
roomId,
height,
borderWidth,
borderRadius,
borderStyle,
borderColor,
} = props.attributes;

const style = {
height: attributes.height ? attributes.height.toString() : '',
borderWidth: attributes.borderWidth ? attributes.borderWidth.toString() : 0,
borderRadius: attributes.borderRadius ? attributes.borderRadius.toString() : "",
borderStyle: attributes.borderStyle ?? '',
borderColor: attributes.borderColor ?? '',
height: height ? height.toString() : '',
borderWidth: borderWidth ? borderWidth.toString() : 0,
borderRadius: borderRadius ? borderRadius.toString() : "",
borderStyle: borderStyle ?? '',
borderColor: borderColor ?? '',
};

const chatProps: ChatProps = {
focusable: props.focusable,
iframeUrl: props.iframeUrl,
defaultHomeserver: attributes.defaultHomeserver,
roomId: attributes.roomId,
focusable,
iframeUrl,
instanceId,
defaultHomeserver,
roomId,
};

return (
Expand Down
19 changes: 14 additions & 5 deletions frontend/components/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,33 @@ import { IframeUrl } from "./url";
export interface ChatProps {
focusable?: boolean,
iframeUrl: URL,
instanceId: string,
defaultHomeserver?: string,
roomId?: string,
}

export function Chat(props: ChatProps) {
const ref = props.focusable ? useFocusableIframe() : undefined;
const {
focusable,
iframeUrl,
instanceId,
defaultHomeserver,
roomId
} = props;

const iframeUrl = new IframeUrl(props.iframeUrl, {
defaultHomeserver: props.defaultHomeserver,
roomId: props.roomId,
const ref = focusable ? useFocusableIframe() : undefined;
const url = new IframeUrl(iframeUrl, {
instanceId,
defaultHomeserver,
roomId,
});

return (
<div className={"chatrix-component-chat"}>
<iframe
// @ts-ignore
ref={ref}
src={iframeUrl.toString()}
src={url.toString()}
></iframe>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions frontend/components/chat/url.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const LOGIN_TOKEN_PARAM_NAME = "loginToken";

type IframeParams = {
instanceId: string,
defaultHomeserver?: string
roomId?: string,
}
Expand Down
1 change: 1 addition & 0 deletions frontend/iframe/config/ConfigFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class ConfigFactory {
};

return {
instanceId: getQueryParam("instanceId") ?? "",
defaultHomeserver: getQueryParam("defaultHomeserver") ?? "",
roomId: getQueryParam("roomId") ?? "",
themeManifests: [
Expand Down
6 changes: 6 additions & 0 deletions frontend/iframe/config/IConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export interface IConfig {
/**
* Unique identifier for this instance of the client.
* When multiple clients are embedded on the same page, this is used to distinguish them.
*/
instanceId: string;

/**
* The default homeserver used by Hydrogen; autofilled in the login UI.
* eg: https://matrix.org
Expand Down
12 changes: 9 additions & 3 deletions frontend/iframe/platform/History.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { History as BaseHistory } from "hydrogen-web/src/platform/web/dom/History";

export class History extends BaseHistory {
private readonly _instanceId: string;
private _lastSessionHash: string | null | undefined;

constructor() {
constructor(instanceId: string) {
super();
this._instanceId = instanceId;
}

get() {
Expand All @@ -21,16 +23,20 @@ export class History extends BaseHistory {
}

onSubscribeFirst() {
this._lastSessionHash = window.localStorage?.getItem("chatrix_last_url_hash");
this._lastSessionHash = window.localStorage?.getItem(this.urlHashKey);
// @ts-ignore
window.addEventListener('hashchange', this);
}

_storeHash(hash) {
window.localStorage?.setItem("chatrix_last_url_hash", hash);
window.localStorage?.setItem(this.urlHashKey, hash);
}

replaceUrlSilently(url) {
super.replaceUrlSilently(url);
}

private get urlHashKey(): string {
return `chatrix_${this._instanceId}_last_url_hash`;
}
}
2 changes: 1 addition & 1 deletion frontend/iframe/platform/Platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class Platform extends BasePlatform {
super._serviceWorkerHandler = serviceWorkerHandler;
super.settingsStorage = new SettingsStorage("chatrix_setting_v1_");
super.sessionInfoStorage = new SessionInfoStorage("chatrix_sessions_v1");
super.history = new History();
super.history = new History(this.config.instanceId);
}

public get history(): History {
Expand Down
1 change: 1 addition & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

renderBlock(document.getElementById("root-block"), {
attributes: {
instanceId: "block",
defaultHomeserver: env.VITE_HOMESERVER,
roomId: env.VITE_ROOM_ID,
}
Expand Down
1 change: 1 addition & 0 deletions src/Popup/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
container.style.zIndex = 1;

Chatrix.renderPopup(container, {
instanceId: config.instanceId,
defaultHomeserver: config.defaultHomeserver,
roomId: config.roomId,
});
Expand Down
17 changes: 7 additions & 10 deletions src/Popup/popup.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
use function Automattic\Chatrix\Admin\Settings\get as get_chatrix_settings;
use const Automattic\Chatrix\SCRIPT_HANDLE_APP;

function chatrix_config() {
return apply_filters( 'chatrix_config', array() );
}

function register() {
register_default_instance();
define_config();
Expand All @@ -35,10 +31,9 @@ function ( array $instances ) {

return array(
'default' => array(
'homeserver' => $settings['homeserver'],
'room_id' => $settings['room'],
'login_methods' => array( 'password', 'sso' ), // TODO: don't hardcode login methods.
'pages' => 'all' === $settings['show_on'] ? 'all' : $settings['pages'],
'homeserver' => $settings['homeserver'],
'room_id' => $settings['room'],
'pages' => 'all' === $settings['show_on'] ? 'all' : $settings['pages'],
),
);
}
Expand Down Expand Up @@ -67,7 +62,8 @@ function ( array $config ) {
$instances = apply_filters( 'chatrix_instances', array() );

foreach ( $instances as $instance_id => $instance ) {
$instance_config = array(
$instance['instance_id'] = $instance_id;
$instance_config = array(
'url' => rest_url( "chatrix/config/$instance_id" ),
'config' => $instance,
'instance_id' => $instance_id,
Expand Down Expand Up @@ -118,14 +114,15 @@ function init_javascript() {
add_action(
'wp_enqueue_scripts',
function () {
$config = chatrix_config();
$config = apply_filters( 'chatrix_config', array() );
if ( empty( $config ) ) {
return;
}

$handle = 'chatrix-popup';
$json_data = wp_json_encode(
array(
'instanceId' => 'popup_' . $config['instance_id'],
'defaultHomeserver' => $config['config']['homeserver'],
'roomId' => empty( $config['config']['room_id'] ) ? null : $config['config']['room_id'],
)
Expand Down