Skip to content

Commit

Permalink
Merge branch 'develop' into matthew/fix-quicktime
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy committed Mar 22, 2022
2 parents 9a76bb0 + a80e55d commit 6a46c7a
Show file tree
Hide file tree
Showing 25 changed files with 2,544 additions and 2,772 deletions.
1 change: 1 addition & 0 deletions res/css/structures/_LeftPanel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ $roomListCollapsedWidth: 68px;
display: flex;
flex-direction: row;
flex: 1;
height: 100%; // ensure space panel is still scrollable with an outer wrapper

.mx_LeftPanel_wrapper--user {
background-color: $roomlist-bg-color;
Expand Down
20 changes: 10 additions & 10 deletions src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1465,24 +1465,24 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
setTimeout(() => {
if (SettingsStore.getValue("feature_thread") && SdkConfig.get("show_labs_settings")) {
Modal.createDialog(InfoDialog, {
title: _t("Threads are no longer experimental! 🎉"),
title: _t("Threads Approaching Beta 🎉"),
description: <>
<p>
{ _t("We’ve recently introduced key stability "
+ "improvements for Threads, which also means "
+ "phasing out support for experimental Threads.") }
{ _t("We're getting closer to releasing a public Beta for Threads.") }
</p>
<p>
{ _t("All thread events created during the "
+ "experimental period will now be rendered in "
+ "the room timeline and displayed as replies. "
+ "This is a one-off transition. Threads are now "
+ "part of the Matrix specification.") }
{ _t("As we prepare for it, we need to make some changes: threads created "
+ "before this point will be <strong>displayed as regular replies</strong>.",
{}, {
"strong": sub => <strong>{ sub }</strong>,
}) }
</p>
<p>
{ _t("Thank you for helping us testing Threads!") }
{ _t("This will be a one-off transition, as threads are now part "
+ "of the Matrix specification.") }
</p>
</>,
button: _t("Got it"),
onFinished: () => {
localStorage.setItem("mx_seen_feature_thread_experimental", "true");
},
Expand Down
8 changes: 4 additions & 4 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3098,10 +3098,10 @@
"Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s",
"Unable to copy room link": "Unable to copy room link",
"Unable to copy a link to the room to the clipboard.": "Unable to copy a link to the room to the clipboard.",
"Threads are no longer experimental! 🎉": "Threads are no longer experimental! 🎉",
"We’ve recently introduced key stability improvements for Threads, which also means phasing out support for experimental Threads.": "We’ve recently introduced key stability improvements for Threads, which also means phasing out support for experimental Threads.",
"All thread events created during the experimental period will now be rendered in the room timeline and displayed as replies. This is a one-off transition. Threads are now part of the Matrix specification.": "All thread events created during the experimental period will now be rendered in the room timeline and displayed as replies. This is a one-off transition. Threads are now part of the Matrix specification.",
"Thank you for helping us testing Threads!": "Thank you for helping us testing Threads!",
"Threads Approaching Beta 🎉": "Threads Approaching Beta 🎉",
"We're getting closer to releasing a public Beta for Threads.": "We're getting closer to releasing a public Beta for Threads.",
"As we prepare for it, we need to make some changes: threads created before this point will be <strong>displayed as regular replies</strong>.": "As we prepare for it, we need to make some changes: threads created before this point will be <strong>displayed as regular replies</strong>.",
"This will be a one-off transition, as threads are now part of the Matrix specification.": "This will be a one-off transition, as threads are now part of the Matrix specification.",
"New search beta available": "New search beta available",
"We're testing a new search to make finding what you want quicker.\n": "We're testing a new search to make finding what you want quicker.\n",
"Signed Out": "Signed Out",
Expand Down
6 changes: 5 additions & 1 deletion src/utils/Reply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
import { PERMITTED_URL_SCHEMES } from "../HtmlUtils";
import { makeUserPermalink, RoomPermalinkCreator } from "./permalinks/Permalinks";
import { RecursivePartial } from "../@types/common";
import SettingsStore from "../settings/SettingsStore";

export function getParentEventId(ev: MatrixEvent): string | undefined {
if (!ev || ev.isRedacted()) return;
Expand Down Expand Up @@ -178,7 +179,10 @@ export function shouldDisplayReply(event: MatrixEvent): boolean {
}

const relation = event.getRelation();
if (relation?.rel_type === THREAD_RELATION_TYPE.name && relation?.is_falling_back) {
if (SettingsStore.getValue("feature_thread") &&
relation?.rel_type === THREAD_RELATION_TYPE.name &&
relation?.is_falling_back
) {
return false;
}

Expand Down
36 changes: 36 additions & 0 deletions src/utils/beacon/duration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import { Beacon } from "matrix-js-sdk/src/matrix";

/**
* Get ms until expiry
* Returns 0 when expiry is already passed
* @param startTimestamp
* @param durationMs
* @returns remainingMs
*/
export const msUntilExpiry = (startTimestamp: number, durationMs: number): number =>
Math.max(0, (startTimestamp + durationMs) - Date.now());

export const getBeaconMsUntilExpiry = (beacon: Beacon): number =>
msUntilExpiry(beacon.beaconInfo.timestamp, beacon.beaconInfo.timeout);

export const getBeaconExpiryTimestamp = (beacon: Beacon): number =>
beacon.beaconInfo.timestamp + beacon.beaconInfo.timeout;

export const sortBeaconsByLatestExpiry = (left: Beacon, right: Beacon): number =>
getBeaconExpiryTimestamp(right) - getBeaconExpiryTimestamp(left);
17 changes: 17 additions & 0 deletions src/utils/beacon/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

export * from './duration';
14 changes: 8 additions & 6 deletions test/components/views/elements/AppTile-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ describe("AppTile", () => {
await RightPanelStore.instance.onReady();
});

beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockRestore();
});

it("tracks live tiles correctly", () => {
expect(AppTile.isLive("1", "r1")).toEqual(false);

Expand Down Expand Up @@ -196,7 +200,7 @@ describe("AppTile", () => {
it("distinguishes widgets with the same ID in different rooms", async () => {
// Set up right panel state
const realGetValue = SettingsStore.getValue;
SettingsStore.getValue = (name, roomId) => {
jest.spyOn(SettingsStore, 'getValue').mockImplementation((name, roomId) => {
if (name === "RightPanel.phases") {
if (roomId === "r1") {
return {
Expand All @@ -212,7 +216,7 @@ describe("AppTile", () => {
return null;
}
return realGetValue(name, roomId);
};
});

// Run initial render with room 1, and also running lifecycle methods
const renderer = TestRenderer.create(<MatrixClientContext.Provider value={cli}>
Expand All @@ -232,7 +236,7 @@ describe("AppTile", () => {
expect(AppTile.isLive("1", "r1")).toBe(true);
expect(AppTile.isLive("1", "r2")).toBe(false);

SettingsStore.getValue = (name, roomId) => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((name, roomId) => {
if (name === "RightPanel.phases") {
if (roomId === "r2") {
return {
Expand All @@ -248,7 +252,7 @@ describe("AppTile", () => {
return null;
}
return realGetValue(name, roomId);
};
});
// Wait for RPS room 2 updates to fire
const rpsUpdated2 = waitForRps("r2");
// Switch to room 2
Expand All @@ -266,8 +270,6 @@ describe("AppTile", () => {

expect(AppTile.isLive("1", "r1")).toBe(false);
expect(AppTile.isLive("1", "r2")).toBe(true);

SettingsStore.getValue = realGetValue;
});

it("preserves non-persisted widget on container move", async () => {
Expand Down
58 changes: 20 additions & 38 deletions test/components/views/elements/PollCreateDialog-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ import {
M_TEXT,
PollStartEvent,
} from 'matrix-events-sdk';
import { IContent, MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';

import {
wrapInMatrixClientContext,
findById,
stubClient,
getMockClientWithEventEmitter,
} from '../../../test-utils';
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import _PollCreateDialog from "../../../../src/components/views/elements/PollCreateDialog";
const PollCreateDialog = wrapInMatrixClientContext(_PollCreateDialog);
import PollCreateDialog from "../../../../src/components/views/elements/PollCreateDialog";
import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';

// Fake date to give a predictable snapshot
const realDateNow = Date.now;
Expand All @@ -51,9 +50,21 @@ afterAll(() => {
});

describe("PollCreateDialog", () => {
const mockClient = getMockClientWithEventEmitter({
sendEvent: jest.fn().mockResolvedValue({ event_id: '1' }),
});

beforeEach(() => {
mockClient.sendEvent.mockClear();
});

it("renders a blank poll", () => {
const dialog = mount(
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />,
{
wrappingComponent: MatrixClientContext.Provider,
wrappingComponentProps: { value: mockClient },
},
);
expect(dialog.html()).toMatchSnapshot();
});
Expand Down Expand Up @@ -207,9 +218,6 @@ describe("PollCreateDialog", () => {
});

it("displays a spinner after submitting", () => {
stubClient();
MatrixClientPeg.get().sendEvent = jest.fn(() => Promise.resolve());

const dialog = mount(
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />,
);
Expand All @@ -223,21 +231,6 @@ describe("PollCreateDialog", () => {
});

it("sends a poll create event when submitted", () => {
stubClient();
let sentEventContent: IContent = null;
MatrixClientPeg.get().sendEvent = jest.fn(
(
_roomId: string,
_threadId: string,
eventType: string,
content: IContent,
) => {
expect(M_POLL_START.matches(eventType)).toBeTruthy();
sentEventContent = content;
return Promise.resolve();
},
);

const dialog = mount(
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />,
);
Expand All @@ -246,6 +239,8 @@ describe("PollCreateDialog", () => {
changeValue(dialog, "Option 2", "A2");

dialog.find("button").simulate("click");
const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0];
expect(M_POLL_START.matches(eventType)).toBeTruthy();
expect(sentEventContent).toEqual(
{
[M_TEXT.name]: "Q\n1. A1\n2. A2",
Expand Down Expand Up @@ -275,21 +270,6 @@ describe("PollCreateDialog", () => {
});

it("sends a poll edit event when editing", () => {
stubClient();
let sentEventContent: IContent = null;
MatrixClientPeg.get().sendEvent = jest.fn(
(
_roomId: string,
_threadId: string,
eventType: string,
content: IContent,
) => {
expect(M_POLL_START.matches(eventType)).toBeTruthy();
sentEventContent = content;
return Promise.resolve();
},
);

const previousEvent: MatrixEvent = new MatrixEvent(
PollStartEvent.from(
"Poll Q",
Expand All @@ -312,6 +292,8 @@ describe("PollCreateDialog", () => {
changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name);
dialog.find("button").simulate("click");

const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0];
expect(M_POLL_START.matches(eventType)).toBeTruthy();
expect(sentEventContent).toEqual(
{
"m.new_content": {
Expand Down
15 changes: 10 additions & 5 deletions test/components/views/messages/DateSeparator-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ limitations under the License.

import React from "react";
import { mount } from "enzyme";
import { mocked } from "jest-mock";

import sdk from "../../../skinned-sdk";
import * as TestUtils from "../../../test-utils";
import { formatFullDateNoTime } from "../../../../src/DateUtils";
import SettingsStore from "../../../../src/settings/SettingsStore";
import { UIFeature } from "../../../../src/settings/UIFeature";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import { getMockClientWithEventEmitter } from "../../../test-utils";

jest.mock("../../../../src/settings/SettingsStore");

const _DateSeparator = sdk.getComponent("views.messages.DateSeparator");
const DateSeparator = TestUtils.wrapInMatrixClientContext(_DateSeparator);
const DateSeparator = sdk.getComponent("views.messages.DateSeparator");

describe("DateSeparator", () => {
const HOUR_MS = 3600000;
Expand All @@ -45,8 +46,12 @@ describe("DateSeparator", () => {
}
}

const mockClient = getMockClientWithEventEmitter({});
const getComponent = (props = {}) =>
mount(<DateSeparator {...defaultProps} {...props} />);
mount(<DateSeparator {...defaultProps} {...props} />, {
wrappingComponent: MatrixClientContext.Provider,
wrappingComponentProps: { value: mockClient },
});

type TestCase = [string, number, string];
const testCases: TestCase[] = [
Expand Down Expand Up @@ -106,7 +111,7 @@ describe("DateSeparator", () => {

describe('when feature_jump_to_date is enabled', () => {
beforeEach(() => {
(SettingsStore.getValue as jest.Mock) = jest.fn((arg) => {
mocked(SettingsStore).getValue.mockImplementation((arg) => {
if (arg === "feature_jump_to_date") {
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion test/components/views/messages/MLocationBody-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ describe("MLocationBody", () => {

describe("isSelfLocation", () => {
it("Returns true for a full m.asset event", () => {
const content = makeLocationContent("", 0);
const content = makeLocationContent("", '0');
expect(isSelfLocation(content)).toBe(true);
});

Expand Down
Loading

0 comments on commit 6a46c7a

Please sign in to comment.