Merge branch 'develop' into germain-gg/fix-right-panel-member
This commit is contained in:
commit
159deec937
156 changed files with 17312 additions and 14272 deletions
|
@ -1003,7 +1003,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
|
||||
let avatar: JSX.Element | null = null;
|
||||
let sender: JSX.Element | null = null;
|
||||
let avatarSize: string;
|
||||
let avatarSize: string | null;
|
||||
let needsSenderProfile: boolean;
|
||||
|
||||
if (isRenderingNotification) {
|
||||
|
@ -1021,7 +1021,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
avatarSize = "32px";
|
||||
needsSenderProfile = true;
|
||||
} else if (eventType === EventType.RoomCreate || isBubbleMessage) {
|
||||
avatarSize = "0";
|
||||
avatarSize = null;
|
||||
needsSenderProfile = false;
|
||||
} else if (this.props.layout == Layout.IRC) {
|
||||
avatarSize = "14px";
|
||||
|
@ -1032,14 +1032,14 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
ElementCall.CALL_EVENT_TYPE.matches(eventType)
|
||||
) {
|
||||
// no avatar or sender profile for continuation messages and call tiles
|
||||
avatarSize = "0";
|
||||
avatarSize = null;
|
||||
needsSenderProfile = false;
|
||||
} else {
|
||||
avatarSize = "30px";
|
||||
needsSenderProfile = true;
|
||||
}
|
||||
|
||||
if (this.props.mxEvent.sender && avatarSize) {
|
||||
if (this.props.mxEvent.sender && avatarSize !== null) {
|
||||
let member: RoomMember | null = null;
|
||||
// set member to receiver (target) if it is a 3PID invite
|
||||
// so that the correct avatar is shown as the text is
|
||||
|
|
|
@ -112,8 +112,8 @@ const VoiceCallButton: FC<VoiceCallButtonProps> = ({ room, busy, setBusy, behavi
|
|||
<AccessibleTooltipButton
|
||||
className="mx_LegacyRoomHeader_button mx_LegacyRoomHeader_voiceCallButton"
|
||||
onClick={onClick}
|
||||
title={_t("Voice call")}
|
||||
tooltip={tooltip ?? _t("Voice call")}
|
||||
title={_t("voip|voice_call")}
|
||||
tooltip={tooltip ?? _t("voip|voice_call")}
|
||||
alignment={Alignment.Bottom}
|
||||
disabled={disabled || busy}
|
||||
/>
|
||||
|
@ -228,8 +228,8 @@ const VideoCallButton: FC<VideoCallButtonProps> = ({ room, busy, setBusy, behavi
|
|||
inputRef={buttonRef}
|
||||
className="mx_LegacyRoomHeader_button mx_LegacyRoomHeader_videoCallButton"
|
||||
onClick={onClick}
|
||||
title={_t("Video call")}
|
||||
tooltip={tooltip ?? _t("Video call")}
|
||||
title={_t("voip|video_call")}
|
||||
tooltip={tooltip ?? _t("voip|video_call")}
|
||||
alignment={Alignment.Bottom}
|
||||
disabled={disabled || busy}
|
||||
/>
|
||||
|
|
|
@ -78,7 +78,7 @@ function SendButton(props: ISendButtonProps): JSX.Element {
|
|||
<AccessibleTooltipButton
|
||||
className="mx_MessageComposer_sendMessage"
|
||||
onClick={props.onClick}
|
||||
title={props.title ?? _t("Send message")}
|
||||
title={props.title ?? _t("composer|send_button_title")}
|
||||
data-testid="sendmessagebtn"
|
||||
/>
|
||||
);
|
||||
|
@ -303,19 +303,19 @@ export class MessageComposer extends React.Component<IProps, IState> {
|
|||
if (this.props.replyToEvent) {
|
||||
const replyingToThread = this.props.relation?.rel_type === THREAD_RELATION_TYPE.name;
|
||||
if (replyingToThread && this.props.e2eStatus) {
|
||||
return _t("Reply to encrypted thread…");
|
||||
return _t("composer|placeholder_thread_encrypted");
|
||||
} else if (replyingToThread) {
|
||||
return _t("Reply to thread…");
|
||||
return _t("composer|placeholder_thread");
|
||||
} else if (this.props.e2eStatus) {
|
||||
return _t("Send an encrypted reply…");
|
||||
return _t("composer|placeholder_reply_encrypted");
|
||||
} else {
|
||||
return _t("Send a reply…");
|
||||
return _t("composer|placeholder_reply");
|
||||
}
|
||||
} else {
|
||||
if (this.props.e2eStatus) {
|
||||
return _t("Send an encrypted message…");
|
||||
return _t("composer|placeholder_encrypted");
|
||||
} else {
|
||||
return _t("Send a message…");
|
||||
return _t("composer|placeholder");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@ import React from "react";
|
|||
import { UnstableValue } from "matrix-js-sdk/src/NamespacedValue";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { formatDuration } from "../../../DateUtils";
|
||||
|
||||
const BUSY_PRESENCE_NAME = new UnstableValue("busy", "org.matrix.msc3026.busy");
|
||||
|
||||
|
@ -37,47 +38,23 @@ export default class PresenceLabel extends React.Component<IProps> {
|
|||
activeAgo: -1,
|
||||
};
|
||||
|
||||
// Return duration as a string using appropriate time units
|
||||
// XXX: This would be better handled using a culture-aware library, but we don't use one yet.
|
||||
private getDuration(time: number): string | undefined {
|
||||
if (!time) return;
|
||||
const t = Math.round(time / 1000);
|
||||
const s = t % 60;
|
||||
const m = Math.round(t / 60) % 60;
|
||||
const h = Math.round(t / (60 * 60)) % 24;
|
||||
const d = Math.round(t / (60 * 60 * 24));
|
||||
if (t < 60) {
|
||||
if (t < 0) {
|
||||
return _t("%(duration)ss", { duration: 0 });
|
||||
}
|
||||
return _t("%(duration)ss", { duration: s });
|
||||
}
|
||||
if (t < 60 * 60) {
|
||||
return _t("%(duration)sm", { duration: m });
|
||||
}
|
||||
if (t < 24 * 60 * 60) {
|
||||
return _t("%(duration)sh", { duration: h });
|
||||
}
|
||||
return _t("%(duration)sd", { duration: d });
|
||||
}
|
||||
|
||||
private getPrettyPresence(presence?: string, activeAgo?: number, currentlyActive?: boolean): string {
|
||||
// for busy presence, we ignore the 'currentlyActive' flag: they're busy whether
|
||||
// they're active or not. It can be set while the user is active in which case
|
||||
// the 'active ago' ends up being 0.
|
||||
if (presence && BUSY_PRESENCE_NAME.matches(presence)) return _t("Busy");
|
||||
if (presence && BUSY_PRESENCE_NAME.matches(presence)) return _t("presence|busy");
|
||||
|
||||
if (!currentlyActive && activeAgo !== undefined && activeAgo > 0) {
|
||||
const duration = this.getDuration(activeAgo);
|
||||
if (presence === "online") return _t("Online for %(duration)s", { duration: duration });
|
||||
if (presence === "unavailable") return _t("Idle for %(duration)s", { duration: duration }); // XXX: is this actually right?
|
||||
if (presence === "offline") return _t("Offline for %(duration)s", { duration: duration });
|
||||
return _t("Unknown for %(duration)s", { duration: duration });
|
||||
const duration = formatDuration(activeAgo);
|
||||
if (presence === "online") return _t("presence|online_for", { duration: duration });
|
||||
if (presence === "unavailable") return _t("presence|idle_for", { duration: duration }); // XXX: is this actually right?
|
||||
if (presence === "offline") return _t("presence|offline_for", { duration: duration });
|
||||
return _t("presence|unknown_for", { duration: duration });
|
||||
} else {
|
||||
if (presence === "online") return _t("Online");
|
||||
if (presence === "unavailable") return _t("Idle"); // XXX: is this actually right?
|
||||
if (presence === "offline") return _t("common|offline");
|
||||
return _t("Unknown");
|
||||
if (presence === "online") return _t("presence|online");
|
||||
if (presence === "unavailable") return _t("presence|idle"); // XXX: is this actually right?
|
||||
if (presence === "offline") return _t("presence|offline");
|
||||
return _t("presence|unknown");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -165,43 +165,55 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
</Box>
|
||||
<Flex as="nav" align="center" gap="var(--cpd-space-2x)">
|
||||
{!useElementCallExclusively && (
|
||||
<Tooltip label={!voiceCallDisabledReason ? _t("voip|voice_call") : voiceCallDisabledReason!}>
|
||||
<IconButton
|
||||
disabled={!!voiceCallDisabledReason}
|
||||
title={!voiceCallDisabledReason ? _t("voip|voice_call") : voiceCallDisabledReason!}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
placeCall(room, CallType.Voice, voiceCallType);
|
||||
}}
|
||||
>
|
||||
<VoiceCallIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label={!videoCallDisabledReason ? _t("voip|video_call") : videoCallDisabledReason!}>
|
||||
<IconButton
|
||||
disabled={!!voiceCallDisabledReason}
|
||||
title={!voiceCallDisabledReason ? _t("Voice call") : voiceCallDisabledReason!}
|
||||
onClick={() => {
|
||||
placeCall(room, CallType.Voice, voiceCallType);
|
||||
disabled={!!videoCallDisabledReason}
|
||||
title={!videoCallDisabledReason ? _t("voip|video_call") : videoCallDisabledReason!}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
placeCall(room, CallType.Video, videoCallType);
|
||||
}}
|
||||
>
|
||||
<VoiceCallIcon />
|
||||
<VideoCallIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
<IconButton
|
||||
disabled={!!videoCallDisabledReason}
|
||||
title={!videoCallDisabledReason ? _t("Video call") : videoCallDisabledReason!}
|
||||
onClick={() => {
|
||||
placeCall(room, CallType.Video, videoCallType);
|
||||
}}
|
||||
>
|
||||
<VideoCallIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
indicator={notificationColorToIndicator(threadNotifications)}
|
||||
onClick={() => {
|
||||
setPhase(RightPanelPhases.ThreadPanel);
|
||||
}}
|
||||
title={_t("common|threads")}
|
||||
>
|
||||
<ThreadsIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
indicator={notificationColorToIndicator(globalNotificationState.color)}
|
||||
onClick={() => {
|
||||
setPhase(RightPanelPhases.NotificationPanel);
|
||||
}}
|
||||
title={_t("Notifications")}
|
||||
>
|
||||
<NotificationsIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label={_t("common|threads")}>
|
||||
<IconButton
|
||||
indicator={notificationColorToIndicator(threadNotifications)}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
setPhase(RightPanelPhases.ThreadPanel);
|
||||
}}
|
||||
title={_t("common|threads")}
|
||||
>
|
||||
<ThreadsIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label={_t("Notifications")}>
|
||||
<IconButton
|
||||
indicator={notificationColorToIndicator(globalNotificationState.color)}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
setPhase(RightPanelPhases.NotificationPanel);
|
||||
}}
|
||||
title={_t("Notifications")}
|
||||
>
|
||||
<NotificationsIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
{!isDirectMessage && (
|
||||
<BodyText
|
||||
|
@ -219,6 +231,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
|||
members={members.slice(0, 3)}
|
||||
size="20px"
|
||||
overflow={false}
|
||||
viewUserOnClick={false}
|
||||
>
|
||||
{formatCount(memberCount)}
|
||||
</FacePile>
|
||||
|
|
|
@ -33,7 +33,7 @@ export const RoomKnocksBar: VFC<{ room: Room }> = ({ room }) => {
|
|||
const [disabled, setDisabled] = useState(false);
|
||||
const knockMembers = useTypedEventEmitterState(
|
||||
room,
|
||||
RoomStateEvent.Members,
|
||||
RoomStateEvent.Update,
|
||||
useCallback(() => room.getMembersWithMembership("knock"), [room]),
|
||||
);
|
||||
const knockMembersCount = knockMembers.length;
|
||||
|
|
|
@ -419,7 +419,7 @@ const TAG_AESTHETICS: TagAestheticsMap = {
|
|||
defaultHidden: false,
|
||||
},
|
||||
[DefaultTagID.ServerNotice]: {
|
||||
sectionLabel: _td("System Alerts"),
|
||||
sectionLabel: _td("common|system_alerts"),
|
||||
isInvite: false,
|
||||
defaultHidden: false,
|
||||
},
|
||||
|
|
|
@ -261,7 +261,7 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
|
|||
// Load stickerpack content
|
||||
if (!!stickerpickerWidget?.content?.url) {
|
||||
// Set default name
|
||||
stickerpickerWidget.content.name = stickerpickerWidget.content.name || _t("Stickerpack");
|
||||
stickerpickerWidget.content.name = stickerpickerWidget.content.name || _t("common|stickerpack");
|
||||
|
||||
// FIXME: could this use the same code as other apps?
|
||||
const stickerApp: IWidget = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue