Remove Piwik support (#8835)
* Remove all mentions of Piwik * Kill off all consumer of the old Piwik Analytics module * Simplify ModalManager interface * i18n * Attempt to fix old e2e tests * Remove unused component * Iterate PR
This commit is contained in:
parent
7d14d15ba6
commit
3c5c2bef6d
142 changed files with 446 additions and 1412 deletions
|
@ -89,7 +89,6 @@
|
|||
@import "./views/context_menus/_IconizedContextMenu.scss";
|
||||
@import "./views/context_menus/_MessageContextMenu.scss";
|
||||
@import "./views/dialogs/_AddExistingToSpaceDialog.scss";
|
||||
@import "./views/dialogs/_Analytics.scss";
|
||||
@import "./views/dialogs/_AnalyticsLearnMoreDialog.scss";
|
||||
@import "./views/dialogs/_BugReportDialog.scss";
|
||||
@import "./views/dialogs/_BulkRedactDialog.scss";
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_AnalyticsModal table {
|
||||
margin: 10px 0px;
|
||||
|
||||
.mx_AnalyticsModal_label {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
2
src/@types/global.d.ts
vendored
2
src/@types/global.d.ts
vendored
|
@ -34,7 +34,6 @@ import type { Renderer } from "react-dom";
|
|||
import RightPanelStore from "../stores/right-panel/RightPanelStore";
|
||||
import WidgetStore from "../stores/WidgetStore";
|
||||
import CallHandler from "../CallHandler";
|
||||
import { Analytics } from "../Analytics";
|
||||
import UserActivity from "../UserActivity";
|
||||
import { ModalWidgetStore } from "../stores/ModalWidgetStore";
|
||||
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
|
||||
|
@ -91,7 +90,6 @@ declare global {
|
|||
mxWidgetStore: WidgetStore;
|
||||
mxWidgetLayoutStore: WidgetLayoutStore;
|
||||
mxCallHandler: CallHandler;
|
||||
mxAnalytics: Analytics;
|
||||
mxUserActivity: UserActivity;
|
||||
mxModalWidgetStore: ModalWidgetStore;
|
||||
mxVoipUserMapper: VoipUserMapper;
|
||||
|
|
|
@ -206,7 +206,7 @@ export default class AddThreepid {
|
|||
continueKind: "primary",
|
||||
},
|
||||
};
|
||||
const { finished } = Modal.createTrackedDialog('Add Email', '', InteractiveAuthDialog, {
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Add Email Address"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
authData: e.data,
|
||||
|
@ -319,7 +319,7 @@ export default class AddThreepid {
|
|||
continueKind: "primary",
|
||||
},
|
||||
};
|
||||
const { finished } = Modal.createTrackedDialog('Add MSISDN', '', InteractiveAuthDialog, {
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Add Phone Number"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
authData: e.data,
|
||||
|
|
|
@ -1,460 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
||||
Copyright 2020 - 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 React from 'react';
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { Optional } from "matrix-events-sdk";
|
||||
import { randomString } from 'matrix-js-sdk/src/randomstring';
|
||||
|
||||
import { getCurrentLanguage, _t, _td, IVariables } from './languageHandler';
|
||||
import PlatformPeg from './PlatformPeg';
|
||||
import SdkConfig from './SdkConfig';
|
||||
import Modal from './Modal';
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
import { SnakedObject } from "./utils/SnakedObject";
|
||||
import { IConfigOptions } from "./IConfigOptions";
|
||||
|
||||
// Note: we keep the analytics redaction on groups in case people have old links.
|
||||
const hashRegex = /#\/(groups?|room|user|settings|register|login|forgot_password|home|directory)/;
|
||||
const hashVarRegex = /#\/(group|room|user)\/.*$/;
|
||||
|
||||
// Remove all but the first item in the hash path. Redact unexpected hashes.
|
||||
function getRedactedHash(hash: string): string {
|
||||
// Don't leak URLs we aren't expecting - they could contain tokens/PII
|
||||
const match = hashRegex.exec(hash);
|
||||
if (!match) {
|
||||
logger.warn(`Unexpected hash location "${hash}"`);
|
||||
return '#/<unexpected hash location>';
|
||||
}
|
||||
|
||||
if (hashVarRegex.test(hash)) {
|
||||
return hash.replace(hashVarRegex, "#/$1/<redacted>");
|
||||
}
|
||||
|
||||
return hash.replace(hashRegex, "#/$1");
|
||||
}
|
||||
|
||||
// Return the current origin, path and hash separated with a `/`. This does
|
||||
// not include query parameters.
|
||||
function getRedactedUrl(): string {
|
||||
const { origin, hash } = window.location;
|
||||
let { pathname } = window.location;
|
||||
|
||||
// Redact paths which could contain unexpected PII
|
||||
if (origin.startsWith('file://')) {
|
||||
pathname = "/<redacted>/";
|
||||
}
|
||||
|
||||
return origin + pathname + getRedactedHash(hash);
|
||||
}
|
||||
|
||||
interface IData {
|
||||
/* eslint-disable camelcase */
|
||||
gt_ms?: string;
|
||||
e_c?: string;
|
||||
e_a?: string;
|
||||
e_n?: string;
|
||||
e_v?: string;
|
||||
ping?: string;
|
||||
/* eslint-enable camelcase */
|
||||
}
|
||||
|
||||
interface IVariable {
|
||||
id: number;
|
||||
expl: string; // explanation
|
||||
example: string; // example value
|
||||
getTextVariables?(): IVariables; // object to pass as 2nd argument to `_t`
|
||||
}
|
||||
|
||||
const customVariables: Record<string, IVariable> = {
|
||||
// The Matomo installation at https://matomo.riot.im is currently configured
|
||||
// with a limit of 10 custom variables.
|
||||
'App Platform': {
|
||||
id: 1,
|
||||
expl: _td('The platform you\'re on'),
|
||||
example: 'Electron Platform',
|
||||
},
|
||||
'App Version': {
|
||||
id: 2,
|
||||
expl: _td('The version of %(brand)s'),
|
||||
getTextVariables: () => ({
|
||||
brand: SdkConfig.get().brand,
|
||||
}),
|
||||
example: '15.0.0',
|
||||
},
|
||||
'User Type': {
|
||||
id: 3,
|
||||
expl: _td('Whether or not you\'re logged in (we don\'t record your username)'),
|
||||
example: 'Logged In',
|
||||
},
|
||||
'Chosen Language': {
|
||||
id: 4,
|
||||
expl: _td('Your language of choice'),
|
||||
example: 'en',
|
||||
},
|
||||
'Instance': {
|
||||
id: 5,
|
||||
expl: _td('Which officially provided instance you are using, if any'),
|
||||
example: 'app',
|
||||
},
|
||||
'RTE: Uses Richtext Mode': {
|
||||
id: 6,
|
||||
expl: _td('Whether or not you\'re using the Richtext mode of the Rich Text Editor'),
|
||||
example: 'off',
|
||||
},
|
||||
'Homeserver URL': {
|
||||
id: 7,
|
||||
expl: _td('Your homeserver\'s URL'),
|
||||
example: 'https://matrix.org',
|
||||
},
|
||||
'Touch Input': {
|
||||
id: 8,
|
||||
expl: _td("Whether you're using %(brand)s on a device where touch is the primary input mechanism"),
|
||||
getTextVariables: () => ({
|
||||
brand: SdkConfig.get().brand,
|
||||
}),
|
||||
example: 'false',
|
||||
},
|
||||
'Breadcrumbs': {
|
||||
id: 9,
|
||||
expl: _td("Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)"),
|
||||
example: 'disabled',
|
||||
},
|
||||
'Installed PWA': {
|
||||
id: 10,
|
||||
expl: _td("Whether you're using %(brand)s as an installed Progressive Web App"),
|
||||
getTextVariables: () => ({
|
||||
brand: SdkConfig.get().brand,
|
||||
}),
|
||||
example: 'false',
|
||||
},
|
||||
};
|
||||
|
||||
function whitelistRedact(whitelist: string[], str: string): string {
|
||||
if (whitelist.includes(str)) return str;
|
||||
return '<redacted>';
|
||||
}
|
||||
|
||||
const UID_KEY = "mx_Riot_Analytics_uid";
|
||||
const CREATION_TS_KEY = "mx_Riot_Analytics_cts";
|
||||
const VISIT_COUNT_KEY = "mx_Riot_Analytics_vc";
|
||||
const LAST_VISIT_TS_KEY = "mx_Riot_Analytics_lvts";
|
||||
|
||||
function getUid(): string {
|
||||
try {
|
||||
let data = localStorage?.getItem(UID_KEY);
|
||||
if (!data && localStorage) {
|
||||
localStorage.setItem(UID_KEY, data = randomString(16));
|
||||
}
|
||||
return data;
|
||||
} catch (e) {
|
||||
logger.error("Analytics error: ", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
const HEARTBEAT_INTERVAL = 30 * 1000; // seconds
|
||||
|
||||
export class Analytics {
|
||||
private baseUrl: URL = null;
|
||||
private visitVariables: Record<number, [string, string]> = {}; // {[id: number]: [name: string, value: string]}
|
||||
private firstPage = true;
|
||||
private heartbeatIntervalID: number = null;
|
||||
|
||||
private readonly creationTs: string;
|
||||
private readonly lastVisitTs: string;
|
||||
private readonly visitCount: string;
|
||||
|
||||
constructor() {
|
||||
this.creationTs = localStorage && localStorage.getItem(CREATION_TS_KEY);
|
||||
if (!this.creationTs && localStorage) {
|
||||
localStorage.setItem(CREATION_TS_KEY, this.creationTs = String(new Date().getTime()));
|
||||
}
|
||||
|
||||
this.lastVisitTs = localStorage && localStorage.getItem(LAST_VISIT_TS_KEY);
|
||||
this.visitCount = localStorage && localStorage.getItem(VISIT_COUNT_KEY) || "0";
|
||||
this.visitCount = String(parseInt(this.visitCount, 10) + 1); // increment
|
||||
if (localStorage) {
|
||||
localStorage.setItem(VISIT_COUNT_KEY, this.visitCount);
|
||||
}
|
||||
}
|
||||
|
||||
public get disabled() {
|
||||
return !this.baseUrl;
|
||||
}
|
||||
|
||||
public canEnable() {
|
||||
const piwikConfig = SdkConfig.get("piwik");
|
||||
let piwik: Optional<SnakedObject<Extract<IConfigOptions["piwik"], object>>>;
|
||||
if (typeof piwikConfig === 'object') {
|
||||
piwik = new SnakedObject(piwikConfig);
|
||||
}
|
||||
return navigator.doNotTrack !== "1" && piwik?.get("site_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Analytics if initialized but disabled
|
||||
* otherwise try and initalize, no-op if piwik config missing
|
||||
*/
|
||||
public async enable() {
|
||||
if (!this.disabled) return;
|
||||
if (!this.canEnable()) return;
|
||||
const piwikConfig = SdkConfig.get("piwik");
|
||||
let piwik: Optional<SnakedObject<Extract<IConfigOptions["piwik"], object>>>;
|
||||
if (typeof piwikConfig === 'object') {
|
||||
piwik = new SnakedObject(piwikConfig);
|
||||
}
|
||||
|
||||
this.baseUrl = new URL("piwik.php", piwik.get("url"));
|
||||
// set constants
|
||||
this.baseUrl.searchParams.set("rec", "1"); // rec is required for tracking
|
||||
this.baseUrl.searchParams.set("idsite", piwik.get("site_id")); // idsite is required for tracking
|
||||
this.baseUrl.searchParams.set("apiv", "1"); // API version to use
|
||||
this.baseUrl.searchParams.set("send_image", "0"); // we want a 204, not a tiny GIF
|
||||
// set user parameters
|
||||
this.baseUrl.searchParams.set("_id", getUid()); // uuid
|
||||
this.baseUrl.searchParams.set("_idts", this.creationTs); // first ts
|
||||
this.baseUrl.searchParams.set("_idvc", this.visitCount); // visit count
|
||||
if (this.lastVisitTs) {
|
||||
this.baseUrl.searchParams.set("_viewts", this.lastVisitTs); // last visit ts
|
||||
}
|
||||
|
||||
const platform = PlatformPeg.get();
|
||||
this.setVisitVariable('App Platform', platform.getHumanReadableName());
|
||||
try {
|
||||
this.setVisitVariable('App Version', await platform.getAppVersion());
|
||||
} catch (e) {
|
||||
this.setVisitVariable('App Version', 'unknown');
|
||||
}
|
||||
|
||||
this.setVisitVariable('Chosen Language', getCurrentLanguage());
|
||||
|
||||
const hostname = window.location.hostname;
|
||||
if (hostname === 'riot.im') {
|
||||
this.setVisitVariable('Instance', window.location.pathname);
|
||||
} else if (hostname.endsWith('.element.io')) {
|
||||
this.setVisitVariable('Instance', hostname.replace('.element.io', ''));
|
||||
}
|
||||
|
||||
let installedPWA = "unknown";
|
||||
try {
|
||||
// Known to work at least for desktop Chrome
|
||||
installedPWA = String(window.matchMedia('(display-mode: standalone)').matches);
|
||||
} catch (e) { }
|
||||
this.setVisitVariable('Installed PWA', installedPWA);
|
||||
|
||||
let touchInput = "unknown";
|
||||
try {
|
||||
// MDN claims broad support across browsers
|
||||
touchInput = String(window.matchMedia('(pointer: coarse)').matches);
|
||||
} catch (e) { }
|
||||
this.setVisitVariable('Touch Input', touchInput);
|
||||
|
||||
// start heartbeat
|
||||
this.heartbeatIntervalID = window.setInterval(this.ping.bind(this), HEARTBEAT_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Analytics, stop the heartbeat and clear identifiers from localStorage
|
||||
*/
|
||||
public disable() {
|
||||
if (this.disabled) return;
|
||||
this.trackEvent('Analytics', 'opt-out');
|
||||
window.clearInterval(this.heartbeatIntervalID);
|
||||
this.baseUrl = null;
|
||||
this.visitVariables = {};
|
||||
localStorage.removeItem(UID_KEY);
|
||||
localStorage.removeItem(CREATION_TS_KEY);
|
||||
localStorage.removeItem(VISIT_COUNT_KEY);
|
||||
localStorage.removeItem(LAST_VISIT_TS_KEY);
|
||||
}
|
||||
|
||||
private async track(data: IData) {
|
||||
if (this.disabled) return;
|
||||
|
||||
const now = new Date();
|
||||
const params = {
|
||||
...data,
|
||||
url: getRedactedUrl(),
|
||||
|
||||
_cvar: JSON.stringify(this.visitVariables), // user custom vars
|
||||
res: `${window.screen.width}x${window.screen.height}`, // resolution as WWWWxHHHH
|
||||
rand: String(Math.random()).slice(2, 8), // random nonce to cache-bust
|
||||
h: now.getHours(),
|
||||
m: now.getMinutes(),
|
||||
s: now.getSeconds(),
|
||||
};
|
||||
|
||||
const url = new URL(this.baseUrl.toString()); // copy
|
||||
for (const key in params) {
|
||||
url.searchParams.set(key, params[key]);
|
||||
}
|
||||
|
||||
try {
|
||||
await window.fetch(url.toString(), {
|
||||
method: "GET",
|
||||
mode: "no-cors",
|
||||
cache: "no-cache",
|
||||
redirect: "follow",
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error("Analytics error: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ping() {
|
||||
this.track({
|
||||
ping: "1",
|
||||
});
|
||||
localStorage.setItem(LAST_VISIT_TS_KEY, String(new Date().getTime())); // update last visit ts
|
||||
}
|
||||
|
||||
public trackPageChange(generationTimeMs?: number) {
|
||||
if (this.disabled) return;
|
||||
if (this.firstPage) {
|
||||
// De-duplicate first page
|
||||
// router seems to hit the fn twice
|
||||
this.firstPage = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof generationTimeMs !== 'number') {
|
||||
logger.warn('Analytics.trackPageChange: expected generationTimeMs to be a number');
|
||||
// But continue anyway because we still want to track the change
|
||||
}
|
||||
|
||||
this.track({
|
||||
gt_ms: String(generationTimeMs),
|
||||
});
|
||||
}
|
||||
|
||||
public trackEvent(category: string, action: string, name?: string, value?: string) {
|
||||
if (this.disabled) return;
|
||||
this.track({
|
||||
e_c: category,
|
||||
e_a: action,
|
||||
e_n: name,
|
||||
e_v: value,
|
||||
});
|
||||
}
|
||||
|
||||
private setVisitVariable(key: keyof typeof customVariables, value: string) {
|
||||
if (this.disabled) return;
|
||||
this.visitVariables[customVariables[key].id] = [key, value];
|
||||
}
|
||||
|
||||
public setLoggedIn(isGuest: boolean, homeserverUrl: string) {
|
||||
if (this.disabled) return;
|
||||
|
||||
const piwikConfig = SdkConfig.get("piwik");
|
||||
let piwik: Optional<SnakedObject<Extract<IConfigOptions["piwik"], object>>>;
|
||||
if (typeof piwikConfig === 'object') {
|
||||
piwik = new SnakedObject(piwikConfig);
|
||||
}
|
||||
if (!piwik) return;
|
||||
|
||||
const whitelistedHSUrls = piwik.get("whitelisted_hs_urls", "whitelistedHSUrls") || [];
|
||||
|
||||
this.setVisitVariable('User Type', isGuest ? 'Guest' : 'Logged In');
|
||||
this.setVisitVariable('Homeserver URL', whitelistRedact(whitelistedHSUrls, homeserverUrl));
|
||||
}
|
||||
|
||||
public setBreadcrumbs(state: boolean) {
|
||||
if (this.disabled) return;
|
||||
this.setVisitVariable('Breadcrumbs', state ? 'enabled' : 'disabled');
|
||||
}
|
||||
|
||||
public showDetailsModal = () => {
|
||||
let rows = [];
|
||||
if (!this.disabled) {
|
||||
rows = Object.values(this.visitVariables);
|
||||
} else {
|
||||
rows = Object.keys(customVariables).map(
|
||||
(k) => [
|
||||
k,
|
||||
_t('e.g. %(exampleValue)s', { exampleValue: customVariables[k].example }),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
const resolution = `${window.screen.width}x${window.screen.height}`;
|
||||
const otherVariables = [
|
||||
{
|
||||
expl: _td('Every page you use in the app'),
|
||||
value: _t(
|
||||
'e.g. <CurrentPageURL>',
|
||||
{},
|
||||
{
|
||||
CurrentPageURL: getRedactedUrl,
|
||||
},
|
||||
),
|
||||
},
|
||||
{ expl: _td('Your user agent'), value: navigator.userAgent },
|
||||
{ expl: _td('Your device resolution'), value: resolution },
|
||||
];
|
||||
|
||||
const piwikConfig = SdkConfig.get("piwik");
|
||||
let piwik: Optional<SnakedObject<Extract<IConfigOptions["piwik"], object>>>;
|
||||
if (typeof piwikConfig === 'object') {
|
||||
piwik = new SnakedObject(piwikConfig);
|
||||
}
|
||||
const cookiePolicyUrl = piwik?.get("policy_url");
|
||||
const cookiePolicyLink = _t(
|
||||
"Our complete cookie policy can be found <CookiePolicyLink>here</CookiePolicyLink>.",
|
||||
{},
|
||||
{
|
||||
"CookiePolicyLink": (sub) => {
|
||||
return <a href={cookiePolicyUrl} target="_blank" rel="noreferrer noopener">{ sub }</a>;
|
||||
},
|
||||
});
|
||||
Modal.createTrackedDialog('Analytics Details', '', ErrorDialog, {
|
||||
title: _t('Analytics'),
|
||||
description: <div className="mx_AnalyticsModal">
|
||||
{ cookiePolicyUrl && <p>{ cookiePolicyLink }</p> }
|
||||
<div>{ _t('Some examples of the information being sent to us to help make %(brand)s better includes:', {
|
||||
brand: SdkConfig.get().brand,
|
||||
}) }</div>
|
||||
<table>
|
||||
{ rows.map((row) => <tr key={row[0]}>
|
||||
<td className="mx_AnalyticsModal_label">{ _t(
|
||||
customVariables[row[0]].expl,
|
||||
customVariables[row[0]].getTextVariables ?
|
||||
customVariables[row[0]].getTextVariables() :
|
||||
null,
|
||||
) }</td>
|
||||
{ row[1] !== undefined && <td><code>{ row[1] }</code></td> }
|
||||
</tr>) }
|
||||
{ otherVariables.map((item, index) =>
|
||||
<tr key={index}>
|
||||
<td>{ _t(item.expl) }</td>
|
||||
<td><code>{ item.value }</code></td>
|
||||
</tr>,
|
||||
) }
|
||||
</table>
|
||||
<div>
|
||||
{ _t('Where this page includes identifiable information, such as a room, '
|
||||
+ 'user ID, that data is removed before being sent to the server.') }
|
||||
</div>
|
||||
</div>,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (!window.mxAnalytics) {
|
||||
window.mxAnalytics = new Analytics();
|
||||
}
|
||||
export default window.mxAnalytics;
|
|
@ -47,7 +47,6 @@ import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
|||
import WidgetStore from "./stores/WidgetStore";
|
||||
import { WidgetMessagingStore } from "./stores/widgets/WidgetMessagingStore";
|
||||
import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions";
|
||||
import Analytics from './Analytics';
|
||||
import { UIFeature } from "./settings/UIFeature";
|
||||
import { Action } from './dispatcher/actions';
|
||||
import VoipUserMapper from './VoipUserMapper';
|
||||
|
@ -305,7 +304,6 @@ export default class CallHandler extends EventEmitter {
|
|||
return;
|
||||
}
|
||||
|
||||
Analytics.trackEvent('voip', 'receiveCall', 'type', call.type);
|
||||
this.addCallForRoom(mappedRoomId, call);
|
||||
this.setCallListeners(call);
|
||||
// Explicitly handle first state change
|
||||
|
@ -447,7 +445,6 @@ export default class CallHandler extends EventEmitter {
|
|||
call.on(CallEvent.Error, (err: CallError) => {
|
||||
if (!this.matchesCallForThisRoom(call)) return;
|
||||
|
||||
Analytics.trackEvent('voip', 'callError', 'error', err.toString());
|
||||
logger.error("Call error:", err);
|
||||
|
||||
if (err.code === CallErrorCode.NoUserMedia) {
|
||||
|
@ -463,7 +460,7 @@ export default class CallHandler extends EventEmitter {
|
|||
return;
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Call Failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Call Failed'),
|
||||
description: err.message,
|
||||
});
|
||||
|
@ -471,8 +468,6 @@ export default class CallHandler extends EventEmitter {
|
|||
call.on(CallEvent.Hangup, () => {
|
||||
if (!this.matchesCallForThisRoom(call)) return;
|
||||
|
||||
Analytics.trackEvent('voip', 'callHangup');
|
||||
|
||||
this.removeCallForRoom(mappedRoomId);
|
||||
});
|
||||
call.on(CallEvent.State, (newState: CallState, oldState: CallState) => {
|
||||
|
@ -584,7 +579,6 @@ export default class CallHandler extends EventEmitter {
|
|||
}
|
||||
case CallState.Ended: {
|
||||
const hangupReason = call.hangupReason;
|
||||
Analytics.trackEvent('voip', 'callEnded', 'hangupReason', hangupReason);
|
||||
this.removeCallForRoom(mappedRoomId);
|
||||
if (oldState === CallState.InviteSent && call.hangupParty === CallParty.Remote) {
|
||||
this.play(AudioID.Busy);
|
||||
|
@ -603,13 +597,13 @@ export default class CallHandler extends EventEmitter {
|
|||
description = _t("The call could not be established");
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title, description,
|
||||
});
|
||||
} else if (
|
||||
hangupReason === CallErrorCode.AnsweredElsewhere && oldState === CallState.Connecting
|
||||
) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Answered Elsewhere"),
|
||||
description: _t("The call was answered on another device."),
|
||||
});
|
||||
|
@ -709,7 +703,7 @@ export default class CallHandler extends EventEmitter {
|
|||
private showICEFallbackPrompt(): void {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const code = sub => <code>{ sub }</code>;
|
||||
Modal.createTrackedDialog('No TURN servers', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Call failed due to misconfigured server"),
|
||||
description: <div>
|
||||
<p>{ _t(
|
||||
|
@ -759,14 +753,12 @@ export default class CallHandler extends EventEmitter {
|
|||
</div>;
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Media capture failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title, description,
|
||||
}, null, true);
|
||||
}
|
||||
|
||||
private async placeMatrixCall(roomId: string, type: CallType, transferee?: MatrixCall): Promise<void> {
|
||||
Analytics.trackEvent('voip', 'placeCall', 'type', type);
|
||||
|
||||
const mappedRoomId = (await VoipUserMapper.sharedInstance().getOrCreateVirtualRoomForRoom(roomId)) || roomId;
|
||||
logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId);
|
||||
|
||||
|
@ -789,7 +781,7 @@ export default class CallHandler extends EventEmitter {
|
|||
try {
|
||||
this.addCallForRoom(roomId, call);
|
||||
} catch (e) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Existing Call with user', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Already in call'),
|
||||
description: _t("You're already in a call with this person."),
|
||||
});
|
||||
|
@ -821,7 +813,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
// if the runtime env doesn't do VoIP, whine.
|
||||
if (!MatrixClientPeg.get().supportsVoip()) {
|
||||
Modal.createTrackedDialog('Call Handler', 'VoIP is unsupported', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Calls are unsupported'),
|
||||
description: _t('You cannot place calls in this browser.'),
|
||||
});
|
||||
|
@ -829,7 +821,7 @@ export default class CallHandler extends EventEmitter {
|
|||
}
|
||||
|
||||
if (MatrixClientPeg.get().getSyncState() === SyncState.Error) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Sync error', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Connectivity to the server has been lost'),
|
||||
description: _t('You cannot place calls without a connection to the server.'),
|
||||
});
|
||||
|
@ -838,7 +830,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
// don't allow > 2 calls to be placed.
|
||||
if (this.getAllActiveCalls().length > 1) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Too Many Calls'),
|
||||
description: _t("You've reached the maximum number of simultaneous calls."),
|
||||
});
|
||||
|
@ -856,7 +848,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
const members = room.getJoinedMembers();
|
||||
if (members.length <= 1) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Cannot place call with self', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
description: _t('You cannot place a call with yourself.'),
|
||||
});
|
||||
} else if (members.length === 2) {
|
||||
|
@ -901,7 +893,7 @@ export default class CallHandler extends EventEmitter {
|
|||
if (!this.calls.has(roomId)) return;
|
||||
|
||||
if (this.getAllActiveCalls().length > 1) {
|
||||
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Too Many Calls'),
|
||||
description: _t("You've reached the maximum number of simultaneous calls."),
|
||||
});
|
||||
|
@ -926,7 +918,7 @@ export default class CallHandler extends EventEmitter {
|
|||
public async dialNumber(number: string, transferee?: MatrixCall): Promise<void> {
|
||||
const results = await this.pstnLookup(number);
|
||||
if (!results || results.length === 0 || !results[0].userid) {
|
||||
Modal.createTrackedDialog('', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to look up phone number"),
|
||||
description: _t("There was an error looking up the phone number"),
|
||||
});
|
||||
|
@ -969,7 +961,7 @@ export default class CallHandler extends EventEmitter {
|
|||
|
||||
const results = await this.pstnLookup(destination);
|
||||
if (!results || results.length === 0 || !results[0].userid) {
|
||||
Modal.createTrackedDialog('', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to transfer call"),
|
||||
description: _t("There was an error looking up the phone number"),
|
||||
});
|
||||
|
@ -998,7 +990,7 @@ export default class CallHandler extends EventEmitter {
|
|||
await call.transfer(destination);
|
||||
} catch (e) {
|
||||
logger.log("Failed to transfer call", e);
|
||||
Modal.createTrackedDialog('Failed to transfer call', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Transfer Failed'),
|
||||
description: _t('Failed to transfer call'),
|
||||
});
|
||||
|
@ -1036,7 +1028,6 @@ export default class CallHandler extends EventEmitter {
|
|||
private async placeJitsiCall(roomId: string, type: CallType): Promise<void> {
|
||||
const client = MatrixClientPeg.get();
|
||||
logger.info(`Place conference call in ${roomId}`);
|
||||
Analytics.trackEvent('voip', 'placeConferenceCall');
|
||||
|
||||
dis.dispatch({ action: 'appsDrawer', show: true });
|
||||
|
||||
|
@ -1053,7 +1044,7 @@ export default class CallHandler extends EventEmitter {
|
|||
logger.log('Jitsi widget added');
|
||||
} catch (e) {
|
||||
if (e.errcode === 'M_FORBIDDEN') {
|
||||
Modal.createTrackedDialog('Call Failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Permission Required'),
|
||||
description: _t("You do not have permission to start a conference call in this room"),
|
||||
});
|
||||
|
@ -1062,29 +1053,6 @@ export default class CallHandler extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
public terminateCallApp(roomId: string): void {
|
||||
logger.info("Terminating conference call in " + roomId);
|
||||
|
||||
Modal.createTrackedDialog('Confirm Jitsi Terminate', '', QuestionDialog, {
|
||||
hasCancelButton: true,
|
||||
title: _t("End conference"),
|
||||
description: _t("This will end the conference for everyone. Continue?"),
|
||||
button: _t("End conference"),
|
||||
onFinished: (proceed) => {
|
||||
if (!proceed) return;
|
||||
|
||||
// We'll just obliterate them all. There should only ever be one, but might as well
|
||||
// be safe.
|
||||
const roomInfo = WidgetStore.instance.getRoom(roomId);
|
||||
const jitsiWidgets = roomInfo.widgets.filter(w => WidgetType.JITSI.matches(w.type));
|
||||
jitsiWidgets.forEach(w => {
|
||||
// setting invalid content removes it
|
||||
WidgetUtils.setRoomWidget(roomId, w.id);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public hangupCallApp(roomId: string): void {
|
||||
logger.info("Leaving conference call in " + roomId);
|
||||
|
||||
|
|
|
@ -397,7 +397,7 @@ export default class ContentMessages {
|
|||
}
|
||||
|
||||
if (tooBigFiles.length > 0) {
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
|
||||
const { finished } = Modal.createDialog<[boolean]>(UploadFailureDialog, {
|
||||
badFiles: tooBigFiles,
|
||||
totalFiles: files.length,
|
||||
contentMessages: this,
|
||||
|
@ -413,13 +413,11 @@ export default class ContentMessages {
|
|||
for (let i = 0; i < okFiles.length; ++i) {
|
||||
const file = okFiles[i];
|
||||
if (!uploadAll) {
|
||||
const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
|
||||
'', UploadConfirmDialog, {
|
||||
file,
|
||||
currentIndex: i,
|
||||
totalFiles: okFiles.length,
|
||||
},
|
||||
);
|
||||
const { finished } = Modal.createDialog<[boolean, boolean]>(UploadConfirmDialog, {
|
||||
file,
|
||||
currentIndex: i,
|
||||
totalFiles: okFiles.length,
|
||||
});
|
||||
const [shouldContinue, shouldUploadAll] = await finished;
|
||||
if (!shouldContinue) break;
|
||||
if (shouldUploadAll) {
|
||||
|
@ -588,7 +586,7 @@ export default class ContentMessages {
|
|||
{ fileName: upload.fileName },
|
||||
);
|
||||
}
|
||||
Modal.createTrackedDialog('Upload failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Upload Failed'),
|
||||
description: desc,
|
||||
});
|
||||
|
|
|
@ -18,7 +18,6 @@ import { MatrixError } from "matrix-js-sdk/src/http-api";
|
|||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { Error as ErrorEvent } from "@matrix-org/analytics-events/types/typescript/Error";
|
||||
|
||||
import Analytics from "./Analytics";
|
||||
import { PosthogAnalytics } from './PosthogAnalytics';
|
||||
|
||||
export class DecryptionFailure {
|
||||
|
@ -37,7 +36,6 @@ export type ErrCodeMapFn = (errcode: string) => ErrorCode;
|
|||
|
||||
export class DecryptionFailureTracker {
|
||||
private static internalInstance = new DecryptionFailureTracker((total, errorCode, rawError) => {
|
||||
Analytics.trackEvent('E2E', 'Decryption failure', errorCode, String(total));
|
||||
for (let i = 0; i < total; i++) {
|
||||
PosthogAnalytics.instance.trackEvent<ErrorEvent>({
|
||||
eventName: "Error",
|
||||
|
|
|
@ -135,18 +135,15 @@ export interface IConfigOptions {
|
|||
servers: string[];
|
||||
};
|
||||
|
||||
// piwik (matomo) is deprecated in favour of posthog
|
||||
piwik?: false | {
|
||||
url: string; // piwik instance
|
||||
site_id: string;
|
||||
policy_url: string; // cookie policy
|
||||
whitelisted_hs_urls: string[];
|
||||
policy_url: string; // deprecated in favour of `privacy_policy_url` at root instead
|
||||
};
|
||||
posthog?: {
|
||||
project_api_key: string;
|
||||
api_host: string; // hostname
|
||||
};
|
||||
analytics_owner?: string; // defaults to `brand`
|
||||
privacy_policy_url?: string; // location for cookie policy
|
||||
|
||||
// Server hosting upsell options
|
||||
hosting_signup_link?: string; // slightly different from `host_signup`
|
||||
|
|
|
@ -143,27 +143,25 @@ export default class IdentityAuthClient {
|
|||
!doesAccountDataHaveIdentityServer() &&
|
||||
!(await doesIdentityServerHaveTerms(identityServerUrl))
|
||||
) {
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Default identity server terms warning', '',
|
||||
QuestionDialog, {
|
||||
title: _t("Identity server has no terms of service"),
|
||||
description: (
|
||||
<div>
|
||||
<p>{ _t(
|
||||
"This action requires accessing the default identity server " +
|
||||
"<server /> to validate an email address or phone number, " +
|
||||
"but the server does not have any terms of service.", {},
|
||||
{
|
||||
server: () => <b>{ abbreviateUrl(identityServerUrl) }</b>,
|
||||
},
|
||||
) }</p>
|
||||
<p>{ _t(
|
||||
"Only continue if you trust the owner of the server.",
|
||||
) }</p>
|
||||
</div>
|
||||
),
|
||||
button: _t("Trust"),
|
||||
});
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Identity server has no terms of service"),
|
||||
description: (
|
||||
<div>
|
||||
<p>{ _t(
|
||||
"This action requires accessing the default identity server " +
|
||||
"<server /> to validate an email address or phone number, " +
|
||||
"but the server does not have any terms of service.", {},
|
||||
{
|
||||
server: () => <b>{ abbreviateUrl(identityServerUrl) }</b>,
|
||||
},
|
||||
) }</p>
|
||||
<p>{ _t(
|
||||
"Only continue if you trust the owner of the server.",
|
||||
) }</p>
|
||||
</div>
|
||||
),
|
||||
button: _t("Trust"),
|
||||
});
|
||||
const [confirmed] = await finished;
|
||||
if (confirmed) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
|
|
|
@ -28,7 +28,6 @@ import { IMatrixClientCreds, MatrixClientPeg } from './MatrixClientPeg';
|
|||
import SecurityCustomisations from "./customisations/Security";
|
||||
import EventIndexPeg from './indexing/EventIndexPeg';
|
||||
import createMatrixClient from './utils/createMatrixClient';
|
||||
import Analytics from './Analytics';
|
||||
import Notifier from './Notifier';
|
||||
import UserActivity from './UserActivity';
|
||||
import Presence from './Presence';
|
||||
|
@ -201,7 +200,7 @@ export function attemptTokenLogin(
|
|||
const identityServer = localStorage.getItem(SSO_ID_SERVER_URL_KEY);
|
||||
if (!homeserver) {
|
||||
logger.warn("Cannot log in with token: can't determine HS URL to use");
|
||||
Modal.createTrackedDialog("SSO", "Unknown HS", ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("We couldn't log you in"),
|
||||
description: _t("We asked the browser to remember which homeserver you use to let you sign in, " +
|
||||
"but unfortunately your browser has forgotten it. Go to the sign in page and try again."),
|
||||
|
@ -226,7 +225,7 @@ export function attemptTokenLogin(
|
|||
return true;
|
||||
});
|
||||
}).catch((err) => {
|
||||
Modal.createTrackedDialog("SSO", "Token Rejected", ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("We couldn't log you in"),
|
||||
description: err.name === "ConnectionError"
|
||||
? _t("Your homeserver was unreachable and was not able to log you in. Please try again. " +
|
||||
|
@ -470,7 +469,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
|
|||
async function handleLoadSessionFailure(e: Error): Promise<boolean> {
|
||||
logger.error("Unable to load session", e);
|
||||
|
||||
const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
|
||||
const modal = Modal.createDialog(SessionRestoreErrorDialog, {
|
||||
error: e,
|
||||
});
|
||||
|
||||
|
@ -597,8 +596,6 @@ async function doSetLoggedIn(
|
|||
await abortLogin();
|
||||
}
|
||||
|
||||
Analytics.setLoggedIn(credentials.guest, credentials.homeserverUrl);
|
||||
|
||||
MatrixClientPeg.replaceUsingCreds(credentials);
|
||||
|
||||
setSentryUser(credentials.userId);
|
||||
|
@ -640,7 +637,7 @@ async function doSetLoggedIn(
|
|||
|
||||
function showStorageEvictedDialog(): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
Modal.createTrackedDialog('Storage evicted', '', StorageEvictedDialog, {
|
||||
Modal.createDialog(StorageEvictedDialog, {
|
||||
onFinished: resolve,
|
||||
});
|
||||
});
|
||||
|
@ -880,8 +877,6 @@ export async function onLoggedOut(): Promise<void> {
|
|||
* @returns {Promise} promise which resolves once the stores have been cleared
|
||||
*/
|
||||
async function clearStorage(opts?: { deleteEverything?: boolean }): Promise<void> {
|
||||
Analytics.disable();
|
||||
|
||||
if (window.localStorage) {
|
||||
// try to save any 3pid invites from being obliterated and registration time
|
||||
const pendingInvites = ThreepidInviteStore.instance.getWireInvites();
|
||||
|
|
|
@ -193,8 +193,6 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
}
|
||||
}
|
||||
|
||||
StorageManager.trackStores(this.matrixClient);
|
||||
|
||||
// try to initialise e2e on the new client
|
||||
try {
|
||||
// check that we have a version of the js-sdk which includes initCrypto
|
||||
|
|
|
@ -20,7 +20,6 @@ import ReactDOM from 'react-dom';
|
|||
import classNames from 'classnames';
|
||||
import { defer, sleep } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import Analytics from './Analytics';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import AsyncWrapper from './AsyncWrapper';
|
||||
|
||||
|
@ -103,24 +102,6 @@ export class ModalManager {
|
|||
return this.priorityModal || this.staticModal || this.modals.length > 0;
|
||||
}
|
||||
|
||||
public createTrackedDialog<T extends any[]>(
|
||||
analyticsAction: string,
|
||||
analyticsInfo: string,
|
||||
...rest: Parameters<ModalManager["createDialog"]>
|
||||
) {
|
||||
Analytics.trackEvent('Modal', analyticsAction, analyticsInfo);
|
||||
return this.createDialog<T>(...rest);
|
||||
}
|
||||
|
||||
public appendTrackedDialog<T extends any[]>(
|
||||
analyticsAction: string,
|
||||
analyticsInfo: string,
|
||||
...rest: Parameters<ModalManager["appendDialog"]>
|
||||
) {
|
||||
Analytics.trackEvent('Modal', analyticsAction, analyticsInfo);
|
||||
return this.appendDialog<T>(...rest);
|
||||
}
|
||||
|
||||
public createDialog<T extends any[]>(
|
||||
Element: React.ComponentType,
|
||||
...rest: ParametersWithoutFirst<ModalManager["createDialogAsync"]>
|
||||
|
@ -135,24 +116,6 @@ export class ModalManager {
|
|||
return this.appendDialogAsync<T>(Promise.resolve(Element), ...rest);
|
||||
}
|
||||
|
||||
public createTrackedDialogAsync<T extends any[]>(
|
||||
analyticsAction: string,
|
||||
analyticsInfo: string,
|
||||
...rest: Parameters<ModalManager["createDialogAsync"]>
|
||||
) {
|
||||
Analytics.trackEvent('Modal', analyticsAction, analyticsInfo);
|
||||
return this.createDialogAsync<T>(...rest);
|
||||
}
|
||||
|
||||
public appendTrackedDialogAsync<T extends any[]>(
|
||||
analyticsAction: string,
|
||||
analyticsInfo: string,
|
||||
...rest: Parameters<ModalManager["appendDialogAsync"]>
|
||||
) {
|
||||
Analytics.trackEvent('Modal', analyticsAction, analyticsInfo);
|
||||
return this.appendDialogAsync<T>(...rest);
|
||||
}
|
||||
|
||||
public closeCurrentModal(reason: string) {
|
||||
const modal = this.getCurrentModal();
|
||||
if (!modal) {
|
||||
|
@ -273,7 +236,7 @@ export class ModalManager {
|
|||
* @param {onBeforeClose} options.onBeforeClose a callback to decide whether to close the dialog
|
||||
* @returns {object} Object with 'close' parameter being a function that will close the dialog
|
||||
*/
|
||||
private createDialogAsync<T extends any[]>(
|
||||
public createDialogAsync<T extends any[]>(
|
||||
prom: Promise<React.ComponentType>,
|
||||
props?: IProps<T>,
|
||||
className?: string,
|
||||
|
|
|
@ -28,7 +28,6 @@ import { MatrixClientPeg } from './MatrixClientPeg';
|
|||
import SdkConfig from './SdkConfig';
|
||||
import PlatformPeg from './PlatformPeg';
|
||||
import * as TextForEvent from './TextForEvent';
|
||||
import Analytics from './Analytics';
|
||||
import * as Avatar from './Avatar';
|
||||
import dis from './dispatcher/dispatcher';
|
||||
import { _t } from './languageHandler';
|
||||
|
@ -230,8 +229,6 @@ export const Notifier = {
|
|||
// calculated value. It is determined based upon whether or not the master rule is enabled
|
||||
// and other flags. Setting it here would cause a circular reference.
|
||||
|
||||
Analytics.trackEvent('Notifier', 'Set Enabled', String(enable));
|
||||
|
||||
// make sure that we persist the current setting audio_enabled setting
|
||||
// before changing anything
|
||||
if (SettingsStore.isLevelSupported(SettingLevel.DEVICE)) {
|
||||
|
@ -249,7 +246,7 @@ export const Notifier = {
|
|||
? _t('%(brand)s does not have permission to send you notifications - ' +
|
||||
'please check your browser settings', { brand })
|
||||
: _t('%(brand)s was not given permission to send notifications - please try again', { brand });
|
||||
Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Unable to enable Notifications'),
|
||||
description,
|
||||
});
|
||||
|
@ -298,8 +295,6 @@ export const Notifier = {
|
|||
setPromptHidden: function(hidden: boolean, persistent = true) {
|
||||
this.toolbarHidden = hidden;
|
||||
|
||||
Analytics.trackEvent('Notifier', 'Set Toolbar Hidden', String(hidden));
|
||||
|
||||
hideNotificationsToast();
|
||||
|
||||
// update the info to localStorage for persistent settings
|
||||
|
|
|
@ -49,7 +49,7 @@ export async function startAnyRegistrationFlow(
|
|||
options: { go_home_on_cancel?: boolean, go_welcome_on_cancel?: boolean, screen_after?: boolean},
|
||||
): Promise<void> {
|
||||
if (options === undefined) options = {};
|
||||
const modal = Modal.createTrackedDialog('Registration required', '', QuestionDialog, {
|
||||
const modal = Modal.createDialog(QuestionDialog, {
|
||||
hasCancelButton: true,
|
||||
quitOnly: true,
|
||||
title: _t("Sign In or Create Account"),
|
||||
|
|
|
@ -61,16 +61,16 @@ export function inviteMultipleToRoom(
|
|||
|
||||
export function showStartChatInviteDialog(initialText = ""): void {
|
||||
// This dialog handles the room creation internally - we don't need to worry about it.
|
||||
Modal.createTrackedDialog(
|
||||
'Start DM', '', InviteDialog, { kind: KIND_DM, initialText },
|
||||
Modal.createDialog(
|
||||
InviteDialog, { kind: KIND_DM, initialText },
|
||||
/*className=*/"mx_InviteDialog_flexWrapper", /*isPriority=*/false, /*isStatic=*/true,
|
||||
);
|
||||
}
|
||||
|
||||
export function showRoomInviteDialog(roomId: string, initialText = ""): void {
|
||||
// This dialog handles the room creation internally - we don't need to worry about it.
|
||||
Modal.createTrackedDialog(
|
||||
"Invite Users", "", InviteDialog, {
|
||||
Modal.createDialog(
|
||||
InviteDialog, {
|
||||
kind: KIND_INVITE,
|
||||
initialText,
|
||||
roomId,
|
||||
|
@ -108,7 +108,7 @@ export function inviteUsersToRoom(
|
|||
showAnyInviteErrors(result.states, room, result.inviter);
|
||||
}).catch((err) => {
|
||||
logger.error(err.stack);
|
||||
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to invite"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -127,7 +127,7 @@ export function showAnyInviteErrors(
|
|||
// Just get the first message because there was a fatal problem on the first
|
||||
// user. This usually means that no other users were attempted, making it
|
||||
// pointless for us to list who failed exactly.
|
||||
Modal.createTrackedDialog('Failed to invite users to the room', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to invite users to %(roomName)s", { roomName: room.name }),
|
||||
description: inviter.getErrorText(failedUsers[0]),
|
||||
});
|
||||
|
@ -175,7 +175,7 @@ export function showAnyInviteErrors(
|
|||
</div>
|
||||
</div>;
|
||||
|
||||
Modal.createTrackedDialog("Some invites could not be sent", "", ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Some invites couldn't be sent"),
|
||||
description,
|
||||
});
|
||||
|
|
|
@ -150,7 +150,7 @@ async function getSecretStorageKey(
|
|||
}
|
||||
|
||||
const inputToKey = makeInputToKey(keyInfo);
|
||||
const { finished } = Modal.createTrackedDialog("Access Secret Storage dialog", "",
|
||||
const { finished } = Modal.createDialog(
|
||||
AccessSecretStorageDialog,
|
||||
/* props= */
|
||||
{
|
||||
|
@ -195,7 +195,7 @@ export async function getDehydrationKey(
|
|||
}
|
||||
|
||||
const inputToKey = makeInputToKey(keyInfo);
|
||||
const { finished } = Modal.createTrackedDialog("Access Secret Storage dialog", "",
|
||||
const { finished } = Modal.createDialog(
|
||||
AccessSecretStorageDialog,
|
||||
/* props= */
|
||||
{
|
||||
|
@ -298,7 +298,7 @@ export const crossSigningCallbacks: ICryptoCallbacks = {
|
|||
export async function promptForBackupPassphrase(): Promise<Uint8Array> {
|
||||
let key: Uint8Array;
|
||||
|
||||
const { finished } = Modal.createTrackedDialog('Restore Backup', '', RestoreKeyBackupDialog, {
|
||||
const { finished } = Modal.createDialog(RestoreKeyBackupDialog, {
|
||||
showSummary: false, keyCallback: k => key = k,
|
||||
}, null, /* priority = */ false, /* static = */ true);
|
||||
|
||||
|
@ -336,7 +336,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
|
|||
if (!(await cli.hasSecretStorageKey()) || forceReset) {
|
||||
// This dialog calls bootstrap itself after guiding the user through
|
||||
// passphrase creation.
|
||||
const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
|
||||
const { finished } = Modal.createDialogAsync(
|
||||
import(
|
||||
"./async-components/views/dialogs/security/CreateSecretStorageDialog"
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
@ -363,14 +363,11 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
|
|||
} else {
|
||||
await cli.bootstrapCrossSigning({
|
||||
authUploadDeviceSigningKeys: async (makeRequest) => {
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Cross-signing keys dialog', '', InteractiveAuthDialog,
|
||||
{
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: cli,
|
||||
makeRequest,
|
||||
},
|
||||
);
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: cli,
|
||||
makeRequest,
|
||||
});
|
||||
const [confirmed] = await finished;
|
||||
if (!confirmed) {
|
||||
throw new Error("Cross-signing key upload auth canceled");
|
||||
|
|
|
@ -82,7 +82,7 @@ const singleMxcUpload = async (): Promise<any> => {
|
|||
fileSelector.onchange = (ev: HTMLInputEvent) => {
|
||||
const file = ev.target.files[0];
|
||||
|
||||
Modal.createTrackedDialog('Upload Files confirmation', '', UploadConfirmDialog, {
|
||||
Modal.createDialog(UploadConfirmDialog, {
|
||||
file,
|
||||
onFinished: (shouldContinue) => {
|
||||
resolve(shouldContinue ? MatrixClientPeg.get().uploadContent(file) : null);
|
||||
|
@ -307,7 +307,7 @@ export const Commands = [
|
|||
);
|
||||
}
|
||||
|
||||
const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
|
||||
const { finished } = Modal.createDialog(
|
||||
RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null,
|
||||
/*isPriority=*/false, /*isStatic=*/true);
|
||||
|
||||
|
@ -483,7 +483,7 @@ export const Commands = [
|
|||
const ref = e => e && linkifyElement(e);
|
||||
const body = topicToHtml(topic.text, topic.html, ref, true);
|
||||
|
||||
Modal.createTrackedDialog('Slash Commands', 'Topic', InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: room.name,
|
||||
description: <div ref={ref}>{ body }</div>,
|
||||
hasCloseButton: true,
|
||||
|
@ -529,22 +529,18 @@ export const Commands = [
|
|||
) {
|
||||
const defaultIdentityServerUrl = getDefaultIdentityServerUrl();
|
||||
if (defaultIdentityServerUrl) {
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>(
|
||||
'Slash Commands',
|
||||
'Identity server',
|
||||
QuestionDialog, {
|
||||
title: _t("Use an identity server"),
|
||||
description: <p>{ _t(
|
||||
"Use an identity server to invite by email. " +
|
||||
"Click continue to use the default identity server " +
|
||||
"(%(defaultIdentityServerName)s) or manage in Settings.",
|
||||
{
|
||||
defaultIdentityServerName: abbreviateUrl(defaultIdentityServerUrl),
|
||||
},
|
||||
) }</p>,
|
||||
button: _t("Continue"),
|
||||
},
|
||||
);
|
||||
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
|
||||
title: _t("Use an identity server"),
|
||||
description: <p>{ _t(
|
||||
"Use an identity server to invite by email. " +
|
||||
"Click continue to use the default identity server " +
|
||||
"(%(defaultIdentityServerName)s) or manage in Settings.",
|
||||
{
|
||||
defaultIdentityServerName: abbreviateUrl(defaultIdentityServerUrl),
|
||||
},
|
||||
) }</p>,
|
||||
button: _t("Continue"),
|
||||
});
|
||||
|
||||
prom = finished.then(([useDefault]) => {
|
||||
if (useDefault) {
|
||||
|
@ -810,7 +806,7 @@ export const Commands = [
|
|||
ignoredUsers.push(userId); // de-duped internally in the js-sdk
|
||||
return success(
|
||||
cli.setIgnoredUsers(ignoredUsers).then(() => {
|
||||
Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: _t('Ignored user'),
|
||||
description: <div>
|
||||
<p>{ _t('You are now ignoring %(userId)s', { userId }) }</p>
|
||||
|
@ -840,7 +836,7 @@ export const Commands = [
|
|||
if (index !== -1) ignoredUsers.splice(index, 1);
|
||||
return success(
|
||||
cli.setIgnoredUsers(ignoredUsers).then(() => {
|
||||
Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: _t('Unignored user'),
|
||||
description: <div>
|
||||
<p>{ _t('You are no longer ignoring %(userId)s', { userId }) }</p>
|
||||
|
@ -1040,7 +1036,7 @@ export const Commands = [
|
|||
await cli.setDeviceVerified(userId, deviceId, true);
|
||||
|
||||
// Tell the user we verified everything
|
||||
Modal.createTrackedDialog('Slash Commands', 'Verified key', InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: _t('Verified key'),
|
||||
description: <div>
|
||||
<p>
|
||||
|
@ -1098,7 +1094,7 @@ export const Commands = [
|
|||
command: "help",
|
||||
description: _td("Displays list of commands with usages and descriptions"),
|
||||
runFn: function() {
|
||||
Modal.createTrackedDialog('Slash Commands', 'Help', SlashCommandHelpDialog);
|
||||
Modal.createDialog(SlashCommandHelpDialog);
|
||||
return success();
|
||||
},
|
||||
category: CommandCategories.advanced,
|
||||
|
@ -1130,7 +1126,7 @@ export const Commands = [
|
|||
args: "<description>",
|
||||
runFn: function(roomId, args) {
|
||||
return success(
|
||||
Modal.createTrackedDialog('Slash Commands', 'Bug Report Dialog', BugReportDialog, {
|
||||
Modal.createDialog(BugReportDialog, {
|
||||
initialText: args,
|
||||
}).finished,
|
||||
);
|
||||
|
|
|
@ -190,7 +190,7 @@ export async function dialogTermsInteractionCallback(
|
|||
): Promise<string[]> {
|
||||
logger.log("Terms that need agreement", policiesAndServicePairs);
|
||||
|
||||
const { finished } = Modal.createTrackedDialog<[boolean, string[]]>('Terms of Service', '', TermsDialog, {
|
||||
const { finished } = Modal.createDialog<[boolean, string[]]>(TermsDialog, {
|
||||
policiesAndServicePairs,
|
||||
agreedUrls,
|
||||
}, classNames("mx_TermsDialog", extraClassNames));
|
||||
|
|
|
@ -91,7 +91,7 @@ export default class RoomListActions {
|
|||
room, newTag === DefaultTagID.DM,
|
||||
).catch((err) => {
|
||||
logger.error("Failed to set DM tag " + err);
|
||||
Modal.createTrackedDialog('Failed to set direct message tag', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to set direct message tag'),
|
||||
description: ((err && err.message) ? err.message : _t('Operation failed')),
|
||||
});
|
||||
|
@ -111,7 +111,7 @@ export default class RoomListActions {
|
|||
roomId, oldTag,
|
||||
).catch(function(err) {
|
||||
logger.error("Failed to remove tag " + oldTag + " from room: " + err);
|
||||
Modal.createTrackedDialog('Failed to remove tag from room', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to remove tag %(tagName)s from room', { tagName: oldTag }),
|
||||
description: ((err && err.message) ? err.message : _t('Operation failed')),
|
||||
});
|
||||
|
@ -130,7 +130,7 @@ export default class RoomListActions {
|
|||
|
||||
const promiseToAdd = matrixClient.setRoomTag(roomId, newTag, metaData).catch(function(err) {
|
||||
logger.error("Failed to add tag " + newTag + " to room: " + err);
|
||||
Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to add tag %(tagName)s to room', { tagName: newTag }),
|
||||
description: ((err && err.message) ? err.message : _t('Operation failed')),
|
||||
});
|
||||
|
|
|
@ -134,10 +134,7 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
|
|||
|
||||
private onDisable = async () => {
|
||||
const DisableEventIndexDialog = (await import("./DisableEventIndexDialog")).default;
|
||||
Modal.createTrackedDialog("Disable message search", "Disable message search",
|
||||
DisableEventIndexDialog,
|
||||
null, null, /* priority = */ false, /* static = */ true,
|
||||
);
|
||||
Modal.createDialog(DisableEventIndexDialog, null, null, /* priority = */ false, /* static = */ true);
|
||||
};
|
||||
|
||||
private onCrawlerSleepTimeChange = (e) => {
|
||||
|
|
|
@ -303,18 +303,15 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
|
|||
},
|
||||
};
|
||||
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Cross-signing keys dialog', '', InteractiveAuthDialog,
|
||||
{
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
makeRequest,
|
||||
aestheticsForStagePhases: {
|
||||
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
|
||||
[SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics,
|
||||
},
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
makeRequest,
|
||||
aestheticsForStagePhases: {
|
||||
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
|
||||
[SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics,
|
||||
},
|
||||
);
|
||||
});
|
||||
const [confirmed] = await finished;
|
||||
if (!confirmed) {
|
||||
throw new Error("Cross-signing key upload auth canceled");
|
||||
|
@ -390,14 +387,10 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
|
|||
// so let's stash it here, rather than prompting for it twice.
|
||||
const keyCallback = k => this.backupKey = k;
|
||||
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Restore Backup', '', RestoreKeyBackupDialog,
|
||||
{
|
||||
showSummary: false,
|
||||
keyCallback,
|
||||
},
|
||||
null, /* priority = */ false, /* static = */ false,
|
||||
);
|
||||
const { finished } = Modal.createDialog(RestoreKeyBackupDialog, {
|
||||
showSummary: false,
|
||||
keyCallback,
|
||||
}, null, /* priority = */ false, /* static = */ false);
|
||||
|
||||
await finished;
|
||||
const { backupSigStatus } = await this.fetchBackupInfo();
|
||||
|
|
|
@ -43,11 +43,9 @@ export default class NewRecoveryMethodDialog extends React.PureComponent<IProps>
|
|||
};
|
||||
|
||||
private onSetupClick = async (): Promise<void> => {
|
||||
Modal.createTrackedDialog(
|
||||
'Restore Backup', '', RestoreKeyBackupDialog, {
|
||||
onFinished: this.props.onFinished,
|
||||
}, null, /* priority = */ false, /* static = */ true,
|
||||
);
|
||||
Modal.createDialog(RestoreKeyBackupDialog, {
|
||||
onFinished: this.props.onFinished,
|
||||
}, null, /* priority = */ false, /* static = */ true);
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
|
|
|
@ -35,7 +35,7 @@ export default class RecoveryMethodRemovedDialog extends React.PureComponent<IPr
|
|||
|
||||
private onSetupClick = (): void => {
|
||||
this.props.onFinished();
|
||||
Modal.createTrackedDialogAsync("Key Backup", "Key Backup",
|
||||
Modal.createDialogAsync(
|
||||
import("./CreateKeyBackupDialog") as unknown as Promise<ComponentType<{}>>,
|
||||
null, null, /* priority = */ false, /* static = */ true,
|
||||
);
|
||||
|
|
|
@ -30,24 +30,20 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
|||
import { useEventEmitter } from "../../hooks/useEventEmitter";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader";
|
||||
import Analytics from "../../Analytics";
|
||||
import PosthogTrackers from "../../PosthogTrackers";
|
||||
import EmbeddedPage from "./EmbeddedPage";
|
||||
|
||||
const onClickSendDm = (ev: ButtonEvent) => {
|
||||
Analytics.trackEvent('home_page', 'button', 'dm');
|
||||
PosthogTrackers.trackInteraction("WebHomeCreateChatButton", ev);
|
||||
dis.dispatch({ action: 'view_create_chat' });
|
||||
};
|
||||
|
||||
const onClickExplore = (ev: ButtonEvent) => {
|
||||
Analytics.trackEvent('home_page', 'button', 'room_directory');
|
||||
PosthogTrackers.trackInteraction("WebHomeExploreRoomsButton", ev);
|
||||
dis.fire(Action.ViewRoomDirectory);
|
||||
};
|
||||
|
||||
const onClickNewRoom = (ev: ButtonEvent) => {
|
||||
Analytics.trackEvent('home_page', 'button', 'create_room');
|
||||
PosthogTrackers.trackInteraction("WebHomeCreateRoomButton", ev);
|
||||
dis.dispatch({ action: 'view_create_room' });
|
||||
};
|
||||
|
|
|
@ -39,7 +39,6 @@ import 'focus-visible';
|
|||
import 'what-input';
|
||||
|
||||
import PosthogTrackers from '../../PosthogTrackers';
|
||||
import Analytics from "../../Analytics";
|
||||
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
|
||||
import { IMatrixClientCreds, MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
|
@ -73,8 +72,7 @@ import LoggedInView from './LoggedInView';
|
|||
import { Action } from "../../dispatcher/actions";
|
||||
import {
|
||||
hideToast as hideAnalyticsToast,
|
||||
showAnonymousAnalyticsOptInToast,
|
||||
showPseudonymousAnalyticsOptInToast,
|
||||
showToast as showAnalyticsToast,
|
||||
} from "../../toasts/AnalyticsToast";
|
||||
import { showToast as showNotificationsToast } from "../../toasts/DesktopNotificationsToast";
|
||||
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
||||
|
@ -344,10 +342,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
if (SettingsStore.getValue("pseudonymousAnalyticsOptIn")) {
|
||||
Analytics.enable();
|
||||
}
|
||||
|
||||
initSentry(SdkConfig.get("sentry"));
|
||||
}
|
||||
|
||||
|
@ -406,7 +400,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.shouldTrackPageChange(prevState, this.state)) {
|
||||
const durationMs = this.stopPageChangeTimer();
|
||||
Analytics.trackPageChange(durationMs);
|
||||
PosthogTrackers.instance.trackPageChange(this.state.view, this.state.page_type, durationMs);
|
||||
}
|
||||
if (this.focusComposer) {
|
||||
|
@ -625,7 +618,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.copyRoom(payload.room_id);
|
||||
break;
|
||||
case 'reject_invite':
|
||||
Modal.createTrackedDialog('Reject invitation', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t('Reject invitation'),
|
||||
description: _t('Are you sure you want to reject the invitation?'),
|
||||
onFinished: (confirm) => {
|
||||
|
@ -640,7 +633,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}, (err) => {
|
||||
modal.close();
|
||||
Modal.createTrackedDialog('Failed to reject invitation', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to reject invitation'),
|
||||
description: err.toString(),
|
||||
});
|
||||
|
@ -684,7 +677,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
break;
|
||||
case Action.ViewUserSettings: {
|
||||
const tabPayload = payload as OpenToTabPayload;
|
||||
Modal.createTrackedDialog('User settings', '', UserSettingsDialog,
|
||||
Modal.createDialog(UserSettingsDialog,
|
||||
{ initialTabId: tabPayload.initialTabId },
|
||||
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||
|
||||
|
@ -699,7 +692,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.viewSomethingBehindModal();
|
||||
break;
|
||||
case Action.ViewRoomDirectory: {
|
||||
Modal.createTrackedDialog('Room directory', '', RoomDirectory, {
|
||||
Modal.createDialog(RoomDirectory, {
|
||||
initialText: payload.initialText,
|
||||
}, 'mx_RoomDirectory_dialogWrapper', false, true);
|
||||
|
||||
|
@ -756,7 +749,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
break;
|
||||
case Action.OpenDialPad:
|
||||
Modal.createTrackedDialog('Dial pad', '', DialPadModal, {}, "mx_Dialog_dialPadWrapper");
|
||||
Modal.createDialog(DialPadModal, {}, "mx_Dialog_dialPadWrapper");
|
||||
break;
|
||||
case Action.OnLoggedIn:
|
||||
if (
|
||||
|
@ -801,19 +794,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
hideToSRUsers: false,
|
||||
});
|
||||
break;
|
||||
case Action.AnonymousAnalyticsAccept:
|
||||
hideAnalyticsToast();
|
||||
SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, true);
|
||||
SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false);
|
||||
if (Analytics.canEnable()) {
|
||||
Analytics.enable();
|
||||
}
|
||||
break;
|
||||
case Action.AnonymousAnalyticsReject:
|
||||
hideAnalyticsToast();
|
||||
SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, false);
|
||||
SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false);
|
||||
break;
|
||||
case Action.PseudonymousAnalyticsAccept:
|
||||
hideAnalyticsToast();
|
||||
SettingsStore.setValue("pseudonymousAnalyticsOptIn", null, SettingLevel.ACCOUNT, true);
|
||||
|
@ -1009,7 +989,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
private async createRoom(defaultPublic = false, defaultName?: string, type?: RoomType) {
|
||||
const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog, {
|
||||
const modal = Modal.createDialog(CreateRoomDialog, {
|
||||
type,
|
||||
defaultPublic,
|
||||
defaultName,
|
||||
|
@ -1112,7 +1092,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
const warnings = this.leaveRoomWarnings(roomId);
|
||||
|
||||
const isSpace = roomToLeave?.isSpaceRoom();
|
||||
Modal.createTrackedDialog(isSpace ? "Leave space" : "Leave room", '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: isSpace ? _t("Leave space") : _t("Leave room"),
|
||||
description: (
|
||||
<span>
|
||||
|
@ -1156,7 +1136,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
RoomListStore.instance.manualRoomUpdate(room, RoomUpdateCause.RoomRemoved);
|
||||
}).catch((err) => {
|
||||
const errCode = err.errcode || _td("unknown error code");
|
||||
Modal.createTrackedDialog("Failed to forget room", '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to forget room %(errCode)s", { errCode }),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -1167,7 +1147,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
const roomLink = makeRoomPermalink(roomId);
|
||||
const success = await copyPlaintext(roomLink);
|
||||
if (!success) {
|
||||
Modal.createTrackedDialog("Unable to copy room link", "", ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to copy room link"),
|
||||
description: _t("Unable to copy a link to the room to the clipboard."),
|
||||
});
|
||||
|
@ -1271,8 +1251,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
if (PosthogAnalytics.instance.isEnabled() && SettingsStore.isLevelSupported(SettingLevel.ACCOUNT)) {
|
||||
this.initPosthogAnalyticsToast();
|
||||
} else if (Analytics.canEnable() && SettingsStore.getValue("showCookieBar")) {
|
||||
showAnonymousAnalyticsOptInToast();
|
||||
}
|
||||
|
||||
if (SdkConfig.get("mobile_guide_toast")) {
|
||||
|
@ -1282,14 +1260,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private showPosthogToast(analyticsOptIn: boolean) {
|
||||
showPseudonymousAnalyticsOptInToast(analyticsOptIn);
|
||||
}
|
||||
|
||||
private initPosthogAnalyticsToast() {
|
||||
// Show the analytics toast if necessary
|
||||
if (SettingsStore.getValue("pseudonymousAnalyticsOptIn") === null) {
|
||||
this.showPosthogToast(SettingsStore.getValue("analyticsOptIn", null, true));
|
||||
showAnalyticsToast();
|
||||
}
|
||||
|
||||
// Listen to changes in settings and show the toast if appropriate - this is necessary because account
|
||||
|
@ -1298,7 +1272,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
SettingsStore.watchSetting("pseudonymousAnalyticsOptIn", null,
|
||||
(originalSettingName, changedInRoomId, atLevel, newValueAtLevel, newValue) => {
|
||||
if (newValue === null) {
|
||||
this.showPosthogToast(SettingsStore.getValue("analyticsOptIn", null, true));
|
||||
showAnalyticsToast();
|
||||
} else {
|
||||
// It's possible for the value to change if a cached sync loads at page load, but then network
|
||||
// sync contains a new value of the flag with it set to false (e.g. another device set it since last
|
||||
|
@ -1478,7 +1452,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
return;
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Signed out', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Signed Out'),
|
||||
description: _t('For security, this session has been signed out. Please sign in again.'),
|
||||
});
|
||||
|
@ -1488,7 +1462,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
});
|
||||
cli.on(HttpApiEvent.NoConsent, function(message, consentUri) {
|
||||
Modal.createTrackedDialog('No Consent Dialog', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t('Terms and Conditions'),
|
||||
description: <div>
|
||||
<p> { _t(
|
||||
|
@ -1535,7 +1509,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
cli.on(CryptoEvent.Warning, (type) => {
|
||||
switch (type) {
|
||||
case 'CRYPTO_WARNING_OLD_VERSION_DETECTED':
|
||||
Modal.createTrackedDialog('Crypto migrated', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Old cryptography data detected'),
|
||||
description: _t(
|
||||
"Data from an older version of %(brand)s has been detected. " +
|
||||
|
@ -1569,14 +1543,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
if (haveNewVersion) {
|
||||
Modal.createTrackedDialogAsync('New Recovery Method', 'New Recovery Method',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../async-components/views/dialogs/security/NewRecoveryMethodDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
{ newVersionInfo },
|
||||
);
|
||||
} else {
|
||||
Modal.createTrackedDialogAsync('Recovery Method Removed', 'Recovery Method Removed',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../async-components/views/dialogs/security/RecoveryMethodRemovedDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
@ -1585,16 +1559,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
|
||||
cli.on(CryptoEvent.KeySignatureUploadFailure, (failures, source, continuation) => {
|
||||
Modal.createTrackedDialog(
|
||||
'Failed to upload key signatures',
|
||||
'Failed to upload key signatures',
|
||||
Modal.createDialog(
|
||||
KeySignatureUploadFailedDialog,
|
||||
{ failures, source, continuation });
|
||||
});
|
||||
|
||||
cli.on(CryptoEvent.VerificationRequest, request => {
|
||||
if (request.verifier) {
|
||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||
Modal.createDialog(IncomingSasDialog, {
|
||||
verifier: request.verifier,
|
||||
}, null, /* priority = */ false, /* static = */ true);
|
||||
} else if (request.pending) {
|
||||
|
|
|
@ -27,7 +27,6 @@ import Modal from "../../Modal";
|
|||
import { _t } from '../../languageHandler';
|
||||
import SdkConfig from '../../SdkConfig';
|
||||
import { instanceForInstanceId, protocolNameForInstanceId, ALL_ROOMS, Protocols } from '../../utils/DirectoryUtils';
|
||||
import Analytics from '../../Analytics';
|
||||
import NetworkDropdown from "../views/directory/NetworkDropdown";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { IDialogProps } from "../views/dialogs/IDialogProps";
|
||||
|
@ -47,10 +46,6 @@ import { GenericError } from "../../utils/error";
|
|||
const LAST_SERVER_KEY = "mx_last_room_directory_server";
|
||||
const LAST_INSTANCE_KEY = "mx_last_room_directory_instance";
|
||||
|
||||
function track(action: string) {
|
||||
Analytics.trackEvent('RoomDirectory', action);
|
||||
}
|
||||
|
||||
interface IProps extends IDialogProps {
|
||||
initialText?: string;
|
||||
}
|
||||
|
@ -121,7 +116,6 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
// thing you see when loading the client!
|
||||
return;
|
||||
}
|
||||
track('Failed to get protocol list from homeserver');
|
||||
const brand = SdkConfig.get().brand;
|
||||
this.setState({
|
||||
error: _t(
|
||||
|
@ -225,7 +219,6 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
logger.error("Failed to get publicRooms: %s", JSON.stringify(err));
|
||||
track('Failed to get public room list');
|
||||
const brand = SdkConfig.get().brand;
|
||||
this.setState({
|
||||
loading: false,
|
||||
|
@ -255,7 +248,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
desc = _t('Remove %(name)s from the directory?', { name: name });
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Remove from Directory', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t('Remove from Directory'),
|
||||
description: desc,
|
||||
onFinished: (shouldDelete: boolean) => {
|
||||
|
@ -275,7 +268,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
modal.close();
|
||||
this.refreshRoomList();
|
||||
logger.error("Failed to " + step + ": " + err);
|
||||
Modal.createTrackedDialog('Remove from Directory Error', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Error'),
|
||||
description: (err && err.message)
|
||||
? err.message
|
||||
|
@ -360,7 +353,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
|
|||
});
|
||||
} catch (e) {
|
||||
if (e instanceof GenericError) {
|
||||
Modal.createTrackedDialog(e.message, '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: e.message,
|
||||
description: e.description,
|
||||
});
|
||||
|
|
|
@ -104,7 +104,7 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
|
|||
};
|
||||
|
||||
private openSpotlight() {
|
||||
Modal.createTrackedDialog("Spotlight", "", SpotlightDialog, {}, "mx_SpotlightDialog_wrapper", false, true);
|
||||
Modal.createDialog(SpotlightDialog, {}, "mx_SpotlightDialog_wrapper", false, true);
|
||||
}
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
|
|
|
@ -1397,7 +1397,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
}, (error) => {
|
||||
logger.error("Search failed", error);
|
||||
Modal.createTrackedDialog('Search failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Search failed"),
|
||||
description: ((error && error.message) ? error.message :
|
||||
_t("Server may be unavailable, overloaded, or search timed out :(")),
|
||||
|
@ -1522,7 +1522,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
logger.error("Failed to reject invite: %s", error);
|
||||
|
||||
const msg = error.message ? error.message : JSON.stringify(error);
|
||||
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to reject invite"),
|
||||
description: msg,
|
||||
});
|
||||
|
@ -1555,7 +1555,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
logger.error("Failed to reject invite: %s", error);
|
||||
|
||||
const msg = error.message ? error.message : JSON.stringify(error);
|
||||
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to reject invite"),
|
||||
description: msg,
|
||||
});
|
||||
|
|
|
@ -234,7 +234,7 @@ const ThreadPanel: React.FC<IProps> = ({
|
|||
}, [timelineSet, timelinePanel]);
|
||||
|
||||
const openFeedback = SdkConfig.get().bug_report_endpoint_url ? () => {
|
||||
Modal.createTrackedDialog("Threads Feedback", "feature_thread", BetaFeedbackDialog, {
|
||||
Modal.createDialog(BetaFeedbackDialog, {
|
||||
featureId: "feature_thread",
|
||||
});
|
||||
} : null;
|
||||
|
|
|
@ -1353,7 +1353,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Failed to load timeline position', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to load timeline position"),
|
||||
description,
|
||||
onFinished,
|
||||
|
|
|
@ -229,7 +229,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
Modal.createTrackedDialog('Feedback Dialog', '', FeedbackDialog);
|
||||
Modal.createDialog(FeedbackDialog);
|
||||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
|
@ -242,7 +242,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
// log out without user prompt if they have no local megolm sessions
|
||||
defaultDispatcher.dispatch({ action: 'logout' });
|
||||
} else {
|
||||
Modal.createTrackedDialog('Logout from LeftPanel', '', LogoutDialog);
|
||||
Modal.createDialog(LogoutDialog);
|
||||
}
|
||||
|
||||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
|
|
|
@ -70,7 +70,7 @@ export default class UserView extends React.Component<IProps, IState> {
|
|||
try {
|
||||
profileInfo = await cli.getProfileInfo(this.props.userId);
|
||||
} catch (err) {
|
||||
Modal.createTrackedDialog(_t('Could not load user profile'), '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Could not load user profile'),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
|
|
@ -199,7 +199,7 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
if (this.state.logoutDevices) {
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>('Forgot Password Warning', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
|
||||
title: _t('Warning!'),
|
||||
description:
|
||||
<div>
|
||||
|
@ -271,7 +271,7 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
public showErrorDialog(description: string, title?: string) {
|
||||
Modal.createTrackedDialog('Forgot Password Error', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title,
|
||||
description,
|
||||
});
|
||||
|
|
|
@ -98,7 +98,7 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
|||
// We need to call onFinished now to close this dialog, and
|
||||
// again later to signal that the verification is complete.
|
||||
this.props.onFinished();
|
||||
Modal.createTrackedDialog('New Session Verification', 'Starting dialog', VerificationRequestDialog, {
|
||||
Modal.createDialog(VerificationRequestDialog, {
|
||||
verificationRequestPromise: requestPromise,
|
||||
member: cli.getUser(userId),
|
||||
onFinished: async () => {
|
||||
|
|
|
@ -101,7 +101,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private onClearAll = () => {
|
||||
Modal.createTrackedDialog('Clear Data', 'Soft Logout', ConfirmWipeDeviceDialog, {
|
||||
Modal.createDialog(ConfirmWipeDeviceDialog, {
|
||||
onFinished: (wipeData) => {
|
||||
if (!wipeData) return;
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
|
|||
|
||||
if (this.state.email === '') {
|
||||
if (this.showEmail()) {
|
||||
Modal.createTrackedDialog("Email prompt dialog", '', RegistrationEmailPromptDialog, {
|
||||
Modal.createDialog(RegistrationEmailPromptDialog, {
|
||||
onFinished: async (confirmed: boolean, email?: string) => {
|
||||
if (confirmed) {
|
||||
this.setState({
|
||||
|
|
|
@ -91,7 +91,7 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
|
|||
if (value && feedbackLabel && feedbackSubheading && SdkConfig.get().bug_report_endpoint_url) {
|
||||
feedbackButton = <AccessibleButton
|
||||
onClick={() => {
|
||||
Modal.createTrackedDialog("Beta Feedback", featureId, BetaFeedbackDialog, { featureId });
|
||||
Modal.createDialog(BetaFeedbackDialog, { featureId });
|
||||
}}
|
||||
kind="primary"
|
||||
>
|
||||
|
|
|
@ -173,7 +173,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
};
|
||||
|
||||
private onViewSourceClick = (): void => {
|
||||
Modal.createTrackedDialog('View Event Source', '', ViewSource, {
|
||||
Modal.createDialog(ViewSource, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
}, 'mx_Dialog_viewsource');
|
||||
this.closeMenu();
|
||||
|
@ -238,7 +238,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
|
||||
private onShareClick = (e: React.MouseEvent): void => {
|
||||
e.preventDefault();
|
||||
Modal.createTrackedDialog('share room message dialog', '', ShareDialog, {
|
||||
Modal.createDialog(ShareDialog, {
|
||||
target: this.props.mxEvent,
|
||||
permalinkCreator: this.props.permalinkCreator,
|
||||
});
|
||||
|
@ -286,7 +286,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
|||
|
||||
private onEndPollClick = (): void => {
|
||||
const matrixClient = MatrixClientPeg.get();
|
||||
Modal.createTrackedDialog('End Poll', '', EndPollDialog, {
|
||||
Modal.createDialog(EndPollDialog, {
|
||||
matrixClient,
|
||||
event: this.props.mxEvent,
|
||||
getRelationsForEvent: this.props.getRelationsForEvent,
|
||||
|
|
|
@ -296,7 +296,7 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => {
|
|||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
Modal.createTrackedDialog('Export room dialog', '', ExportDialog, { room });
|
||||
Modal.createDialog(ExportDialog, { room });
|
||||
onFinished();
|
||||
}}
|
||||
label={_t("Export chat")}
|
||||
|
|
|
@ -69,7 +69,7 @@ const WidgetContextMenu: React.FC<IProps> = ({
|
|||
logger.error("Failed to start livestream", err);
|
||||
// XXX: won't i18n well, but looks like widget api only support 'message'?
|
||||
const message = err.message || _t("Unable to start audio streaming.");
|
||||
Modal.createTrackedDialog('WidgetContext Menu', 'Livestream failed', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to start livestream'),
|
||||
description: message,
|
||||
});
|
||||
|
@ -134,7 +134,7 @@ const WidgetContextMenu: React.FC<IProps> = ({
|
|||
onDeleteClick();
|
||||
} else {
|
||||
// Show delete confirmation dialog
|
||||
Modal.createTrackedDialog('Delete Widget', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Delete Widget"),
|
||||
description: _t(
|
||||
"Deleting a widget removes it for all users in this room." +
|
||||
|
|
|
@ -15,14 +15,13 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { Optional } from "matrix-events-sdk";
|
||||
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
import Modal from "../../../Modal";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import { SnakedObject } from "../../../utils/SnakedObject";
|
||||
import { getPolicyUrl } from "../../../toasts/AnalyticsToast";
|
||||
|
||||
export enum ButtonClicked {
|
||||
Primary,
|
||||
|
@ -98,19 +97,13 @@ const AnalyticsLearnMoreDialog: React.FC<IProps> = ({
|
|||
};
|
||||
|
||||
export const showDialog = (props: Omit<IProps, "cookiePolicyUrl" | "analyticsOwner">): void => {
|
||||
const piwikConfig = SdkConfig.get("piwik");
|
||||
let privacyPolicyUrl: Optional<string>;
|
||||
if (piwikConfig && typeof piwikConfig === "object") {
|
||||
privacyPolicyUrl = (new SnakedObject(piwikConfig)).get("policy_url");
|
||||
}
|
||||
const privacyPolicyUrl = getPolicyUrl();
|
||||
const analyticsOwner = SdkConfig.get("analytics_owner") ?? SdkConfig.get("brand");
|
||||
Modal.createTrackedDialog(
|
||||
"Analytics Learn More",
|
||||
"",
|
||||
AnalyticsLearnMoreDialog,
|
||||
{ privacyPolicyUrl, analyticsOwner, ...props },
|
||||
"mx_AnalyticsLearnMoreDialog_wrapper",
|
||||
);
|
||||
Modal.createDialog(AnalyticsLearnMoreDialog, {
|
||||
privacyPolicyUrl,
|
||||
analyticsOwner,
|
||||
...props,
|
||||
}, "mx_AnalyticsLearnMoreDialog_wrapper");
|
||||
};
|
||||
|
||||
export default AnalyticsLearnMoreDialog;
|
||||
|
|
|
@ -110,8 +110,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
|
|||
}).then(() => {
|
||||
if (!this.unmounted) {
|
||||
this.props.onFinished(false);
|
||||
// N.B. first param is passed to piwik and so doesn't want i18n
|
||||
Modal.createTrackedDialog('Bug report sent', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t('Logs sent'),
|
||||
description: _t('Thank you!'),
|
||||
hasCancelButton: false,
|
||||
|
|
|
@ -53,7 +53,7 @@ export function createRedactEventDialog({
|
|||
mxEvent: MatrixEvent;
|
||||
onCloseDialog?: () => void;
|
||||
}) {
|
||||
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
|
||||
Modal.createDialog(ConfirmRedactDialog, {
|
||||
onFinished: async (proceed: boolean, reason?: string) => {
|
||||
if (!proceed) return;
|
||||
|
||||
|
@ -73,7 +73,7 @@ export function createRedactEventDialog({
|
|||
// detached queue and we show the room status bar to allow retry
|
||||
if (typeof code !== "undefined") {
|
||||
// display error message stating you couldn't delete this.
|
||||
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Error'),
|
||||
description: _t('You cannot delete this message. (%(code)s)', { code }),
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
|
|||
const brand = SdkConfig.get().brand;
|
||||
|
||||
const _onLogoutClicked = () => {
|
||||
Modal.createTrackedDialog('Logout e2e db too new', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Sign out"),
|
||||
description: _t(
|
||||
"To avoid losing your chat history, you must export your room keys " +
|
||||
|
|
|
@ -19,7 +19,6 @@ import React from 'react';
|
|||
import { AuthType, IAuthData } from 'matrix-js-sdk/src/interactive-auth';
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import Analytics from '../../../Analytics';
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import InteractiveAuth, { ERROR_USER_CANCELLED, InteractiveAuthCallback } from "../../structures/InteractiveAuth";
|
||||
|
@ -122,7 +121,6 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
|
|||
// this isn't done.
|
||||
MatrixClientPeg.get().deactivateAccount(auth, this.state.shouldErase).then(r => {
|
||||
// Deactivation worked - logout & close this dialog
|
||||
Analytics.trackEvent('Account', 'Deactivate Account');
|
||||
defaultDispatcher.fire(Action.TriggerLogout);
|
||||
this.props.onFinished(true);
|
||||
}).catch(e => {
|
||||
|
|
|
@ -62,16 +62,11 @@ export default class EndPollDialog extends React.Component<IProps> {
|
|||
this.props.event.getRoomId(), endEvent.type, endEvent.content,
|
||||
).catch((e: any) => {
|
||||
console.error("Failed to submit poll response event:", e);
|
||||
Modal.createTrackedDialog(
|
||||
'Failed to end poll',
|
||||
'',
|
||||
ErrorDialog,
|
||||
{
|
||||
title: _t("Failed to end poll"),
|
||||
description: _t(
|
||||
"Sorry, the poll did not end. Please try again."),
|
||||
},
|
||||
);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to end poll"),
|
||||
description: _t(
|
||||
"Sorry, the poll did not end. Please try again."),
|
||||
});
|
||||
});
|
||||
}
|
||||
this.props.onFinished(endPoll);
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
/*
|
||||
* Usage:
|
||||
* Modal.createTrackedDialog('An Identifier', 'some detail', ErrorDialog, {
|
||||
* Modal.createDialog(ErrorDialog, {
|
||||
* title: "some text", (default: "Error")
|
||||
* description: "some more text",
|
||||
* button: "Button Text",
|
||||
|
|
|
@ -47,7 +47,7 @@ const FeedbackDialog: React.FC<IProps> = (props: IProps) => {
|
|||
|
||||
const onDebugLogsLinkClick = (): void => {
|
||||
props.onFinished();
|
||||
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
|
||||
Modal.createDialog(BugReportDialog, {});
|
||||
};
|
||||
|
||||
const rageshakeUrl = SdkConfig.get().bug_report_endpoint_url;
|
||||
|
@ -58,7 +58,7 @@ const FeedbackDialog: React.FC<IProps> = (props: IProps) => {
|
|||
submitFeedback(rageshakeUrl, "feedback", comment, canContact);
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Feedback sent', '', InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: _t('Feedback sent'),
|
||||
description: _t('Thank you!'),
|
||||
});
|
||||
|
|
|
@ -50,7 +50,7 @@ const GenericFeatureFeedbackDialog: React.FC<IProps> = ({
|
|||
submitFeedback(SdkConfig.get().bug_report_endpoint_url, rageshakeLabel, comment, canContact, rageshakeData);
|
||||
onFinished(true);
|
||||
|
||||
Modal.createTrackedDialog("Feedback Sent", rageshakeLabel, InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title,
|
||||
description: _t("Feedback sent! Thanks, we appreciate it!"),
|
||||
button: _t("Close"),
|
||||
|
|
|
@ -904,7 +904,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
|||
if (this.unmounted) return;
|
||||
|
||||
if (failed.length > 0) {
|
||||
Modal.createTrackedDialog('Invite Paste Fail', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t('Failed to find the following users'),
|
||||
description: _t(
|
||||
"The following users might not exist or are invalid, and cannot be invited: %(csvNames)s",
|
||||
|
|
|
@ -80,7 +80,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private onExportE2eKeysClicked = (): void => {
|
||||
Modal.createTrackedDialogAsync('Export E2E Keys', '',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../../async-components/views/dialogs/security/ExportE2eKeysDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
@ -103,12 +103,9 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
|
|||
// A key backup exists for this account, but the creating device is not
|
||||
// verified, so restore the backup which will give us the keys from it and
|
||||
// allow us to trust it (ie. upload keys to it)
|
||||
Modal.createTrackedDialog(
|
||||
'Restore Backup', '', RestoreKeyBackupDialog, null, null,
|
||||
/* priority = */ false, /* static = */ true,
|
||||
);
|
||||
Modal.createDialog(RestoreKeyBackupDialog, null, null, /* priority = */ false, /* static = */ true);
|
||||
} else {
|
||||
Modal.createTrackedDialogAsync("Key Backup", "Key Backup",
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
"../../../async-components/views/dialogs/security/CreateKeyBackupDialog"
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
|
|
@ -56,7 +56,7 @@ export default class RoomUpgradeDialog extends React.Component<IProps, IState> {
|
|||
upgradeRoom(this.props.room, this.targetVersion, false, false).then(() => {
|
||||
this.props.onFinished(true);
|
||||
}).catch((err) => {
|
||||
Modal.createTrackedDialog('Failed to upgrade room', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to upgrade room"),
|
||||
description: ((err && err.message) ? err.message : _t("The room upgrade could not be completed")),
|
||||
});
|
||||
|
|
|
@ -97,7 +97,7 @@ export default class RoomUpgradeWarningDialog extends React.Component<IProps, IS
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
|
||||
Modal.createDialog(BugReportDialog, {});
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -33,13 +33,13 @@ interface IProps extends IDialogProps {
|
|||
|
||||
export default class SessionRestoreErrorDialog extends React.Component<IProps> {
|
||||
private sendBugReport = (): void => {
|
||||
Modal.createTrackedDialog('Session Restore Error', 'Send Bug Report Dialog', BugReportDialog, {
|
||||
Modal.createDialog(BugReportDialog, {
|
||||
error: this.props.error,
|
||||
});
|
||||
};
|
||||
|
||||
private onClearStorageClick = (): void => {
|
||||
Modal.createTrackedDialog('Session Restore Confirm Logout', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Sign out"),
|
||||
description:
|
||||
<div>{ _t("Sign out and remove encryption keys?") }</div>,
|
||||
|
|
|
@ -64,7 +64,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
private onSubmit = (): void => {
|
||||
const emailAddress = this.state.emailAddress;
|
||||
if (!Email.looksValid(emailAddress)) {
|
||||
Modal.createTrackedDialog('Invalid Email Address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Invalid Email Address"),
|
||||
description: _t("This doesn't appear to be a valid email address"),
|
||||
});
|
||||
|
@ -72,7 +72,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
}
|
||||
this.addThreepid = new AddThreepid();
|
||||
this.addThreepid.addEmailAddress(emailAddress).then(() => {
|
||||
Modal.createTrackedDialog('Verification Pending', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Verification Pending"),
|
||||
description: _t(
|
||||
"Please check your email and click on the link it contains. Once this " +
|
||||
|
@ -84,7 +84,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
}, (err) => {
|
||||
this.setState({ emailBusy: false });
|
||||
logger.error("Unable to add email address " + emailAddress + " " + err);
|
||||
Modal.createTrackedDialog('Unable to add email address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to add email address"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -112,7 +112,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
|
||||
const message = _t("Unable to verify email address.") + " " +
|
||||
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
|
||||
Modal.createTrackedDialog('Verification Pending', '3pid Auth Failed', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Verification Pending"),
|
||||
description: message,
|
||||
button: _t('Continue'),
|
||||
|
@ -120,7 +120,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
|
|||
});
|
||||
} else {
|
||||
logger.error("Unable to verify email address: " + err);
|
||||
Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify email address."),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
|
|
@ -701,7 +701,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
};
|
||||
|
||||
const openFeedback = SdkConfig.get().bug_report_endpoint_url ? () => {
|
||||
Modal.createTrackedDialog("Spotlight Feedback", "feature_spotlight", BetaFeedbackDialog, {
|
||||
Modal.createDialog(BetaFeedbackDialog, {
|
||||
featureId: "feature_spotlight",
|
||||
});
|
||||
} : null;
|
||||
|
|
|
@ -30,7 +30,7 @@ interface IProps extends IDialogProps { }
|
|||
export default class StorageEvictedDialog extends React.Component<IProps> {
|
||||
private sendBugReport = (ev: React.MouseEvent): void => {
|
||||
ev.preventDefault();
|
||||
Modal.createTrackedDialog('Storage evicted', 'Send Bug Report Dialog', BugReportDialog, {});
|
||||
Modal.createDialog(BugReportDialog, {});
|
||||
};
|
||||
|
||||
private onSignOutClick = (): void => {
|
||||
|
|
|
@ -233,14 +233,11 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
|
|||
const cli = MatrixClientPeg.get();
|
||||
await cli.bootstrapCrossSigning({
|
||||
authUploadDeviceSigningKeys: async (makeRequest) => {
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Cross-signing keys dialog', '', InteractiveAuthDialog,
|
||||
{
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: cli,
|
||||
makeRequest,
|
||||
},
|
||||
);
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: cli,
|
||||
makeRequest,
|
||||
});
|
||||
const [confirmed] = await finished;
|
||||
if (!confirmed) {
|
||||
throw new Error("Cross-signing key upload auth canceled");
|
||||
|
|
|
@ -123,18 +123,15 @@ export default class CreateCrossSigningDialog extends React.PureComponent<IProps
|
|||
},
|
||||
};
|
||||
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Cross-signing keys dialog', '', InteractiveAuthDialog,
|
||||
{
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
makeRequest,
|
||||
aestheticsForStagePhases: {
|
||||
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
|
||||
[SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics,
|
||||
},
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
makeRequest,
|
||||
aestheticsForStagePhases: {
|
||||
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
|
||||
[SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics,
|
||||
},
|
||||
);
|
||||
});
|
||||
const [confirmed] = await finished;
|
||||
if (!confirmed) {
|
||||
throw new Error("Cross-signing key upload auth canceled");
|
||||
|
|
|
@ -188,20 +188,16 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s
|
|||
if (removableServers.has(server)) {
|
||||
const onClick = async () => {
|
||||
closeMenu();
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
"Network Dropdown", "Remove server", QuestionDialog,
|
||||
{
|
||||
title: _t("Are you sure?"),
|
||||
description: _t("Are you sure you want to remove <b>%(serverName)s</b>", {
|
||||
serverName: server,
|
||||
}, {
|
||||
b: serverName => <b>{ serverName }</b>,
|
||||
}),
|
||||
button: _t("Remove"),
|
||||
fixedWidth: false,
|
||||
},
|
||||
"mx_NetworkDropdown_dialog",
|
||||
);
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Are you sure?"),
|
||||
description: _t("Are you sure you want to remove <b>%(serverName)s</b>", {
|
||||
serverName: server,
|
||||
}, {
|
||||
b: serverName => <b>{ serverName }</b>,
|
||||
}),
|
||||
button: _t("Remove"),
|
||||
fixedWidth: false,
|
||||
}, "mx_NetworkDropdown_dialog");
|
||||
|
||||
const [ok] = await finished;
|
||||
if (!ok) return;
|
||||
|
@ -242,7 +238,7 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s
|
|||
|
||||
const onClick = async () => {
|
||||
closeMenu();
|
||||
const { finished } = Modal.createTrackedDialog("Network Dropdown", "Add a new server", TextInputDialog, {
|
||||
const { finished } = Modal.createDialog(TextInputDialog, {
|
||||
title: _t("Add a new server"),
|
||||
description: _t("Enter the name of a new server you want to explore."),
|
||||
button: _t("Add"),
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
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 React from 'react';
|
||||
|
||||
import AccessibleButton from './AccessibleButton';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Analytics from '../../../Analytics';
|
||||
import Tooltip from './Tooltip';
|
||||
|
||||
interface IProps {
|
||||
size?: string;
|
||||
tooltip?: boolean;
|
||||
action: string;
|
||||
mouseOverAction?: string;
|
||||
label: string;
|
||||
iconPath?: string;
|
||||
className?: string;
|
||||
children?: JSX.Element;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
showTooltip: boolean;
|
||||
}
|
||||
|
||||
export default class ActionButton extends React.Component<IProps, IState> {
|
||||
static defaultProps: Partial<IProps> = {
|
||||
size: "25",
|
||||
tooltip: false,
|
||||
};
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showTooltip: false,
|
||||
};
|
||||
}
|
||||
|
||||
private onClick = (ev: React.MouseEvent): void => {
|
||||
ev.stopPropagation();
|
||||
Analytics.trackEvent('Action Button', 'click', this.props.action);
|
||||
dis.dispatch({ action: this.props.action });
|
||||
};
|
||||
|
||||
private onMouseEnter = (): void => {
|
||||
this.showTooltip();
|
||||
if (this.props.mouseOverAction) {
|
||||
dis.dispatch({ action: this.props.mouseOverAction });
|
||||
}
|
||||
};
|
||||
|
||||
private showTooltip = (): void => {
|
||||
if (this.props.tooltip) this.setState({ showTooltip: true });
|
||||
};
|
||||
|
||||
private hideTooltip = (): void => {
|
||||
this.setState({ showTooltip: false });
|
||||
};
|
||||
|
||||
render() {
|
||||
let tooltip;
|
||||
if (this.state.showTooltip) {
|
||||
tooltip = <Tooltip className="mx_RoleButton_tooltip" label={this.props.label} />;
|
||||
}
|
||||
|
||||
const icon = this.props.iconPath ?
|
||||
(<img src={this.props.iconPath} width={this.props.size} height={this.props.size} />) :
|
||||
undefined;
|
||||
|
||||
const classNames = ["mx_RoleButton"];
|
||||
if (this.props.className) {
|
||||
classNames.push(this.props.className);
|
||||
}
|
||||
|
||||
return (
|
||||
<AccessibleButton
|
||||
className={classNames.join(" ")}
|
||||
onClick={this.onClick}
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
onMouseLeave={this.hideTooltip}
|
||||
onFocus={this.showTooltip}
|
||||
onBlur={this.hideTooltip}
|
||||
aria-label={this.props.label}
|
||||
>
|
||||
{ icon }
|
||||
{ tooltip }
|
||||
{ this.props.children }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -68,7 +68,7 @@ export default class ErrorBoundary extends React.PureComponent<{}, IState> {
|
|||
};
|
||||
|
||||
private onBugReport = (): void => {
|
||||
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {
|
||||
Modal.createDialog(BugReportDialog, {
|
||||
label: 'react-soft-crash',
|
||||
error: this.state.error,
|
||||
});
|
||||
|
|
|
@ -18,7 +18,6 @@ import classNames from 'classnames';
|
|||
import { EventType } from 'matrix-js-sdk/src/@types/event';
|
||||
import React, { useContext, useRef, useState, MouseEvent } from 'react';
|
||||
|
||||
import Analytics from "../../../Analytics";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import RoomContext from "../../../contexts/RoomContext";
|
||||
import { useTimeout } from "../../../hooks/useTimeout";
|
||||
|
@ -74,7 +73,6 @@ const MiniAvatarUploader: React.FC<IProps> = ({
|
|||
onChange={async (ev) => {
|
||||
if (!ev.target.files?.length) return;
|
||||
setBusy(true);
|
||||
Analytics.trackEvent("mini_avatar", "upload");
|
||||
const file = ev.target.files[0];
|
||||
const uri = await cli.uploadContent(file);
|
||||
await setAvatarUrl(uri);
|
||||
|
|
|
@ -172,25 +172,20 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
|
|||
() => this.props.onFinished(true),
|
||||
).catch(e => {
|
||||
console.error("Failed to post poll:", e);
|
||||
Modal.createTrackedDialog(
|
||||
'Failed to post poll',
|
||||
'',
|
||||
QuestionDialog,
|
||||
{
|
||||
title: _t("Failed to post poll"),
|
||||
description: _t(
|
||||
"Sorry, the poll you tried to create was not posted."),
|
||||
button: _t('Try again'),
|
||||
cancelButton: _t('Cancel'),
|
||||
onFinished: (tryAgain: boolean) => {
|
||||
if (!tryAgain) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.setState({ busy: false, canSubmit: true });
|
||||
}
|
||||
},
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Failed to post poll"),
|
||||
description: _t(
|
||||
"Sorry, the poll you tried to create was not posted."),
|
||||
button: _t('Try again'),
|
||||
cancelButton: _t('Cancel'),
|
||||
onFinished: (tryAgain: boolean) => {
|
||||
if (!tryAgain) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.setState({ busy: false, canSubmit: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ const showPickerDialog = (
|
|||
serverConfig: ValidatedServerConfig,
|
||||
onFinished: (config: ValidatedServerConfig) => void,
|
||||
) => {
|
||||
Modal.createTrackedDialog("Server Picker", "", ServerPickerDialog, { title, serverConfig, onFinished });
|
||||
Modal.createDialog(ServerPickerDialog, { title, serverConfig, onFinished });
|
||||
};
|
||||
|
||||
const onHelpClick = () => {
|
||||
const brand = SdkConfig.get().brand;
|
||||
Modal.createTrackedDialog('Custom Server Dialog', '', InfoDialog, {
|
||||
Modal.createDialog(InfoDialog, {
|
||||
title: _t("Server Options"),
|
||||
description: _t("You can use the custom server options to sign into other Matrix servers by specifying " +
|
||||
"a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on " +
|
||||
|
|
|
@ -183,15 +183,10 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
|||
// pin drop location without permissions is ok
|
||||
if (isSharingOwnLocation(this.props.shareType)) {
|
||||
this.props.onFinished();
|
||||
Modal.createTrackedDialog(
|
||||
'Could not fetch location',
|
||||
'',
|
||||
ErrorDialog,
|
||||
{
|
||||
title: _t("Could not fetch location"),
|
||||
description: positionFailureMessage(e.code),
|
||||
},
|
||||
);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Could not fetch location"),
|
||||
description: positionFailureMessage(e.code),
|
||||
});
|
||||
}
|
||||
|
||||
if (this.geolocate) {
|
||||
|
|
|
@ -49,7 +49,6 @@ const handleShareError = (error: Error, openMenu: () => void, shareType: Locatio
|
|||
"We couldn't start sharing your live location" :
|
||||
"We couldn't send your location";
|
||||
logger.error(errorMessage, error);
|
||||
const analyticsAction = errorMessage;
|
||||
const params = {
|
||||
title: _t("We couldn't send your location"),
|
||||
description: _t("%(brand)s could not send your location. Please try again later.", {
|
||||
|
@ -63,7 +62,7 @@ const handleShareError = (error: Error, openMenu: () => void, shareType: Locatio
|
|||
}
|
||||
},
|
||||
};
|
||||
Modal.createTrackedDialog(analyticsAction, '', QuestionDialog, params);
|
||||
Modal.createDialog(QuestionDialog, params);
|
||||
};
|
||||
|
||||
export const shareLiveLocation = (
|
||||
|
|
|
@ -154,7 +154,7 @@ export default class DateSeparator extends React.Component<IProps, IState> {
|
|||
// detached queue and we show the room status bar to allow retry
|
||||
if (typeof code !== "undefined") {
|
||||
// display error message stating you couldn't delete this.
|
||||
Modal.createTrackedDialog('Unable to find event at that date', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Error'),
|
||||
description: _t('Unable to find event at that date. (%(code)s)', { code }),
|
||||
});
|
||||
|
|
|
@ -75,13 +75,13 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
|
|||
const event = this.props.mxEvent;
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
Modal.createTrackedDialog('Confirm Redact Dialog', 'Edit history', ConfirmAndWaitRedactDialog, {
|
||||
Modal.createDialog(ConfirmAndWaitRedactDialog, {
|
||||
redact: () => cli.redactEvent(event.getRoomId(), event.getId()),
|
||||
}, 'mx_Dialog_confirmredact');
|
||||
};
|
||||
|
||||
private onViewSourceClick = (): void => {
|
||||
Modal.createTrackedDialog('View Event Source', 'Edit history', ViewSource, {
|
||||
Modal.createDialog(ViewSource, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
}, 'mx_Dialog_viewsource');
|
||||
};
|
||||
|
|
|
@ -106,9 +106,7 @@ const MBeaconBody: React.FC<IBodyProps> = React.forwardRef(({ mxEvent }, ref) =>
|
|||
if (displayStatus !== BeaconDisplayStatus.Active) {
|
||||
return;
|
||||
}
|
||||
Modal.createTrackedDialog(
|
||||
'Beacon View',
|
||||
'',
|
||||
Modal.createDialog(
|
||||
BeaconViewDialog,
|
||||
{
|
||||
roomId: mxEvent.getRoomId(),
|
||||
|
|
|
@ -172,7 +172,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
|
|||
});
|
||||
} catch (err) {
|
||||
logger.warn("Unable to decrypt attachment: ", err);
|
||||
Modal.createTrackedDialog('Error decrypting attachment', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
description: _t("Error decrypting attachment"),
|
||||
});
|
||||
|
|
|
@ -57,9 +57,7 @@ export default class MLocationBody extends React.Component<IBodyProps, IState> {
|
|||
}
|
||||
|
||||
private onClick = () => {
|
||||
Modal.createTrackedDialog(
|
||||
'Location View',
|
||||
'',
|
||||
Modal.createDialog(
|
||||
LocationViewDialog,
|
||||
{
|
||||
matrixClient: this.context,
|
||||
|
|
|
@ -181,9 +181,7 @@ export function pollAlreadyHasVotes(mxEvent: MatrixEvent, getRelationsForEvent?:
|
|||
|
||||
export function launchPollEditor(mxEvent: MatrixEvent, getRelationsForEvent?: GetRelationsForEvent): void {
|
||||
if (pollAlreadyHasVotes(mxEvent, getRelationsForEvent)) {
|
||||
Modal.createTrackedDialog(
|
||||
'Not allowed to edit poll',
|
||||
'',
|
||||
Modal.createDialog(
|
||||
ErrorDialog,
|
||||
{
|
||||
title: _t("Can't edit poll"),
|
||||
|
@ -193,9 +191,7 @@ export function launchPollEditor(mxEvent: MatrixEvent, getRelationsForEvent?: Ge
|
|||
},
|
||||
);
|
||||
} else {
|
||||
Modal.createTrackedDialog(
|
||||
'Polls',
|
||||
'create',
|
||||
Modal.createDialog(
|
||||
PollCreateDialog,
|
||||
{
|
||||
room: MatrixClientPeg.get().getRoom(mxEvent.getRoomId()),
|
||||
|
@ -312,9 +308,7 @@ export default class MPollBody extends React.Component<IBodyProps, IState> {
|
|||
).catch((e: any) => {
|
||||
console.error("Failed to submit poll response event:", e);
|
||||
|
||||
Modal.createTrackedDialog(
|
||||
'Vote not registered',
|
||||
'',
|
||||
Modal.createDialog(
|
||||
ErrorDialog,
|
||||
{
|
||||
title: _t("Vote not registered"),
|
||||
|
|
|
@ -468,7 +468,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
|||
scalarClient.connect().then(() => {
|
||||
const completeUrl = scalarClient.getStarterLink(starterLink);
|
||||
const integrationsUrl = integrationManager.uiUrl;
|
||||
Modal.createTrackedDialog('Add an integration', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Add an Integration"),
|
||||
description:
|
||||
<div>
|
||||
|
|
|
@ -52,14 +52,14 @@ export default class TileErrorBoundary extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private onBugReport = (): void => {
|
||||
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {
|
||||
Modal.createDialog(BugReportDialog, {
|
||||
label: 'react-soft-crash-tile',
|
||||
error: this.state.error,
|
||||
});
|
||||
};
|
||||
|
||||
private onViewSource = (): void => {
|
||||
Modal.createTrackedDialog('View Event Source', 'from crash', ViewSource, {
|
||||
Modal.createDialog(ViewSource, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
}, 'mx_Dialog_viewsource');
|
||||
};
|
||||
|
|
|
@ -84,7 +84,7 @@ const EncryptionPanel: React.FC<IProps> = (props: IProps) => {
|
|||
const changeHandler = useCallback(() => {
|
||||
// handle transitions -> cancelled for mismatches which fire a modal instead of showing a card
|
||||
if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) {
|
||||
Modal.createTrackedDialog("Verification failed", "insecure", ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
headerImage: require("../../../../res/img/e2e/warning.svg").default,
|
||||
title: _t("Your messages are not secure"),
|
||||
description: <div>
|
||||
|
|
|
@ -21,7 +21,6 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Analytics from '../../../Analytics';
|
||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||
|
||||
|
@ -31,8 +30,6 @@ interface IProps {
|
|||
isUnread?: boolean;
|
||||
// click handler
|
||||
onClick: (ev: ButtonEvent) => void;
|
||||
// The parameters to track the click event
|
||||
analytics: Parameters<typeof Analytics.trackEvent>;
|
||||
|
||||
// Button name
|
||||
name: string;
|
||||
|
@ -42,14 +39,8 @@ interface IProps {
|
|||
|
||||
// TODO: replace this, the composer buttons and the right panel buttons with a unified representation
|
||||
export default class HeaderButton extends React.Component<IProps> {
|
||||
private onClick = (ev: ButtonEvent) => {
|
||||
Analytics.trackEvent(...this.props.analytics);
|
||||
this.props.onClick(ev);
|
||||
};
|
||||
|
||||
public render() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { isHighlighted, isUnread = false, onClick, analytics, name, title, ...props } = this.props;
|
||||
const { isHighlighted, isUnread = false, onClick, name, title, ...props } = this.props;
|
||||
|
||||
const classes = classNames({
|
||||
mx_RightPanel_headerButton: true,
|
||||
|
@ -64,7 +55,7 @@ export default class HeaderButton extends React.Component<IProps> {
|
|||
role="tab"
|
||||
title={title}
|
||||
className={classes}
|
||||
onClick={this.onClick}
|
||||
onClick={onClick}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,6 @@ const PinnedMessagesHeaderButton = ({ room, isHighlighted, onClick }: IHeaderBut
|
|||
isHighlighted={isHighlighted}
|
||||
isUnread={!!unreadIndicator}
|
||||
onClick={onClick}
|
||||
analytics={["Right Panel", "Pinned Messages Button", "click"]}
|
||||
>
|
||||
{ unreadIndicator }
|
||||
</HeaderButton>;
|
||||
|
@ -115,7 +114,6 @@ const TimelineCardHeaderButton = ({ room, isHighlighted, onClick }: IHeaderButto
|
|||
title={_t("Chat")}
|
||||
isHighlighted={isHighlighted}
|
||||
onClick={onClick}
|
||||
analytics={["Right Panel", "Timeline Panel Button", "click"]}
|
||||
>
|
||||
{ unreadIndicator }
|
||||
</HeaderButton>;
|
||||
|
@ -244,7 +242,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
|
|||
onClick={this.onThreadsPanelClicked}
|
||||
isHighlighted={this.isPhase(RoomHeaderButtons.THREAD_PHASES)}
|
||||
isUnread={this.threadNotificationState.color > 0}
|
||||
analytics={['Right Panel', 'Threads List Button', 'click']}>
|
||||
>
|
||||
<UnreadIndicator color={this.threadNotificationState.color} />
|
||||
</HeaderButton>
|
||||
: null,
|
||||
|
@ -256,7 +254,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
|
|||
title={_t('Notifications')}
|
||||
isHighlighted={this.isPhase(RightPanelPhases.NotificationPanel)}
|
||||
onClick={this.onNotificationsClicked}
|
||||
analytics={['Right Panel', 'Notification List Button', 'click']} />,
|
||||
/>,
|
||||
);
|
||||
rightPanelPhaseButtons.set(RightPanelPhases.RoomSummary,
|
||||
<HeaderButton
|
||||
|
@ -265,7 +263,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
|
|||
title={_t('Room Info')}
|
||||
isHighlighted={this.isPhase(ROOM_INFO_PHASES)}
|
||||
onClick={this.onRoomSummaryClicked}
|
||||
analytics={['Right Panel', 'Room Summary Button', 'click']} />,
|
||||
/>,
|
||||
);
|
||||
|
||||
return <>
|
||||
|
|
|
@ -248,13 +248,13 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
|
|||
const cli = useContext(MatrixClientContext);
|
||||
|
||||
const onShareRoomClick = () => {
|
||||
Modal.createTrackedDialog('share room dialog', '', ShareDialog, {
|
||||
Modal.createDialog(ShareDialog, {
|
||||
target: room,
|
||||
});
|
||||
};
|
||||
|
||||
const onRoomExportClick = async () => {
|
||||
Modal.createTrackedDialog('export room dialog', '', ExportDialog, {
|
||||
Modal.createDialog(ExportDialog, {
|
||||
room,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -365,7 +365,7 @@ const UserOptionsSection: React.FC<{
|
|||
const isMe = member.userId === cli.getUserId();
|
||||
|
||||
const onShareUserClick = () => {
|
||||
Modal.createTrackedDialog('share room member dialog', '', ShareDialog, {
|
||||
Modal.createDialog(ShareDialog, {
|
||||
target: member,
|
||||
});
|
||||
};
|
||||
|
@ -451,7 +451,7 @@ const UserOptionsSection: React.FC<{
|
|||
}
|
||||
});
|
||||
} catch (err) {
|
||||
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to invite'),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -503,7 +503,7 @@ const UserOptionsSection: React.FC<{
|
|||
};
|
||||
|
||||
const warnSelfDemote = async (isSpace: boolean) => {
|
||||
const { finished } = Modal.createTrackedDialog('Demoting Self', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Demote yourself?"),
|
||||
description:
|
||||
<div>
|
||||
|
@ -590,9 +590,7 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit<IBas
|
|||
if (member.membership !== "invite" && member.membership !== "join") return null;
|
||||
|
||||
const onKick = async () => {
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Confirm User Action Dialog',
|
||||
'onKick',
|
||||
const { finished } = Modal.createDialog(
|
||||
room.isSpaceRoom() ? ConfirmSpaceUserActionDialog : ConfirmUserActionDialog,
|
||||
{
|
||||
member,
|
||||
|
@ -632,7 +630,7 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit<IBas
|
|||
logger.log("Kick success");
|
||||
}, function(err) {
|
||||
logger.error("Kick error: " + err);
|
||||
Modal.createTrackedDialog('Failed to kick', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to remove user"),
|
||||
description: ((err && err.message) ? err.message : "Operation failed"),
|
||||
});
|
||||
|
@ -661,7 +659,7 @@ const RedactMessagesButton: React.FC<IBaseProps> = ({ member }) => {
|
|||
const room = cli.getRoom(member.roomId);
|
||||
if (!room) return;
|
||||
|
||||
Modal.createTrackedDialog("Bulk Redact Dialog", "", BulkRedactDialog, {
|
||||
Modal.createDialog(BulkRedactDialog, {
|
||||
matrixClient: cli,
|
||||
room, member,
|
||||
});
|
||||
|
@ -681,9 +679,7 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit<IBa
|
|||
|
||||
const isBanned = member.membership === "ban";
|
||||
const onBanOrUnban = async () => {
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Confirm User Action Dialog',
|
||||
'onBanOrUnban',
|
||||
const { finished } = Modal.createDialog(
|
||||
room.isSpaceRoom() ? ConfirmSpaceUserActionDialog : ConfirmUserActionDialog,
|
||||
{
|
||||
member,
|
||||
|
@ -746,7 +742,7 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit<IBa
|
|||
logger.log("Ban success");
|
||||
}, function(err) {
|
||||
logger.error("Ban error: " + err);
|
||||
Modal.createTrackedDialog('Failed to ban user', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to ban user"),
|
||||
});
|
||||
|
@ -827,7 +823,7 @@ const MuteToggleButton: React.FC<IBaseRoomProps> = ({ member, room, powerLevels,
|
|||
logger.log("Mute toggle success");
|
||||
}, function(err) {
|
||||
logger.error("Mute error: " + err);
|
||||
Modal.createTrackedDialog('Failed to mute user', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to mute user"),
|
||||
});
|
||||
|
@ -1048,7 +1044,7 @@ const PowerLevelEditor: React.FC<{
|
|||
logger.log("Power change success");
|
||||
}, function(err) {
|
||||
logger.error("Failed to change power level " + err);
|
||||
Modal.createTrackedDialog('Failed to change power level', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to change power level"),
|
||||
});
|
||||
|
@ -1065,7 +1061,7 @@ const PowerLevelEditor: React.FC<{
|
|||
const myUserId = cli.getUserId();
|
||||
const myPower = powerLevelEvent.getContent().users[myUserId];
|
||||
if (myPower && parseInt(myPower) <= powerLevel && myUserId !== target) {
|
||||
const { finished } = Modal.createTrackedDialog('Promote to PL100 Warning', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Warning!"),
|
||||
description:
|
||||
<div>
|
||||
|
@ -1214,7 +1210,7 @@ const BasicUserInfo: React.FC<{
|
|||
const roomPermissions = useRoomPermissions(cli, room, member as RoomMember);
|
||||
|
||||
const onSynapseDeactivate = useCallback(async () => {
|
||||
const { finished } = Modal.createTrackedDialog('Synapse User Deactivation', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Deactivate user?"),
|
||||
description:
|
||||
<div>{ _t(
|
||||
|
@ -1234,7 +1230,7 @@ const BasicUserInfo: React.FC<{
|
|||
logger.error("Failed to deactivate user");
|
||||
logger.error(err);
|
||||
|
||||
Modal.createTrackedDialog('Failed to deactivate Synapse user', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Failed to deactivate user'),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
|
|
@ -173,7 +173,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
|||
this.context.sendStateEvent(this.props.roomId, "m.room.canonical_alias",
|
||||
eventContent, "").catch((err) => {
|
||||
logger.error(err);
|
||||
Modal.createTrackedDialog('Error updating main address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error updating main address"),
|
||||
description: _t(
|
||||
"There was an error updating the room's main address. It may not be allowed by the server " +
|
||||
|
@ -211,7 +211,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
|||
.catch((err) => {
|
||||
// TODO: Add error handling based upon server validation
|
||||
logger.error(err);
|
||||
Modal.createTrackedDialog('Error updating alternative addresses', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error updating main address"),
|
||||
description: _t(
|
||||
"There was an error updating the room's alternative addresses. " +
|
||||
|
@ -243,7 +243,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
|||
}
|
||||
}).catch((err) => {
|
||||
logger.error(err);
|
||||
Modal.createTrackedDialog('Error creating address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error creating address"),
|
||||
description: _t(
|
||||
"There was an error creating that address. It may not be allowed by the server " +
|
||||
|
@ -275,7 +275,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
|||
"error occurred.",
|
||||
);
|
||||
}
|
||||
Modal.createTrackedDialog('Error removing address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error removing address"),
|
||||
description,
|
||||
});
|
||||
|
|
|
@ -315,9 +315,7 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
|
|||
MatrixClientPeg.get().getUserId(),
|
||||
);
|
||||
if (!canSend) {
|
||||
Modal.createTrackedDialog(
|
||||
'Polls',
|
||||
'permissions error: cannot start',
|
||||
Modal.createDialog(
|
||||
ErrorDialog,
|
||||
{
|
||||
title: _t("Permission Required"),
|
||||
|
@ -331,9 +329,7 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
|
|||
? this.props.relation.event_id
|
||||
: null;
|
||||
|
||||
Modal.createTrackedDialog(
|
||||
'Polls',
|
||||
'create',
|
||||
Modal.createDialog(
|
||||
PollCreateDialog,
|
||||
{
|
||||
room: this.props.room,
|
||||
|
|
|
@ -22,7 +22,6 @@ import { BreadcrumbsStore } from "../../../stores/BreadcrumbsStore";
|
|||
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||
import Analytics from "../../../Analytics";
|
||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||
import { useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
|
||||
import Toolbar from "../../../accessibility/Toolbar";
|
||||
|
@ -104,7 +103,6 @@ export default class RoomBreadcrumbs extends React.PureComponent<IProps, IState>
|
|||
};
|
||||
|
||||
private viewRoom = (room: Room, index: number, viaKeyboard = false) => {
|
||||
Analytics.trackEvent("Breadcrumbs", "click_node", String(index));
|
||||
defaultDispatcher.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: room.roomId,
|
||||
|
|
|
@ -66,7 +66,7 @@ export default class RoomUpgradeWarningBar extends React.PureComponent<IProps, I
|
|||
};
|
||||
|
||||
private onUpgradeClick = (): void => {
|
||||
Modal.createTrackedDialog('Upgrade Room Version', '', RoomUpgradeDialog, { room: this.props.room });
|
||||
Modal.createDialog(RoomUpgradeDialog, { room: this.props.room });
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
|
|
|
@ -106,7 +106,7 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
|
|||
// Revert echo because of error
|
||||
this.setState({ invited: true });
|
||||
|
||||
Modal.createTrackedDialog('Revoke 3pid invite failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to revoke invite"),
|
||||
description: _t(
|
||||
"Could not revoke the invite. The server may be experiencing a temporary problem or " +
|
||||
|
|
|
@ -162,7 +162,7 @@ export default class VoiceRecordComposerTile extends React.PureComponent<IProps,
|
|||
|
||||
// The "microphone access error" dialogs are used a lot, so let's functionify them
|
||||
const accessError = () => {
|
||||
Modal.createTrackedDialog('Microphone Access Error', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to access your microphone"),
|
||||
description: <>
|
||||
<p>{ _t(
|
||||
|
@ -177,7 +177,7 @@ export default class VoiceRecordComposerTile extends React.PureComponent<IProps,
|
|||
try {
|
||||
const devices = await MediaDeviceHandler.getDevices();
|
||||
if (!devices?.[MediaDeviceKindEnum.AudioInput]?.length) {
|
||||
Modal.createTrackedDialog('No Microphone Error', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("No microphone found"),
|
||||
description: <>
|
||||
<p>{ _t(
|
||||
|
|
|
@ -95,7 +95,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
|
||||
if (userHasOtherDevices && !serverSupportsControlOfDevicesLogout && this.props.confirm) {
|
||||
// warn about logging out all devices
|
||||
const { finished } = Modal.createTrackedDialog<[boolean]>('Change Password', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
|
||||
title: _t("Warning!"),
|
||||
description:
|
||||
<div>
|
||||
|
@ -196,14 +196,14 @@ export default class ChangePassword extends React.Component<IProps, IState> {
|
|||
|
||||
private optionallySetEmail(): Promise<boolean> {
|
||||
// Ask for an email otherwise the user has no way to reset their password
|
||||
const modal = Modal.createTrackedDialog('Do you want to set an email address?', '', SetEmailDialog, {
|
||||
const modal = Modal.createDialog(SetEmailDialog, {
|
||||
title: _t('Do you want to set an email address?'),
|
||||
});
|
||||
return modal.finished.then(([confirmed]) => confirmed);
|
||||
}
|
||||
|
||||
private onExportE2eKeysClicked = (): void => {
|
||||
Modal.createTrackedDialogAsync('Export E2E Keys', 'Change Password',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../../async-components/views/dialogs/security/ExportE2eKeysDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
|
|
@ -75,10 +75,7 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
|
|||
|
||||
private onBootstrapClick = () => {
|
||||
if (this.state.crossSigningPrivateKeysInStorage) {
|
||||
Modal.createTrackedDialog(
|
||||
"Verify session", "Verify session", SetupEncryptionDialog,
|
||||
{}, null, /* priority = */ false, /* static = */ true,
|
||||
);
|
||||
Modal.createDialog(SetupEncryptionDialog, {}, null, /* priority = */ false, /* static = */ true);
|
||||
} else {
|
||||
// Trigger the flow to set up secure backup, which is what this will do when in
|
||||
// the appropriate state.
|
||||
|
@ -130,14 +127,11 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
|
|||
const cli = MatrixClientPeg.get();
|
||||
await cli.bootstrapCrossSigning({
|
||||
authUploadDeviceSigningKeys: async (makeRequest) => {
|
||||
const { finished } = Modal.createTrackedDialog(
|
||||
'Cross-signing keys dialog', '', InteractiveAuthDialog,
|
||||
{
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: cli,
|
||||
makeRequest,
|
||||
},
|
||||
);
|
||||
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Setting up keys"),
|
||||
matrixClient: cli,
|
||||
makeRequest,
|
||||
});
|
||||
const [confirmed] = await finished;
|
||||
if (!confirmed) {
|
||||
throw new Error("Cross-signing key upload auth canceled");
|
||||
|
|
|
@ -91,7 +91,7 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private onExportE2eKeysClicked = (): void => {
|
||||
Modal.createTrackedDialogAsync('Export E2E Keys', '',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../../async-components/views/dialogs/security/ExportE2eKeysDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
@ -100,7 +100,7 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private onImportE2eKeysClicked = (): void => {
|
||||
Modal.createTrackedDialogAsync('Import E2E Keys', '',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../../async-components/views/dialogs/security/ImportE2eKeysDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
|
|
@ -215,7 +215,7 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
continueKind: "danger",
|
||||
},
|
||||
};
|
||||
Modal.createTrackedDialog('Delete Device Dialog', '', InteractiveAuthDialog, {
|
||||
Modal.createDialog(InteractiveAuthDialog, {
|
||||
title: _t("Authentication"),
|
||||
matrixClient: MatrixClientPeg.get(),
|
||||
authData: error.data,
|
||||
|
|
|
@ -84,14 +84,14 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private onOwnDeviceSignOut = (): void => {
|
||||
Modal.createTrackedDialog('Logout from device list', '', LogoutDialog,
|
||||
Modal.createDialog(LogoutDialog,
|
||||
/* props= */{}, /* className= */null,
|
||||
/* isPriority= */false, /* isStatic= */true);
|
||||
};
|
||||
|
||||
private verify = async () => {
|
||||
if (this.props.isOwnDevice) {
|
||||
Modal.createTrackedDialog("Verify session", "Verify session", SetupEncryptionDialog, {
|
||||
Modal.createDialog(SetupEncryptionDialog, {
|
||||
onFinished: this.props.onDeviceChange,
|
||||
});
|
||||
} else {
|
||||
|
@ -101,7 +101,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
|
|||
userId,
|
||||
[this.props.device.device_id],
|
||||
);
|
||||
Modal.createTrackedDialog('New Session Verification', 'Starting dialog', VerificationRequestDialog, {
|
||||
Modal.createDialog(VerificationRequestDialog, {
|
||||
verificationRequestPromise,
|
||||
member: cli.getUser(userId),
|
||||
onFinished: async () => {
|
||||
|
|
|
@ -108,7 +108,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
|
|||
}
|
||||
|
||||
private onManage = async () => {
|
||||
Modal.createTrackedDialogAsync('Message search', 'Message search',
|
||||
Modal.createDialogAsync(
|
||||
// @ts-ignore: TS doesn't seem to like the type of this now that it
|
||||
// has also been converted to TS as well, but I can't figure out why...
|
||||
import('../../../async-components/views/dialogs/eventindex/ManageEventIndexDialog'),
|
||||
|
|
|
@ -75,7 +75,7 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
|
|||
}
|
||||
|
||||
const matrixClient = MatrixClientPeg.get();
|
||||
const { finished } = Modal.createTrackedDialog('Edit restricted', '', ManageRestrictedJoinRuleDialog, {
|
||||
const { finished } = Modal.createDialog(ManageRestrictedJoinRuleDialog, {
|
||||
matrixClient,
|
||||
room,
|
||||
selected,
|
||||
|
@ -227,7 +227,7 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
|
|||
</b>;
|
||||
}
|
||||
|
||||
Modal.createTrackedDialog('Restricted join rule upgrade', '', RoomUpgradeWarningDialog, {
|
||||
Modal.createDialog(RoomUpgradeWarningDialog, {
|
||||
roomId: room.roomId,
|
||||
targetVersion,
|
||||
description: <>
|
||||
|
|
|
@ -277,7 +277,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
private showSaveError() {
|
||||
Modal.createTrackedDialog('Error saving notification preferences', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t('Error saving notification preferences'),
|
||||
description: _t('An error occurred whilst saving your notification preferences.'),
|
||||
});
|
||||
|
|
|
@ -120,7 +120,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
|
|||
}
|
||||
} catch (err) {
|
||||
logger.log("Failed to save profile", err);
|
||||
Modal.createTrackedDialog('Failed to save profile', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Failed to save your profile"),
|
||||
description: ((err && err.message) ? err.message : _t("The operation could not be completed")),
|
||||
});
|
||||
|
|
|
@ -167,7 +167,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
}
|
||||
|
||||
private startNewBackup = (): void => {
|
||||
Modal.createTrackedDialogAsync('Key Backup', 'Key Backup',
|
||||
Modal.createDialogAsync(
|
||||
import(
|
||||
'../../../async-components/views/dialogs/security/CreateKeyBackupDialog'
|
||||
) as unknown as Promise<ComponentType<{}>>,
|
||||
|
@ -180,7 +180,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
};
|
||||
|
||||
private deleteBackup = (): void => {
|
||||
Modal.createTrackedDialog('Delete Backup', '', QuestionDialog, {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t('Delete Backup'),
|
||||
description: _t(
|
||||
"Are you sure? You will lose your encrypted messages if your " +
|
||||
|
@ -199,10 +199,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
|||
};
|
||||
|
||||
private restoreBackup = async (): Promise<void> => {
|
||||
Modal.createTrackedDialog(
|
||||
'Restore Backup', '', RestoreKeyBackupDialog, null, null,
|
||||
/* priority = */ false, /* static = */ true,
|
||||
);
|
||||
Modal.createDialog(RestoreKeyBackupDialog, null, null, /* priority = */ false, /* static = */ true);
|
||||
};
|
||||
|
||||
private resetSecretStorage = async (): Promise<void> => {
|
||||
|
|
|
@ -219,7 +219,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private showNoTermsWarning(fullUrl) {
|
||||
const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Identity server has no terms of service"),
|
||||
description: (
|
||||
<div>
|
||||
|
@ -320,7 +320,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
|||
message = unboundMessage;
|
||||
}
|
||||
|
||||
const { finished } = Modal.createTrackedDialog('Identity Server Bound Warning', '', QuestionDialog, {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
title,
|
||||
description: message,
|
||||
button,
|
||||
|
|
|
@ -80,7 +80,7 @@ export class ExistingEmailAddress extends React.Component<IExistingEmailAddressP
|
|||
return this.props.onRemoved(this.props.email);
|
||||
}).catch((err) => {
|
||||
logger.error("Unable to remove contact information: " + err);
|
||||
Modal.createTrackedDialog('Remove 3pid failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to remove contact information"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -168,7 +168,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
|
||||
// TODO: Inline field validation
|
||||
if (!Email.looksValid(email)) {
|
||||
Modal.createTrackedDialog('Invalid email address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Invalid Email Address"),
|
||||
description: _t("This doesn't appear to be a valid email address"),
|
||||
});
|
||||
|
@ -183,7 +183,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
}).catch((err) => {
|
||||
logger.error("Unable to add email address " + email + " " + err);
|
||||
this.setState({ verifying: false, continueDisabled: false, addTask: null });
|
||||
Modal.createTrackedDialog('Unable to add email address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to add email address"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -215,14 +215,14 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
|
|||
}).catch((err) => {
|
||||
this.setState({ continueDisabled: false });
|
||||
if (err.errcode === 'M_THREEPID_AUTH_FAILED') {
|
||||
Modal.createTrackedDialog("Email hasn't been verified yet", "", ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Your email address hasn't been verified yet"),
|
||||
description: _t("Click the link in the email you received to verify " +
|
||||
"and then click continue again."),
|
||||
});
|
||||
} else {
|
||||
logger.error("Unable to verify email address: ", err);
|
||||
Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify email address."),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
|
|
@ -76,7 +76,7 @@ export class ExistingPhoneNumber extends React.Component<IExistingPhoneNumberPro
|
|||
return this.props.onRemoved(this.props.msisdn);
|
||||
}).catch((err) => {
|
||||
logger.error("Unable to remove contact information: " + err);
|
||||
Modal.createTrackedDialog('Remove 3pid failed', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to remove contact information"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -185,7 +185,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
|
|||
}).catch((err) => {
|
||||
logger.error("Unable to add phone number " + phoneNumber + " " + err);
|
||||
this.setState({ verifying: false, continueDisabled: false, addTask: null });
|
||||
Modal.createTrackedDialog('Add Phone Number Error', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
@ -222,7 +222,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
|
|||
this.setState({ continueDisabled: false });
|
||||
if (err.errcode !== 'M_THREEPID_AUTH_FAILED') {
|
||||
logger.error("Unable to verify phone number: " + err);
|
||||
Modal.createTrackedDialog('Unable to verify phone number', '', ErrorDialog, {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify phone number."),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue