Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rm/1937 ho c part4 #44

Open
wants to merge 4 commits into
base: verji-develop
Choose a base branch
from
Open
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
27 changes: 20 additions & 7 deletions src/components/views/elements/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

import React, { ErrorInfo, ReactNode } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import {
CustomComponentLifecycle,
CustomComponentOpts,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle";

Check failure on line 22 in src/components/views/elements/ErrorBoundary.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle' or its corresponding type declarations.

import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
Expand All @@ -24,6 +28,7 @@
import SdkConfig from "../../../SdkConfig";
import BugReportDialog from "../dialogs/BugReportDialog";
import AccessibleButton from "./AccessibleButton";
import { ModuleRunner } from "../../../modules/ModuleRunner";

interface Props {
children: ReactNode;
Expand Down Expand Up @@ -76,6 +81,12 @@
};

public render(): ReactNode {
const CustomErrorBoundary = { CustomComponent: React.Fragment };
ModuleRunner.instance.invoke(
CustomComponentLifecycle.ErrorBoundary,
CustomErrorBoundary as CustomComponentOpts,
);

if (this.state.error) {
const newIssueUrl = SdkConfig.get().feedback.new_issue_url;

Expand Down Expand Up @@ -121,16 +132,18 @@
}

return (
<div className="mx_ErrorBoundary">
<div className="mx_ErrorBoundary_body">
<h1>{_t("error|something_went_wrong")}</h1>
{bugReportSection}
{clearCacheButton}
<CustomErrorBoundary.CustomComponent>
<div className="mx_ErrorBoundary">
<div className="mx_ErrorBoundary_body">
<h1>{_t("error|something_went_wrong")}</h1>
{bugReportSection}
{clearCacheButton}
</div>
</div>
</div>
</CustomErrorBoundary.CustomComponent>
);
}

return this.props.children;
return <CustomErrorBoundary.CustomComponent>{this.props.children}</CustomErrorBoundary.CustomComponent>;
}
}
40 changes: 25 additions & 15 deletions src/components/views/rooms/EntityTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@

import React from "react";
import classNames from "classnames";
import {
CustomComponentLifecycle,
CustomComponentOpts,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle";

Check failure on line 24 in src/components/views/rooms/EntityTile.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Cannot find module '@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle' or its corresponding type declarations.

import AccessibleButton from "../elements/AccessibleButton";
import { _t, _td, TranslationKey } from "../../../languageHandler";
import E2EIcon, { E2EState } from "./E2EIcon";
import BaseAvatar from "../avatars/BaseAvatar";
import PresenceLabel from "./PresenceLabel";
import { ModuleRunner } from "../../../modules/ModuleRunner";

export enum PowerStatus {
Admin = "admin",
Expand Down Expand Up @@ -172,23 +177,28 @@

const av = this.props.avatarJsx || <BaseAvatar name={this.props.name} size="36px" aria-hidden="true" />;

const CustomEntityTile = { CustomComponent: React.Fragment };
ModuleRunner.instance.invoke(CustomComponentLifecycle.EntityTile, CustomEntityTile as CustomComponentOpts);

// The wrapping div is required to make the magic mouse listener work, for some reason.
return (
<div>
<AccessibleButton
className={classNames(mainClassNames)}
title={this.props.title}
onClick={this.props.onClick}
>
<div className="mx_EntityTile_avatar">
{av}
{e2eIcon}
</div>
{nameAndPresence}
{powerLabel}
{inviteButton}
</AccessibleButton>
</div>
<CustomEntityTile.CustomComponent>
<div>
<AccessibleButton
className={classNames(mainClassNames)}
title={this.props.title}
onClick={this.props.onClick}
>
<div className="mx_EntityTile_avatar">
{av}
{e2eIcon}
</div>
{nameAndPresence}
{powerLabel}
{inviteButton}
</AccessibleButton>
</div>
</CustomEntityTile.CustomComponent>
);
}
}
113 changes: 63 additions & 50 deletions src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ limitations under the License.

import React, { ReactNode } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import {
CustomComponentLifecycle,
CustomComponentOpts,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle";

import AccessibleButton from "../../../elements/AccessibleButton";
import { _t } from "../../../../../languageHandler";
Expand All @@ -30,6 +34,7 @@ import { SettingsSection } from "../../shared/SettingsSection";
import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection";
import ExternalLink from "../../../elements/ExternalLink";
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
import { ModuleRunner } from "../../../../../modules/ModuleRunner";

interface IProps {}

Expand Down Expand Up @@ -262,66 +267,74 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>

const { appVersion, cryptoVersion } = this.getVersionInfo();

const CustomHelpUserSettingsTab = { CustomComponent: React.Fragment };
ModuleRunner.instance.invoke(
CustomComponentLifecycle.HelpUserSettingsTab,
CustomHelpUserSettingsTab as CustomComponentOpts,
);

return (
<SettingsTab>
<SettingsSection>
{bugReportingSection}
<SettingsSubsection heading={_t("common|faq")} description={faqText} />
<SettingsSubsection heading={_t("setting|help_about|versions")}>
<SettingsSubsectionText>
<CopyableText getTextToCopy={this.getVersionTextToCopy}>
{appVersion}
<br />
{cryptoVersion}
<br />
</CopyableText>
{updateButton}
</SettingsSubsectionText>
</SettingsSubsection>
{this.renderLegal()}
{this.renderCredits()}
<SettingsSubsection heading={_t("common|advanced")}>
<SettingsSubsectionText>
{_t(
"setting|help_about|homeserver",
{
homeserverUrl: this.context.getHomeserverUrl(),
},
{
code: (sub) => <code>{sub}</code>,
},
)}
</SettingsSubsectionText>
{this.context.getIdentityServerUrl() && (
<CustomHelpUserSettingsTab.CustomComponent>
<SettingsTab>
<SettingsSection>
{bugReportingSection}
<SettingsSubsection heading={_t("common|faq")} description={faqText} />
<SettingsSubsection heading={_t("setting|help_about|versions")}>
<SettingsSubsectionText>
<CopyableText getTextToCopy={this.getVersionTextToCopy}>
{appVersion}
<br />
{cryptoVersion}
<br />
</CopyableText>
{updateButton}
</SettingsSubsectionText>
</SettingsSubsection>
{this.renderLegal()}
{this.renderCredits()}
<SettingsSubsection heading={_t("common|advanced")}>
<SettingsSubsectionText>
{_t(
"setting|help_about|identity_server",
"setting|help_about|homeserver",
{
identityServerUrl: this.context.getIdentityServerUrl(),
homeserverUrl: this.context.getHomeserverUrl(),
},
{
code: (sub) => <code>{sub}</code>,
},
)}
</SettingsSubsectionText>
)}
<SettingsSubsectionText>
<details>
<summary className="mx_HelpUserSettingsTab_accessTokenDetails">
{_t("common|access_token")}
</summary>
<b>{_t("setting|help_about|access_token_detail")}</b>
<CopyableText getTextToCopy={() => this.context.getAccessToken()}>
{this.context.getAccessToken()}
</CopyableText>
</details>
</SettingsSubsectionText>
<AccessibleButton onClick={this.onClearCacheAndReload} kind="danger_outline">
{_t("setting|help_about|clear_cache_reload")}
</AccessibleButton>
</SettingsSubsection>
</SettingsSection>
</SettingsTab>
{this.context.getIdentityServerUrl() && (
<SettingsSubsectionText>
{_t(
"setting|help_about|identity_server",
{
identityServerUrl: this.context.getIdentityServerUrl(),
},
{
code: (sub) => <code>{sub}</code>,
},
)}
</SettingsSubsectionText>
)}
<SettingsSubsectionText>
<details>
<summary className="mx_HelpUserSettingsTab_accessTokenDetails">
{_t("common|access_token")}
</summary>
<b>{_t("setting|help_about|access_token_detail")}</b>
<CopyableText getTextToCopy={() => this.context.getAccessToken()}>
{this.context.getAccessToken()}
</CopyableText>
</details>
</SettingsSubsectionText>
<AccessibleButton onClick={this.onClearCacheAndReload} kind="danger_outline">
{_t("setting|help_about|clear_cache_reload")}
</AccessibleButton>
</SettingsSubsection>
</SettingsSection>
</SettingsTab>
</CustomHelpUserSettingsTab.CustomComponent>
);
}
}
54 changes: 54 additions & 0 deletions test/components/structures/EntityTile-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright 2024 Verji Tech AS. All rights reserved.
Unauthorized copying or distribution of this file, via any medium, is strictly prohibited.
*/

import React from "react";
import { render, screen } from "@testing-library/react";
import {
CustomComponentLifecycle,
CustomComponentOpts,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle";

import EntityTile from "../../../src/components/views/rooms/EntityTile";
import { ModuleRunner } from "../../../src/modules/ModuleRunner";

describe("EntityTile", () => {
const renderComp = () => {
render(<EntityTile />);
};

beforeEach(() => {
jest.clearAllMocks();
});

it("should render", () => {
renderComp();
expect(screen.getByTestId("avatar-img")).toBeDefined();
});

describe("wrap the EntityTile with a React.Fragment", () => {
it("should wrap the EntityTile with a React.Fragment", () => {
jest.spyOn(ModuleRunner.instance, "invoke").mockImplementation((lifecycleEvent, opts) => {
if (lifecycleEvent === CustomComponentLifecycle.EntityTile) {
(opts as CustomComponentOpts).CustomComponent = ({ children }) => {
return (
<>
<div data-testid="wrapper-header">Header</div>
<div data-testid="wrapper-EntityTile">{children}</div>
<div data-testid="wrapper-footer">Footer</div>
</>
);
};
}
});

renderComp();
expect(screen.getByTestId("wrapper-header")).toBeDefined();
expect(screen.getByTestId("wrapper-EntityTile")).toBeDefined();
expect(screen.getByTestId("wrapper-footer")).toBeDefined();
expect(screen.getByTestId("wrapper-header").nextSibling).toBe(screen.getByTestId("wrapper-EntityTile"));
expect(screen.getByTestId("wrapper-EntityTile").nextSibling).toBe(screen.getByTestId("wrapper-footer"));
});
});
});
58 changes: 58 additions & 0 deletions test/components/structures/ErrorBoundary-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright 2024 Verji Tech AS. All rights reserved.
Unauthorized copying or distribution of this file, via any medium, is strictly prohibited.
*/

import React from "react";
import { render, screen } from "@testing-library/react";
import {
CustomComponentLifecycle,
CustomComponentOpts,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CustomComponentLifecycle";

import ErrorBoundary from "../../../src/components/views/elements/ErrorBoundary";
import { ModuleRunner } from "../../../src/modules/ModuleRunner";

describe("ErrorBoundary", () => {
const renderComp = () => {
render(
<ErrorBoundary>
<div>🤘</div>
</ErrorBoundary>,
);
};

beforeEach(() => {
jest.clearAllMocks();
});

it("should render", () => {
renderComp();
expect(screen.getByText("🤘")).toBeDefined();
});

describe("wrap the ErrorBoundary with a React.Fragment", () => {
it("should wrap the ErrorBoundary with a React.Fragment", () => {
jest.spyOn(ModuleRunner.instance, "invoke").mockImplementation((lifecycleEvent, opts) => {
if (lifecycleEvent === CustomComponentLifecycle.ErrorBoundary) {
(opts as CustomComponentOpts).CustomComponent = ({ children }) => {
return (
<>
<div data-testid="wrapper-header">Header</div>
<div data-testid="wrapper-ErrorBoundary">{children}</div>
<div data-testid="wrapper-footer">Footer</div>
</>
);
};
}
});

renderComp();
expect(screen.getByTestId("wrapper-header")).toBeDefined();
expect(screen.getByTestId("wrapper-ErrorBoundary")).toBeDefined();
expect(screen.getByTestId("wrapper-footer")).toBeDefined();
expect(screen.getByTestId("wrapper-header").nextSibling).toBe(screen.getByTestId("wrapper-ErrorBoundary"));
expect(screen.getByTestId("wrapper-ErrorBoundary").nextSibling).toBe(screen.getByTestId("wrapper-footer"));
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ describe("ReactionsRowButtonTooltip", () => {

it("should render", () => {
const { asFragment } = getComp();
screen.debug();
expect(asFragment()).toMatchSnapshot();
});

Expand Down
Loading
Loading