Merge branch 'develop' into kegan/lists-as-keys
commit
6ec25234d7
res
css/views
context_menus
rooms
wysiwyg_composer/components
img/element-icons/room/composer
src
components/views
rooms
voip
hooks
i18n/strings
test/components/views/rooms/wysiwyg_composer/components
|
@ -1,3 +1,9 @@
|
|||
Changes in [3.64.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.64.2) (2023-01-20)
|
||||
=====================================================================================================
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix second occurence of a crash in older browsers
|
||||
|
||||
Changes in [3.64.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.64.1) (2023-01-18)
|
||||
=====================================================================================================
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "matrix-react-sdk",
|
||||
"version": "3.64.1",
|
||||
"version": "3.64.2",
|
||||
"description": "SDK for matrix.org using React",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
|
@ -57,7 +57,7 @@
|
|||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@matrix-org/analytics-events": "^0.4.0",
|
||||
"@matrix-org/matrix-wysiwyg": "^0.19.0",
|
||||
"@matrix-org/matrix-wysiwyg": "^0.20.0",
|
||||
"@matrix-org/react-sdk-module-api": "^0.0.3",
|
||||
"@sentry/browser": "^7.0.0",
|
||||
"@sentry/tracing": "^7.0.0",
|
||||
|
|
|
@ -84,7 +84,7 @@ limitations under the License.
|
|||
align-items: center;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
&:focus-visible {
|
||||
background-color: $menu-selected-color;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ limitations under the License.
|
|||
display: flex;
|
||||
user-select: none;
|
||||
|
||||
&:not(.mx_RoomHeader_name--textonly):hover {
|
||||
&:hover {
|
||||
background-color: $quinary-content;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,21 @@ limitations under the License.
|
|||
padding-inline-start: $spacing-28;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: #777;
|
||||
border-left: 2px solid $blockquote-bar-color;
|
||||
border-radius: 2px;
|
||||
padding: 0 10px;
|
||||
|
||||
margin-block-start: 0;
|
||||
margin-block-end: 0;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
// model output always includes a linebreak but we do not want the user
|
||||
// to see it when writing input in lists
|
||||
:is(ol, ul, pre) + br:last-of-type {
|
||||
:is(ol, ul, pre, blockquote) + br:last-of-type {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,4 +17,5 @@ limitations under the License.
|
|||
.mx_CallDuration {
|
||||
color: $secondary-content;
|
||||
font-size: $font-12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ limitations under the License.
|
|||
content: "";
|
||||
display: inline-block;
|
||||
mask-image: url("$(res)/img/feather-customised/chevron-down.svg");
|
||||
mask-size: $size;
|
||||
mask-size: 20px;
|
||||
mask-position: center;
|
||||
background-color: $call-primary-content;
|
||||
height: 100%;
|
||||
|
@ -181,7 +181,7 @@ limitations under the License.
|
|||
.mx_CallView_deviceButton {
|
||||
&.mx_CallView_deviceButton_audio::before {
|
||||
mask-image: url("$(res)/img/element-icons/Mic-off.svg");
|
||||
mask-size: 14px;
|
||||
mask-size: 18px;
|
||||
}
|
||||
|
||||
&.mx_CallView_deviceButton_video::before {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.1458 0.893371C2.20888 0.465499 1.90205 0.0690897 1.46046 0.00796516C1.01887 -0.0531594 0.609758 0.244148 0.546674 0.67202L0.00822047 4.32413C-0.0548633 4.752 0.251974 5.14841 0.69356 5.20954C1.13515 5.27066 1.54426 4.97336 1.60735 4.54548L2.1458 0.893371Z" fill="currentColor"/>
|
||||
<path d="M10.2226 7.67587C10.2857 7.248 9.97885 6.85159 9.53726 6.79046C9.09568 6.72934 8.68656 7.02664 8.62348 7.45452L8.08502 11.1066C8.02194 11.5345 8.32878 11.9309 8.77036 11.992C9.21195 12.0532 9.62107 11.7559 9.68415 11.328L10.2226 7.67587Z" fill="currentColor"/>
|
||||
<path d="M5.21224 0.00574343C5.65509 0.0575575 5.97074 0.447414 5.91727 0.876513L5.90255 0.993287C5.89309 1.06788 5.87936 1.17541 5.86224 1.30757C5.828 1.57178 5.78013 1.93492 5.72561 2.33035C5.6179 3.11153 5.48009 4.04989 5.36895 4.58829C5.28147 5.01211 4.85597 5.28697 4.41856 5.20221C3.98115 5.11744 3.69748 4.70515 3.78496 4.28133C3.88411 3.80099 4.01552 2.91329 4.12447 2.12309C4.17828 1.73284 4.22559 1.37397 4.25946 1.11259C4.27639 0.981947 4.28994 0.875787 4.29925 0.802389L4.31351 0.689266C4.36698 0.260167 4.76938 -0.0460706 5.21224 0.00574343Z" fill="currentColor"/>
|
||||
<path d="M13.9918 7.67587C14.0549 7.248 13.748 6.85159 13.3064 6.79046C12.8649 6.72934 12.4557 7.02664 12.3927 7.45452L11.8542 11.1066C11.7911 11.5345 12.098 11.9309 12.5395 11.992C12.9811 12.0532 13.3902 11.7559 13.4533 11.328L13.9918 7.67587Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -336,6 +336,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
|
|||
const { permalinkCreator, relation, replyToEvent } = this.props;
|
||||
const composerContent = this.state.composerContent;
|
||||
this.setState({ composerContent: "", initialComposerContent: "" });
|
||||
dis.dispatch({ action: Action.ClearAndFocusSendMessageComposer });
|
||||
await sendMessage(composerContent, this.state.isRichTextEnabled, {
|
||||
mxClient: this.props.mxClient,
|
||||
roomContext: this.context,
|
||||
|
@ -343,7 +344,6 @@ export class MessageComposer extends React.Component<IProps, IState> {
|
|||
relation,
|
||||
replyToEvent,
|
||||
});
|
||||
dis.dispatch({ action: Action.ClearAndFocusSendMessageComposer });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -743,6 +743,13 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
|||
|
||||
const buttons = this.props.showButtons ? this.renderButtons(isVideoRoom) : null;
|
||||
|
||||
let oobName = _t("Join Room");
|
||||
if (this.props.oobData && this.props.oobData.name) {
|
||||
oobName = this.props.oobData.name;
|
||||
}
|
||||
|
||||
const name = this.renderName(oobName);
|
||||
|
||||
if (this.props.viewingCall && !isVideoRoom) {
|
||||
return (
|
||||
<header className="mx_RoomHeader light-panel">
|
||||
|
@ -752,9 +759,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
|||
>
|
||||
<div className="mx_RoomHeader_avatar">{roomAvatar}</div>
|
||||
{icon}
|
||||
<div className="mx_RoomHeader_name mx_RoomHeader_name--textonly mx_RoomHeader_name--small">
|
||||
{_t("Video call")}
|
||||
</div>
|
||||
{name}
|
||||
{this.props.activeCall instanceof ElementCall && (
|
||||
<GroupCallDuration groupCall={this.props.activeCall.groupCall} />
|
||||
)}
|
||||
|
@ -779,13 +784,6 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
let oobName = _t("Join Room");
|
||||
if (this.props.oobData && this.props.oobData.name) {
|
||||
oobName = this.props.oobData.name;
|
||||
}
|
||||
|
||||
const name = this.renderName(oobName);
|
||||
|
||||
const topicElement = <RoomTopic room={this.props.room} className="mx_RoomHeader_topic" />;
|
||||
|
||||
const viewLabs = (): void =>
|
||||
|
|
|
@ -22,6 +22,7 @@ import { Icon as BoldIcon } from "../../../../../../res/img/element-icons/room/c
|
|||
import { Icon as ItalicIcon } from "../../../../../../res/img/element-icons/room/composer/italic.svg";
|
||||
import { Icon as UnderlineIcon } from "../../../../../../res/img/element-icons/room/composer/underline.svg";
|
||||
import { Icon as StrikeThroughIcon } from "../../../../../../res/img/element-icons/room/composer/strikethrough.svg";
|
||||
import { Icon as QuoteIcon } from "../../../../../../res/img/element-icons/room/composer/quote.svg";
|
||||
import { Icon as InlineCodeIcon } from "../../../../../../res/img/element-icons/room/composer/inline_code.svg";
|
||||
import { Icon as LinkIcon } from "../../../../../../res/img/element-icons/room/composer/link.svg";
|
||||
import { Icon as BulletedListIcon } from "../../../../../../res/img/element-icons/room/composer/bulleted_list.svg";
|
||||
|
@ -126,6 +127,12 @@ export function FormattingButtons({ composer, actionStates }: FormattingButtonsP
|
|||
onClick={() => composer.orderedList()}
|
||||
icon={<NumberedListIcon className="mx_FormattingButtons_Icon" />}
|
||||
/>
|
||||
<Button
|
||||
actionState={actionStates.quote}
|
||||
label={_td("Quote")}
|
||||
onClick={() => composer.quote()}
|
||||
icon={<QuoteIcon className="mx_FormattingButtons_Icon" />}
|
||||
/>
|
||||
<Button
|
||||
actionState={actionStates.inlineCode}
|
||||
label={_td("Code")}
|
||||
|
|
|
@ -38,7 +38,7 @@ import IconizedContextMenu, {
|
|||
IconizedContextMenuOption,
|
||||
IconizedContextMenuOptionList,
|
||||
} from "../context_menus/IconizedContextMenu";
|
||||
import { aboveLeftOf, ContextMenuButton, useContextMenu } from "../../structures/ContextMenu";
|
||||
import { aboveRightOf, ContextMenuButton, useContextMenu } from "../../structures/ContextMenu";
|
||||
import { Alignment } from "../elements/Tooltip";
|
||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||
|
@ -81,7 +81,7 @@ const DeviceButton: FC<DeviceButtonProps> = ({
|
|||
if (showMenu) {
|
||||
const buttonRect = buttonRef.current!.getBoundingClientRect();
|
||||
contextMenu = (
|
||||
<IconizedContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu}>
|
||||
<IconizedContextMenu {...aboveRightOf(buttonRect, undefined, 10)} onFinished={closeMenu}>
|
||||
<IconizedContextMenuOptionList>
|
||||
{devices.map((d) => (
|
||||
<IconizedContextMenuOption key={d.deviceId} label={d.label} onClick={() => selectDevice(d)} />
|
||||
|
@ -101,6 +101,7 @@ const DeviceButton: FC<DeviceButtonProps> = ({
|
|||
>
|
||||
<AccessibleTooltipButton
|
||||
className={`mx_CallView_deviceButton mx_CallView_deviceButton_${kind}`}
|
||||
inputRef={buttonRef}
|
||||
title={muted ? mutedTitle : unmutedTitle}
|
||||
alignment={Alignment.Top}
|
||||
onClick={toggle}
|
||||
|
@ -109,7 +110,6 @@ const DeviceButton: FC<DeviceButtonProps> = ({
|
|||
{devices.length > 1 ? (
|
||||
<ContextMenuButton
|
||||
className="mx_CallView_deviceListButton"
|
||||
inputRef={buttonRef}
|
||||
onClick={openMenu}
|
||||
isExpanded={showMenu}
|
||||
label={deviceListLabel}
|
||||
|
|
|
@ -63,6 +63,9 @@ export function useEventEmitter(emitter: EventEmitter | undefined, eventName: st
|
|||
|
||||
type Mapper<T> = (...args: any[]) => T;
|
||||
|
||||
/**
|
||||
* {@link useEventEmitterState}
|
||||
*/
|
||||
export function useTypedEventEmitterState<T, Events extends string, Arguments extends ListenerMap<Events>>(
|
||||
emitter: TypedEventEmitter<Events, Arguments>,
|
||||
eventName: Events,
|
||||
|
@ -71,6 +74,16 @@ export function useTypedEventEmitterState<T, Events extends string, Arguments ex
|
|||
return useEventEmitterState<T>(emitter, eventName, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a state, that can be updated by events.
|
||||
*
|
||||
* @param emitter The emitter sending the event
|
||||
* @param eventName Event name to listen for
|
||||
* @param fn The callback function, that should return the state value.
|
||||
* It should have the signature of the event callback, except that all parameters are optional.
|
||||
* If the params are not set, a default value for the state should be returned.
|
||||
* @returns State
|
||||
*/
|
||||
export function useEventEmitterState<T>(
|
||||
emitter: EventEmitter | undefined,
|
||||
eventName: string | symbol,
|
||||
|
|
|
@ -1997,9 +1997,9 @@
|
|||
"Close call": "Close call",
|
||||
"View chat timeline": "View chat timeline",
|
||||
"Room options": "Room options",
|
||||
"Join Room": "Join Room",
|
||||
"(~%(count)s results)|other": "(~%(count)s results)",
|
||||
"(~%(count)s results)|one": "(~%(count)s result)",
|
||||
"Join Room": "Join Room",
|
||||
"Video rooms are a beta feature": "Video rooms are a beta feature",
|
||||
"Video room": "Video room",
|
||||
"Public space": "Public space",
|
||||
|
|
|
@ -14,9 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
||||
import { VoiceBroadcastPlayback } from "../models/VoiceBroadcastPlayback";
|
||||
import {
|
||||
VoiceBroadcastPlaybacksStore,
|
||||
|
@ -28,15 +26,11 @@ export const useCurrentVoiceBroadcastPlayback = (
|
|||
): {
|
||||
currentVoiceBroadcastPlayback: VoiceBroadcastPlayback | null;
|
||||
} => {
|
||||
const [currentVoiceBroadcastPlayback, setVoiceBroadcastPlayback] = useState(
|
||||
voiceBroadcastPlaybackStore.getCurrent(),
|
||||
);
|
||||
|
||||
useTypedEventEmitter(
|
||||
const currentVoiceBroadcastPlayback = useTypedEventEmitterState(
|
||||
voiceBroadcastPlaybackStore,
|
||||
VoiceBroadcastPlaybacksStoreEvent.CurrentChanged,
|
||||
(playback: VoiceBroadcastPlayback) => {
|
||||
setVoiceBroadcastPlayback(playback);
|
||||
(playback?: VoiceBroadcastPlayback) => {
|
||||
return playback ?? voiceBroadcastPlaybackStore.getCurrent();
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -14,9 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
||||
import { VoiceBroadcastPreRecordingStore } from "../stores/VoiceBroadcastPreRecordingStore";
|
||||
import { VoiceBroadcastPreRecording } from "../models/VoiceBroadcastPreRecording";
|
||||
|
||||
|
@ -25,12 +23,14 @@ export const useCurrentVoiceBroadcastPreRecording = (
|
|||
): {
|
||||
currentVoiceBroadcastPreRecording: VoiceBroadcastPreRecording | null;
|
||||
} => {
|
||||
const [currentVoiceBroadcastPreRecording, setCurrentVoiceBroadcastPreRecording] = useState(
|
||||
voiceBroadcastPreRecordingStore.getCurrent(),
|
||||
const currentVoiceBroadcastPreRecording = useTypedEventEmitterState(
|
||||
voiceBroadcastPreRecordingStore,
|
||||
"changed",
|
||||
(preRecording?: VoiceBroadcastPreRecording) => {
|
||||
return preRecording ?? voiceBroadcastPreRecordingStore.getCurrent();
|
||||
},
|
||||
);
|
||||
|
||||
useTypedEventEmitter(voiceBroadcastPreRecordingStore, "changed", setCurrentVoiceBroadcastPreRecording);
|
||||
|
||||
return {
|
||||
currentVoiceBroadcastPreRecording,
|
||||
};
|
||||
|
|
|
@ -14,24 +14,20 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { VoiceBroadcastRecording, VoiceBroadcastRecordingsStore, VoiceBroadcastRecordingsStoreEvent } from "..";
|
||||
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
||||
|
||||
export const useCurrentVoiceBroadcastRecording = (
|
||||
voiceBroadcastRecordingsStore: VoiceBroadcastRecordingsStore,
|
||||
): {
|
||||
currentVoiceBroadcastRecording: VoiceBroadcastRecording;
|
||||
} => {
|
||||
const [currentVoiceBroadcastRecording, setCurrentVoiceBroadcastRecording] = useState(
|
||||
voiceBroadcastRecordingsStore.getCurrent(),
|
||||
);
|
||||
|
||||
useTypedEventEmitter(
|
||||
const currentVoiceBroadcastRecording = useTypedEventEmitterState(
|
||||
voiceBroadcastRecordingsStore,
|
||||
VoiceBroadcastRecordingsStoreEvent.CurrentChanged,
|
||||
setCurrentVoiceBroadcastRecording,
|
||||
(recording?: VoiceBroadcastRecording) => {
|
||||
return recording ?? voiceBroadcastRecordingsStore.getCurrent();
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
|
||||
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import {
|
||||
VoiceBroadcastLiveness,
|
||||
VoiceBroadcastPlayback,
|
||||
VoiceBroadcastPlaybackEvent,
|
||||
VoiceBroadcastPlaybackState,
|
||||
VoiceBroadcastPlaybackTimes,
|
||||
} from "..";
|
||||
|
||||
export const useVoiceBroadcastPlayback = (
|
||||
|
@ -52,24 +52,35 @@ export const useVoiceBroadcastPlayback = (
|
|||
playback.toggle();
|
||||
};
|
||||
|
||||
const [playbackState, setPlaybackState] = useState(playback.getState());
|
||||
useTypedEventEmitter(
|
||||
const playbackState = useTypedEventEmitterState(
|
||||
playback,
|
||||
VoiceBroadcastPlaybackEvent.StateChanged,
|
||||
(state: VoiceBroadcastPlaybackState, _playback: VoiceBroadcastPlayback) => {
|
||||
setPlaybackState(state);
|
||||
(state?: VoiceBroadcastPlaybackState) => {
|
||||
return state ?? playback.getState();
|
||||
},
|
||||
);
|
||||
|
||||
const [times, setTimes] = useState({
|
||||
duration: playback.durationSeconds,
|
||||
position: playback.timeSeconds,
|
||||
timeLeft: playback.timeLeftSeconds,
|
||||
});
|
||||
useTypedEventEmitter(playback, VoiceBroadcastPlaybackEvent.TimesChanged, (t) => setTimes(t));
|
||||
const times = useTypedEventEmitterState(
|
||||
playback,
|
||||
VoiceBroadcastPlaybackEvent.TimesChanged,
|
||||
(t?: VoiceBroadcastPlaybackTimes) => {
|
||||
return (
|
||||
t ?? {
|
||||
duration: playback.durationSeconds,
|
||||
position: playback.timeSeconds,
|
||||
timeLeft: playback.timeLeftSeconds,
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const [liveness, setLiveness] = useState(playback.getLiveness());
|
||||
useTypedEventEmitter(playback, VoiceBroadcastPlaybackEvent.LivenessChanged, (l) => setLiveness(l));
|
||||
const liveness = useTypedEventEmitterState(
|
||||
playback,
|
||||
VoiceBroadcastPlaybackEvent.LivenessChanged,
|
||||
(l?: VoiceBroadcastLiveness) => {
|
||||
return l ?? playback.getLiveness();
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
times,
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
VoiceBroadcastInfoState,
|
||||
|
@ -25,7 +25,7 @@ import {
|
|||
VoiceBroadcastRecordingState,
|
||||
} from "..";
|
||||
import QuestionDialog from "../../components/views/dialogs/QuestionDialog";
|
||||
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
||||
import { _t } from "../../languageHandler";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import Modal from "../../Modal";
|
||||
|
@ -74,17 +74,21 @@ export const useVoiceBroadcastRecording = (
|
|||
}
|
||||
};
|
||||
|
||||
const [recordingState, setRecordingState] = useState(recording.getState());
|
||||
useTypedEventEmitter(
|
||||
const recordingState = useTypedEventEmitterState(
|
||||
recording,
|
||||
VoiceBroadcastRecordingEvent.StateChanged,
|
||||
(state: VoiceBroadcastInfoState, _recording: VoiceBroadcastRecording) => {
|
||||
setRecordingState(state);
|
||||
(state?: VoiceBroadcastRecordingState) => {
|
||||
return state ?? recording.getState();
|
||||
},
|
||||
);
|
||||
|
||||
const [timeLeft, setTimeLeft] = useState(recording.getTimeLeft());
|
||||
useTypedEventEmitter(recording, VoiceBroadcastRecordingEvent.TimeLeftChanged, setTimeLeft);
|
||||
const timeLeft = useTypedEventEmitterState(
|
||||
recording,
|
||||
VoiceBroadcastRecordingEvent.TimeLeftChanged,
|
||||
(t?: number) => {
|
||||
return t ?? recording.getTimeLeft();
|
||||
},
|
||||
);
|
||||
|
||||
const live = (
|
||||
[VoiceBroadcastInfoState.Started, VoiceBroadcastInfoState.Resumed] as VoiceBroadcastRecordingState[]
|
||||
|
|
|
@ -57,7 +57,7 @@ export enum VoiceBroadcastPlaybackEvent {
|
|||
InfoStateChanged = "info_state_changed",
|
||||
}
|
||||
|
||||
type VoiceBroadcastPlaybackTimes = {
|
||||
export type VoiceBroadcastPlaybackTimes = {
|
||||
duration: number;
|
||||
position: number;
|
||||
timeLeft: number;
|
||||
|
|
|
@ -32,6 +32,7 @@ const mockWysiwyg = {
|
|||
link: jest.fn(),
|
||||
orderedList: jest.fn(),
|
||||
unorderedList: jest.fn(),
|
||||
quote: jest.fn(),
|
||||
} as unknown as FormattingFunctions;
|
||||
|
||||
const openLinkModalSpy = jest.spyOn(LinkModal, "openLinkModal");
|
||||
|
@ -49,6 +50,7 @@ const testCases: Record<
|
|||
link: { label: "Link", mockFormatFn: openLinkModalSpy },
|
||||
orderedList: { label: "Numbered list", mockFormatFn: mockWysiwyg.orderedList },
|
||||
unorderedList: { label: "Bulleted list", mockFormatFn: mockWysiwyg.unorderedList },
|
||||
quote: { label: "Quote", mockFormatFn: mockWysiwyg.quote },
|
||||
};
|
||||
|
||||
const createActionStates = (state: ActionState): AllActionStates => {
|
||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -1589,10 +1589,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-js/-/matrix-sdk-crypto-js-0.1.0-alpha.2.tgz#a09d0fea858e817da971a3c9f904632ef7b49eb6"
|
||||
integrity sha512-oVkBCh9YP7H9i4gAoQbZzswniczfo/aIptNa4dxRi4Ff9lSvUCFv6Hvzi7C+90c0/PWZLXjIDTIAWZYmwyd2fA==
|
||||
|
||||
"@matrix-org/matrix-wysiwyg@^0.19.0":
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-wysiwyg/-/matrix-wysiwyg-0.19.0.tgz#5ffbabf8a59317ecdb45ba5fa1d06fff150ede40"
|
||||
integrity sha512-1iL/+kjwWAlpWAq64DbkDkE7KGxvR5lNojZgCKMIyuvuKWv8Ikqxa9VOOYFtovKvSqgGRJaYN7/OkKWxZjiDcw==
|
||||
"@matrix-org/matrix-wysiwyg@^0.20.0":
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-wysiwyg/-/matrix-wysiwyg-0.20.0.tgz#6193f790b031eaa96e944b647fe2b27018639d57"
|
||||
integrity sha512-9VqzyccwizglssShi/M+tCxdZDgzsecH4WjlS0HC5KkLmljIxxlHFstf/D3C/G4ZfRodFUh6wUvd+oQI/ScPpw==
|
||||
|
||||
"@matrix-org/olm@https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz":
|
||||
version "3.2.14"
|
||||
|
@ -6492,8 +6492,8 @@ matrix-events-sdk@0.0.1:
|
|||
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==
|
||||
|
||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
||||
version "23.1.0"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/83563c7a01bbeaf7f83f4b7feccc03647b536e7c"
|
||||
version "23.1.1"
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/c309fe69426d701893ebee315105f8fa8fef03f8"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@matrix-org/matrix-sdk-crypto-js" "^0.1.0-alpha.2"
|
||||
|
|
Loading…
Reference in New Issue