Merge branch 'develop' into johannes/webpack-5
This commit is contained in:
commit
d6ea051e46
40 changed files with 1956 additions and 1238 deletions
|
@ -136,6 +136,9 @@ export class PosthogAnalytics {
|
|||
private authenticationType: Signup["authenticationType"] = "Other";
|
||||
private watchSettingRef?: string;
|
||||
|
||||
// Will be set when the matrixClient is passed to the analytics object (e.g. on login).
|
||||
private currentCryptoBackend?: "Rust" | "Legacy" = undefined;
|
||||
|
||||
public static get instance(): PosthogAnalytics {
|
||||
if (!this._instance) {
|
||||
this._instance = new PosthogAnalytics(posthog);
|
||||
|
@ -170,6 +173,7 @@ export class PosthogAnalytics {
|
|||
SettingsStore.monitorSetting("layout", null);
|
||||
SettingsStore.monitorSetting("useCompactLayout", null);
|
||||
this.onLayoutUpdated();
|
||||
this.updateCryptoSuperProperty();
|
||||
}
|
||||
|
||||
private onLayoutUpdated = (): void => {
|
||||
|
@ -278,6 +282,8 @@ export class PosthogAnalytics {
|
|||
this.registerSuperProperties(this.platformSuperProperties);
|
||||
}
|
||||
this.anonymity = anonymity;
|
||||
// update anyhow, no-op if not enabled or Disabled.
|
||||
this.updateCryptoSuperProperty();
|
||||
}
|
||||
|
||||
private static getRandomAnalyticsId(): string {
|
||||
|
@ -367,7 +373,28 @@ export class PosthogAnalytics {
|
|||
this.registerSuperProperties(this.platformSuperProperties);
|
||||
}
|
||||
|
||||
private updateCryptoSuperProperty(): void {
|
||||
if (!this.enabled || this.anonymity === Anonymity.Disabled) return;
|
||||
// Update super property for cryptoSDK in posthog.
|
||||
// This property will be subsequently passed in every event.
|
||||
if (this.currentCryptoBackend) {
|
||||
this.registerSuperProperties({ cryptoSDK: this.currentCryptoBackend });
|
||||
}
|
||||
}
|
||||
|
||||
public async updateAnonymityFromSettings(client: MatrixClient, pseudonymousOptIn: boolean): Promise<void> {
|
||||
// Temporary until we have migration code to switch crypto sdk.
|
||||
if (client.getCrypto()) {
|
||||
const cryptoVersion = client.getCrypto()!.getVersion();
|
||||
// version for rust is something like "Rust SDK 0.6.0 (9c6b550), Vodozemac 0.5.0"
|
||||
// for legacy it will be 'Olm x.x.x"
|
||||
if (cryptoVersion.includes("Rust SDK")) {
|
||||
this.currentCryptoBackend = "Rust";
|
||||
} else {
|
||||
this.currentCryptoBackend = "Legacy";
|
||||
}
|
||||
}
|
||||
|
||||
// Update this.anonymity based on the user's analytics opt-in settings
|
||||
const anonymity = pseudonymousOptIn ? Anonymity.Pseudonymous : Anonymity.Disabled;
|
||||
this.setAnonymity(anonymity);
|
||||
|
@ -379,7 +406,8 @@ export class PosthogAnalytics {
|
|||
}
|
||||
|
||||
if (anonymity !== Anonymity.Disabled) {
|
||||
await PosthogAnalytics.instance.updatePlatformSuperProperties();
|
||||
await this.updatePlatformSuperProperties();
|
||||
this.updateCryptoSuperProperty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ limitations under the License.
|
|||
|
||||
import React, { useContext } from "react";
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { IProps as IContextMenuProps } from "../../structures/ContextMenu";
|
||||
import IconizedContextMenu, {
|
||||
|
@ -30,7 +29,6 @@ import { ButtonEvent } from "../elements/AccessibleButton";
|
|||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import RoomListActions from "../../../actions/RoomListActions";
|
||||
import { EchoChamber } from "../../../stores/local-echo/EchoChamber";
|
||||
import { RoomNotifState } from "../../../RoomNotifs";
|
||||
import Modal from "../../../Modal";
|
||||
|
@ -52,6 +50,7 @@ import { SdkContextClass } from "../../../contexts/SDKContext";
|
|||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
import { DeveloperToolsOption } from "./DeveloperToolsOption";
|
||||
import { tagRoom } from "../../../utils/room/tagRoom";
|
||||
|
||||
interface IProps extends IContextMenuProps {
|
||||
room: Room;
|
||||
|
@ -333,15 +332,7 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
|
|||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (tagId === DefaultTagID.Favourite || tagId === DefaultTagID.LowPriority) {
|
||||
const inverseTag = tagId === DefaultTagID.Favourite ? DefaultTagID.LowPriority : DefaultTagID.Favourite;
|
||||
const isApplied = RoomListStore.instance.getTagsForRoom(room).includes(tagId);
|
||||
const removeTag = isApplied ? tagId : inverseTag;
|
||||
const addTag = isApplied ? null : tagId;
|
||||
dis.dispatch(RoomListActions.tagRoom(cli, room, removeTag, addTag, 0));
|
||||
} else {
|
||||
logger.warn(`Unexpected tag ${tagId} applied to ${room.roomId}`);
|
||||
}
|
||||
tagRoom(room, tagId);
|
||||
|
||||
const action = getKeyBindingsManager().getAccessibilityAction(ev as React.KeyboardEvent);
|
||||
switch (action) {
|
||||
|
|
|
@ -90,7 +90,7 @@ const BaseCard: React.FC<IProps> = forwardRef<HTMLDivElement, IProps>(
|
|||
<div className="mx_BaseCard_header">
|
||||
{backButton}
|
||||
{closeButton}
|
||||
{header}
|
||||
<div className="mx_BaseCard_headerProp">{header}</div>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
|
|
|
@ -16,25 +16,35 @@ limitations under the License.
|
|||
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||
import classNames from "classnames";
|
||||
import { EventType, JoinRule, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { Badge, Heading, Text, Tooltip } from "@vector-im/compound-web";
|
||||
import { MenuItem, Tooltip, Separator, ToggleMenuItem, Text, Badge, Heading } from "@vector-im/compound-web";
|
||||
import { Icon as SearchIcon } from "@vector-im/compound-design-tokens/icons/search.svg";
|
||||
import { Icon as FavouriteIcon } from "@vector-im/compound-design-tokens/icons/favourite-off.svg";
|
||||
import { Icon as UserAddIcon } from "@vector-im/compound-design-tokens/icons/user-add.svg";
|
||||
import { Icon as UserProfileSolidIcon } from "@vector-im/compound-design-tokens/icons/user-profile-solid.svg";
|
||||
import { Icon as LinkIcon } from "@vector-im/compound-design-tokens/icons/link.svg";
|
||||
import { Icon as SettingsIcon } from "@vector-im/compound-design-tokens/icons/settings.svg";
|
||||
import { Icon as ExportArchiveIcon } from "@vector-im/compound-design-tokens/icons/export-archive.svg";
|
||||
import { Icon as LeaveIcon } from "@vector-im/compound-design-tokens/icons/leave.svg";
|
||||
import { Icon as FilesIcon } from "@vector-im/compound-design-tokens/icons/files.svg";
|
||||
import { Icon as PollsIcon } from "@vector-im/compound-design-tokens/icons/polls.svg";
|
||||
import { Icon as PinIcon } from "@vector-im/compound-design-tokens/icons/pin-off.svg";
|
||||
import { Icon as LockIcon } from "@vector-im/compound-design-tokens/icons/lock.svg";
|
||||
import { Icon as LockOffIcon } from "@vector-im/compound-design-tokens/icons/lock-off.svg";
|
||||
import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg";
|
||||
import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg";
|
||||
import { EventType, JoinRule, Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { useIsEncrypted } from "../../../hooks/useIsEncrypted";
|
||||
import BaseCard, { Group } from "./BaseCard";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import RoomAvatar from "../avatars/RoomAvatar";
|
||||
import AccessibleButton, { ButtonEvent, IAccessibleButtonProps } from "../elements/AccessibleButton";
|
||||
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
|
||||
import Modal from "../../../Modal";
|
||||
import ShareDialog from "../dialogs/ShareDialog";
|
||||
import { useEventEmitter } from "../../../hooks/useEventEmitter";
|
||||
import { useEventEmitter, useEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
@ -47,7 +57,6 @@ import RoomContext from "../../../contexts/RoomContext";
|
|||
import { UIComponent, UIFeature } from "../../../settings/UIFeature";
|
||||
import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
||||
import { WidgetContextMenu } from "../context_menus/WidgetContextMenu";
|
||||
import { useRoomMemberCount } from "../../../hooks/useRoomMembers";
|
||||
import { useFeatureEnabled } from "../../../hooks/useSettings";
|
||||
import { usePinnedEvents } from "./PinnedMessagesCard";
|
||||
import { Container, MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
||||
|
@ -59,6 +68,11 @@ import PosthogTrackers from "../../../PosthogTrackers";
|
|||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
import { PollHistoryDialog } from "../dialogs/PollHistoryDialog";
|
||||
import { Flex } from "../../utils/Flex";
|
||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||
import { DefaultTagID } from "../../../stores/room-list/models";
|
||||
import { tagRoom } from "../../../utils/room/tagRoom";
|
||||
import { canInviteTo } from "../../../utils/room/canInviteTo";
|
||||
import { inviteToRoom } from "../../../utils/room/inviteToRoom";
|
||||
import { useAccountData } from "../../../hooks/useAccountData";
|
||||
import { useRoomState } from "../../../hooks/useRoomState";
|
||||
|
||||
|
@ -73,23 +87,6 @@ interface IAppsSectionProps {
|
|||
room: Room;
|
||||
}
|
||||
|
||||
interface IButtonProps extends IAccessibleButtonProps {
|
||||
className: string;
|
||||
onClick(ev: ButtonEvent): void;
|
||||
}
|
||||
|
||||
const Button: React.FC<IButtonProps> = ({ children, className, onClick, ...props }) => {
|
||||
return (
|
||||
<AccessibleButton
|
||||
{...props}
|
||||
className={classNames("mx_BaseCard_Button mx_RoomSummaryCard_Button", className)}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</AccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
export const useWidgets = (room: Room): IApp[] => {
|
||||
const [apps, setApps] = useState<IApp[]>(() => WidgetStore.instance.getApps(room.roomId));
|
||||
|
||||
|
@ -263,11 +260,6 @@ const AppsSection: React.FC<IAppsSectionProps> = ({ room }) => {
|
|||
);
|
||||
};
|
||||
|
||||
const onRoomMembersClick = (ev: ButtonEvent): void => {
|
||||
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.RoomMemberList }, true);
|
||||
PosthogTrackers.trackInteraction("WebRightPanelRoomInfoPeopleButton", ev);
|
||||
};
|
||||
|
||||
const onRoomFilesClick = (): void => {
|
||||
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.FilePanel }, true);
|
||||
};
|
||||
|
@ -304,6 +296,18 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, on
|
|||
});
|
||||
};
|
||||
|
||||
const onLeaveRoomClick = (): void => {
|
||||
defaultDispatcher.dispatch({
|
||||
action: "leave_room",
|
||||
room_id: room.roomId,
|
||||
});
|
||||
};
|
||||
|
||||
const onRoomMembersClick = (ev: ButtonEvent): void => {
|
||||
RightPanelStore.instance.pushCard({ phase: RightPanelPhases.RoomMemberList }, true);
|
||||
PosthogTrackers.trackInteraction("WebRightPanelRoomInfoPeopleButton", ev);
|
||||
};
|
||||
|
||||
const isRoomEncrypted = useIsEncrypted(cli, room);
|
||||
const roomContext = useContext(RoomContext);
|
||||
const e2eStatus = roomContext.e2eStatus;
|
||||
|
@ -383,10 +387,14 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, on
|
|||
</header>
|
||||
);
|
||||
|
||||
const memberCount = useRoomMemberCount(room);
|
||||
const pinningEnabled = useFeatureEnabled("feature_pinning");
|
||||
const pinCount = usePinnedEvents(pinningEnabled ? room : undefined)?.length;
|
||||
|
||||
const roomTags = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () =>
|
||||
RoomListStore.instance.getTagsForRoom(room),
|
||||
);
|
||||
const isFavorite = roomTags.includes(DefaultTagID.Favourite);
|
||||
|
||||
return (
|
||||
<BaseCard header={null} className="mx_RoomSummaryCard" onClose={onClose}>
|
||||
<Flex
|
||||
|
@ -417,43 +425,58 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose, on
|
|||
</Flex>
|
||||
|
||||
{header}
|
||||
<Group title={_t("common|about")} className="mx_RoomSummaryCard_aboutGroup">
|
||||
<Button className="mx_RoomSummaryCard_icon_people" onClick={onRoomMembersClick}>
|
||||
{_t("common|people")}
|
||||
<span className="mx_BaseCard_Button_sublabel">{memberCount}</span>
|
||||
</Button>
|
||||
{!isVideoRoom && (
|
||||
<Button className="mx_RoomSummaryCard_icon_files" onClick={onRoomFilesClick}>
|
||||
{_t("right_panel|files_button")}
|
||||
</Button>
|
||||
)}
|
||||
{!isVideoRoom && (
|
||||
<Button className="mx_RoomSummaryCard_icon_poll" onClick={onRoomPollHistoryClick}>
|
||||
{_t("right_panel|polls_button")}
|
||||
</Button>
|
||||
)}
|
||||
{pinningEnabled && !isVideoRoom && (
|
||||
<Button className="mx_RoomSummaryCard_icon_pins" onClick={onRoomPinsClick}>
|
||||
{_t("right_panel|pinned_messages_button")}
|
||||
{pinCount > 0 && <span className="mx_BaseCard_Button_sublabel">{pinCount}</span>}
|
||||
</Button>
|
||||
)}
|
||||
{!isVideoRoom && (
|
||||
<Button className="mx_RoomSummaryCard_icon_export" onClick={onRoomExportClick}>
|
||||
{_t("right_panel|export_chat_button")}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
data-testid="shareRoomButton"
|
||||
className="mx_RoomSummaryCard_icon_share"
|
||||
onClick={onShareRoomClick}
|
||||
>
|
||||
{_t("right_panel|share_button")}
|
||||
</Button>
|
||||
<Button className="mx_RoomSummaryCard_icon_settings" onClick={onRoomSettingsClick}>
|
||||
{_t("right_panel|settings_button")}
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<Separator />
|
||||
|
||||
<ToggleMenuItem
|
||||
Icon={FavouriteIcon}
|
||||
label={_t("room|context_menu|favourite")}
|
||||
checked={isFavorite}
|
||||
onChange={() => tagRoom(room, DefaultTagID.Favourite)}
|
||||
/>
|
||||
<MenuItem
|
||||
Icon={UserAddIcon}
|
||||
label={_t("action|invite")}
|
||||
disabled={!canInviteTo(room)}
|
||||
onClick={() => inviteToRoom(room)}
|
||||
/>
|
||||
<MenuItem Icon={LinkIcon} label={_t("action|copy_link")} onClick={onShareRoomClick} />
|
||||
<MenuItem Icon={SettingsIcon} label={_t("common|settings")} onClick={onRoomSettingsClick} />
|
||||
|
||||
<Separator />
|
||||
<MenuItem
|
||||
// this icon matches the legacy implementation
|
||||
// and is a short term solution until legacy room header is removed
|
||||
Icon={UserProfileSolidIcon}
|
||||
label={_t("common|people")}
|
||||
onClick={onRoomMembersClick}
|
||||
/>
|
||||
{!isVideoRoom && (
|
||||
<>
|
||||
<MenuItem Icon={FilesIcon} label={_t("right_panel|files_button")} onClick={onRoomFilesClick} />
|
||||
<MenuItem
|
||||
Icon={PollsIcon}
|
||||
label={_t("right_panel|polls_button")}
|
||||
onClick={onRoomPollHistoryClick}
|
||||
/>
|
||||
{pinningEnabled && (
|
||||
<MenuItem
|
||||
Icon={PinIcon}
|
||||
label={_t("right_panel|pinned_messages_button")}
|
||||
onClick={onRoomPinsClick}
|
||||
>
|
||||
<Text as="span" size="sm">
|
||||
{pinCount}
|
||||
</Text>
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem Icon={ExportArchiveIcon} label={_t("export_chat|title")} onClick={onRoomExportClick} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Separator />
|
||||
|
||||
<MenuItem Icon={LeaveIcon} kind="critical" label={_t("action|leave_room")} onClick={onLeaveRoomClick} />
|
||||
|
||||
{SettingsStore.getValue(UIFeature.Widgets) &&
|
||||
!isVideoRoom &&
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { Body as BodyText, IconButton, Tooltip } from "@vector-im/compound-web";
|
||||
import { Icon as VideoCallIcon } from "@vector-im/compound-design-tokens/icons/video-call.svg";
|
||||
import { Icon as VideoCallIcon } from "@vector-im/compound-design-tokens/icons/video-call-solid.svg";
|
||||
import { Icon as VoiceCallIcon } from "@vector-im/compound-design-tokens/icons/voice-call.svg";
|
||||
import { Icon as ThreadsIcon } from "@vector-im/compound-design-tokens/icons/threads-solid.svg";
|
||||
import { Icon as NotificationsIcon } from "@vector-im/compound-design-tokens/icons/notifications-solid.svg";
|
||||
|
@ -49,6 +49,7 @@ import RoomAvatar from "../avatars/RoomAvatar";
|
|||
import { formatCount } from "../../../utils/FormattingUtils";
|
||||
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
|
||||
import { Linkify, topicToHtml } from "../../../HtmlUtils";
|
||||
import PosthogTrackers from "../../../PosthogTrackers";
|
||||
|
||||
/**
|
||||
* A helper to transform a notification color to the what the Compound Icon Button
|
||||
|
@ -193,6 +194,15 @@ export default function RoomHeader({
|
|||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
<Tooltip label={!videoCallDisabledReason ? _t("voip|video_call") : videoCallDisabledReason!}>
|
||||
<IconButton
|
||||
disabled={!!videoCallDisabledReason}
|
||||
aria-label={!videoCallDisabledReason ? _t("voip|video_call") : videoCallDisabledReason!}
|
||||
onClick={videoCallClick}
|
||||
>
|
||||
<VideoCallIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{!useElementCallExclusively && (
|
||||
<Tooltip label={!voiceCallDisabledReason ? _t("voip|voice_call") : voiceCallDisabledReason!}>
|
||||
<IconButton
|
||||
|
@ -204,21 +214,14 @@ export default function RoomHeader({
|
|||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label={!videoCallDisabledReason ? _t("voip|video_call") : videoCallDisabledReason!}>
|
||||
<IconButton
|
||||
disabled={!!videoCallDisabledReason}
|
||||
aria-label={!videoCallDisabledReason ? _t("voip|video_call") : videoCallDisabledReason!}
|
||||
onClick={videoCallClick}
|
||||
>
|
||||
<VideoCallIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label={_t("common|threads")}>
|
||||
<IconButton
|
||||
indicator={notificationColorToIndicator(threadNotifications)}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
RightPanelStore.instance.showOrHidePanel(RightPanelPhases.ThreadPanel);
|
||||
PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", evt);
|
||||
}}
|
||||
aria-label={_t("common|threads")}
|
||||
>
|
||||
|
|
|
@ -418,7 +418,6 @@
|
|||
"spaceinvaders_message": "sends space invaders"
|
||||
},
|
||||
"common": {
|
||||
"about": "About",
|
||||
"access_token": "Access Token",
|
||||
"accessibility": "Accessibility",
|
||||
"advanced": "Advanced",
|
||||
|
@ -1854,8 +1853,6 @@
|
|||
"room_summary_card": {
|
||||
"title": "Room info"
|
||||
},
|
||||
"settings_button": "Room settings",
|
||||
"share_button": "Share room",
|
||||
"thread_list": {
|
||||
"context_menu_label": "Thread options"
|
||||
},
|
||||
|
|
|
@ -623,6 +623,7 @@ export class ElementCall extends Call {
|
|||
public static readonly MEMBER_EVENT_TYPE = new NamespacedValue(null, EventType.GroupCallMemberPrefix);
|
||||
public readonly STUCK_DEVICE_TIMEOUT_MS = 1000 * 60 * 60; // 1 hour
|
||||
|
||||
private settingsStoreCallEncryptionWatcher: string | null = null;
|
||||
private terminationTimer: number | null = null;
|
||||
private _layout = Layout.Tile;
|
||||
public get layout(): Layout {
|
||||
|
@ -633,11 +634,7 @@ export class ElementCall extends Call {
|
|||
this.emit(CallEvent.Layout, value);
|
||||
}
|
||||
|
||||
private static createOrGetCallWidget(roomId: string, client: MatrixClient): IApp {
|
||||
const ecWidget = WidgetStore.instance.getApps(roomId).find((app) => WidgetType.CALL.matches(app.type));
|
||||
if (ecWidget) {
|
||||
return ecWidget;
|
||||
}
|
||||
private static generateWidgetUrl(client: MatrixClient, roomId: string): URL {
|
||||
const accountAnalyticsData = client.getAccountData(PosthogAnalytics.ANALYTICS_EVENT_TYPE);
|
||||
// The analyticsID is passed directly to element call (EC) since this codepath is only for EC and no other widget.
|
||||
// We really don't want the same analyticID's for the EC and EW posthog instances (Data on posthog should be limited/anonymized as much as possible).
|
||||
|
@ -683,6 +680,20 @@ export class ElementCall extends Call {
|
|||
const url = new URL(SdkConfig.get("element_call").url ?? DEFAULTS.element_call.url!);
|
||||
url.pathname = "/room";
|
||||
url.hash = `#?${params.toString()}`;
|
||||
return url;
|
||||
}
|
||||
|
||||
private static createOrGetCallWidget(roomId: string, client: MatrixClient): IApp {
|
||||
const ecWidget = WidgetStore.instance.getApps(roomId).find((app) => WidgetType.CALL.matches(app.type));
|
||||
const url = ElementCall.generateWidgetUrl(client, roomId);
|
||||
|
||||
if (ecWidget) {
|
||||
// always update the url because even if the widget is already created
|
||||
// we might have settings changes that update the widget.
|
||||
ecWidget.url = url.toString();
|
||||
|
||||
return ecWidget;
|
||||
}
|
||||
|
||||
// To use Element Call without touching room state, we create a virtual
|
||||
// widget (one that doesn't have a corresponding state event)
|
||||
|
@ -698,12 +709,21 @@ export class ElementCall extends Call {
|
|||
roomId,
|
||||
);
|
||||
}
|
||||
|
||||
private onCallEncryptionSettingsChange(): void {
|
||||
this.widget.url = ElementCall.generateWidgetUrl(this.client, this.roomId).toString();
|
||||
}
|
||||
|
||||
private constructor(public session: MatrixRTCSession, widget: IApp, client: MatrixClient) {
|
||||
super(widget, client);
|
||||
|
||||
this.session.on(MatrixRTCSessionEvent.MembershipsChanged, this.onMembershipChanged);
|
||||
this.client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionEnded, this.onRTCSessionEnded);
|
||||
|
||||
SettingsStore.watchSetting(
|
||||
"feature_disable_call_per_sender_encryption",
|
||||
null,
|
||||
this.onCallEncryptionSettingsChange.bind(this),
|
||||
);
|
||||
this.updateParticipants();
|
||||
}
|
||||
|
||||
|
@ -784,6 +804,9 @@ export class ElementCall extends Call {
|
|||
this.session.off(MatrixRTCSessionEvent.MembershipsChanged, this.onMembershipChanged);
|
||||
this.client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionEnded, this.onRTCSessionEnded);
|
||||
|
||||
if (this.settingsStoreCallEncryptionWatcher) {
|
||||
SettingsStore.unwatchSetting(this.settingsStoreCallEncryptionWatcher);
|
||||
}
|
||||
if (this.terminationTimer !== null) {
|
||||
clearTimeout(this.terminationTimer);
|
||||
this.terminationTimer = null;
|
||||
|
|
33
src/utils/room/canInviteTo.ts
Normal file
33
src/utils/room/canInviteTo.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright 2023 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 { JoinRule, Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { shouldShowComponent } from "../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../settings/UIFeature";
|
||||
|
||||
/**
|
||||
* Can a user invite new members to the room
|
||||
* @param room
|
||||
* @returns whether the user can invite new members to the room
|
||||
*/
|
||||
export function canInviteTo(room: Room): boolean {
|
||||
const client = room.client;
|
||||
const canInvite =
|
||||
!!room.canInvite(client.getSafeUserId()) || !!(room.isSpaceRoom() && room.getJoinRule() === JoinRule.Public);
|
||||
|
||||
return canInvite && room.getMyMembership() === "join" && shouldShowComponent(UIComponent.InviteUsers);
|
||||
}
|
36
src/utils/room/inviteToRoom.ts
Normal file
36
src/utils/room/inviteToRoom.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2023 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 { Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
|
||||
/**
|
||||
* Invite to a room and prompts guests to registers
|
||||
* @param room
|
||||
*/
|
||||
export function inviteToRoom(room: Room): void {
|
||||
if (room.client.isGuest()) {
|
||||
dis.dispatch({ action: "require_registration" });
|
||||
return;
|
||||
}
|
||||
|
||||
// open the room inviter
|
||||
dis.dispatch({
|
||||
action: "view_invite",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
}
|
40
src/utils/room/tagRoom.ts
Normal file
40
src/utils/room/tagRoom.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2023 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 { Room } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import RoomListStore from "../../stores/room-list/RoomListStore";
|
||||
import { DefaultTagID, TagID } from "../../stores/room-list/models";
|
||||
import RoomListActions from "../../actions/RoomListActions";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
|
||||
/**
|
||||
* Toggle tag for a given room
|
||||
* @param room The room to tag
|
||||
* @param tagId The tag to invert
|
||||
*/
|
||||
export function tagRoom(room: Room, tagId: TagID): void {
|
||||
if (tagId === DefaultTagID.Favourite || tagId === DefaultTagID.LowPriority) {
|
||||
const inverseTag = tagId === DefaultTagID.Favourite ? DefaultTagID.LowPriority : DefaultTagID.Favourite;
|
||||
const isApplied = RoomListStore.instance.getTagsForRoom(room).includes(tagId);
|
||||
const removeTag = isApplied ? tagId : inverseTag;
|
||||
const addTag = isApplied ? null : tagId;
|
||||
dis.dispatch(RoomListActions.tagRoom(room.client, room, removeTag, addTag, 0));
|
||||
} else {
|
||||
logger.warn(`Unexpected tag ${tagId} applied to ${room.roomId}`);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue