Merge branch 'develop' into sort-imports

Signed-off-by: Aaron Raimist <aaron@raim.ist>
This commit is contained in:
Aaron Raimist 2021-12-09 08:34:20 +00:00
commit 7b94e13a84
642 changed files with 30052 additions and 8035 deletions

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { ReactNode } from "react";
import { _t } from "../languageHandler";
import SdkConfig from "../SdkConfig";
@ -23,16 +23,52 @@ import Analytics from "../Analytics";
import AccessibleButton from "../components/views/elements/AccessibleButton";
import GenericToast from "../components/views/toasts/GenericToast";
import ToastStore from "../stores/ToastStore";
import {
ButtonClicked,
showDialog as showAnalyticsLearnMoreDialog,
} from "../components/views/dialogs/AnalyticsLearnMoreDialog";
import { Action } from "../dispatcher/actions";
const onAccept = () => {
dis.dispatch({
action: 'accept_cookies',
action: Action.PseudonymousAnalyticsAccept,
});
};
const onReject = () => {
dis.dispatch({
action: "reject_cookies",
action: Action.PseudonymousAnalyticsReject,
});
};
const onLearnMoreNoOptIn = () => {
showAnalyticsLearnMoreDialog({
onFinished: (buttonClicked?: ButtonClicked) => {
if (buttonClicked === ButtonClicked.Primary) {
// user clicked "Enable"
onAccept();
}
// otherwise, the user either clicked "Cancel", or closed the dialog without making a choice,
// leave the toast open
},
primaryButton: _t("Enable"),
});
};
const onLearnMorePreviouslyOptedIn = () => {
showAnalyticsLearnMoreDialog({
onFinished: (buttonClicked?: ButtonClicked) => {
if (buttonClicked === ButtonClicked.Primary) {
// user clicked "That's fine"
onAccept();
} else if (buttonClicked === ButtonClicked.Cancel) {
// user clicked "Stop"
onReject();
}
// otherwise, the user closed the dialog without making a choice, leave the toast open
},
primaryButton: _t("That's fine"),
cancelButton: _t("Stop"),
});
};
@ -42,39 +78,89 @@ const onUsageDataClicked = () => {
const TOAST_KEY = "analytics";
export const showToast = (policyUrl?: string) => {
const getAnonymousDescription = (): ReactNode => {
// get toast description for anonymous tracking (the previous scheme pre-posthog)
const brand = SdkConfig.get().brand;
const cookiePolicyUrl = SdkConfig.get().piwik?.policyUrl;
return _t(
"Send <UsageDataLink>anonymous usage data</UsageDataLink> which helps us improve %(brand)s. " +
"This will use a <PolicyLink>cookie</PolicyLink>.",
{
brand,
},
{
"UsageDataLink": (sub) => (
<AccessibleButton kind="link" onClick={onUsageDataClicked}>{ sub }</AccessibleButton>
),
"PolicyLink": (sub) => cookiePolicyUrl ? (
<a target="_blank" href={cookiePolicyUrl}>{ sub }</a>
) : sub,
},
);
};
const showToast = (props: Omit<React.ComponentProps<typeof GenericToast>, "toastKey">) => {
const analyticsOwner = SdkConfig.get().analyticsOwner ?? SdkConfig.get().brand;
ToastStore.sharedInstance().addOrReplaceToast({
key: TOAST_KEY,
title: _t("Help us improve %(brand)s", { brand }),
props: {
description: _t(
"Send <UsageDataLink>anonymous usage data</UsageDataLink> which helps us improve %(brand)s. " +
"This will use a <PolicyLink>cookie</PolicyLink>.",
{
brand,
},
{
"UsageDataLink": (sub) => (
<AccessibleButton kind="link" onClick={onUsageDataClicked}>{ sub }</AccessibleButton>
),
// XXX: We need to link to the page that explains our cookies
"PolicyLink": (sub) => policyUrl ? (
<a target="_blank" href={policyUrl}>{ sub }</a>
) : sub,
},
),
acceptLabel: _t("Yes"),
onAccept,
rejectLabel: _t("No"),
onReject,
},
title: _t("Help improve %(analyticsOwner)s", { analyticsOwner }),
props,
component: GenericToast,
className: "mx_AnalyticsToast",
priority: 10,
});
};
export const showPseudonymousAnalyticsOptInToast = (analyticsOptIn: boolean): void => {
let props;
if (analyticsOptIn) {
// The user previously opted into our old analytics system - let them know things have changed and ask
// them to opt in again.
props = {
description: _t(
"You previously consented to share anonymous usage data with us. We're updating how that works."),
acceptLabel: _t("That's fine"),
onAccept,
rejectLabel: _t("Learn more"),
onReject: onLearnMorePreviouslyOptedIn,
};
} else if (analyticsOptIn === null || analyticsOptIn === undefined) {
// The user had no analytics setting previously set, so we just need to prompt to opt-in, rather than
// explaining any change.
const learnMoreLink = (sub) => (
<AccessibleButton kind="link" onClick={onLearnMoreNoOptIn}>{ sub }</AccessibleButton>
);
props = {
description: _t(
"Share anonymous data to help us identify issues. Nothing personal. No third parties. " +
"<LearnMoreLink>Learn More</LearnMoreLink>", {}, { "LearnMoreLink": learnMoreLink }),
acceptLabel: _t("Yes"),
onAccept,
rejectLabel: _t("No"),
onReject,
};
} else { // false
// The user previously opted out of analytics, don't ask again
return;
}
showToast(props);
};
export const showAnonymousAnalyticsOptInToast = (): void => {
const props = {
description: getAnonymousDescription(),
acceptLabel: _t("Yes"),
onAccept: () => dis.dispatch({
action: Action.AnonymousAnalyticsAccept,
}),
rejectLabel: _t("No"),
onReject: () => dis.dispatch({
action: Action.AnonymousAnalyticsReject,
}),
};
showToast(props);
};
export const hideToast = () => {
ToastStore.sharedInstance().dismissToast(TOAST_KEY);
};

View file

@ -16,10 +16,11 @@ limitations under the License.
import { _t } from '../languageHandler';
import dis from "../dispatcher/dispatcher";
import { MatrixClientPeg } from '../MatrixClientPeg';
import DeviceListener from '../DeviceListener';
import GenericToast from "../components/views/toasts/GenericToast";
import ToastStore from "../stores/ToastStore";
import { Action } from "../dispatcher/actions";
import { UserTab } from "../components/views/dialogs/UserSettingsDialog";
const TOAST_KEY = "reviewsessions";
@ -28,8 +29,8 @@ export const showToast = (deviceIds: Set<string>) => {
DeviceListener.sharedInstance().dismissUnverifiedSessions(deviceIds);
dis.dispatch({
action: 'view_user_info',
userId: MatrixClientPeg.get().getUserId(),
action: Action.ViewUserSettings,
initialTabId: UserTab.Security,
});
};

View file

@ -23,7 +23,6 @@ import classNames from 'classnames';
import { replaceableComponent } from '../utils/replaceableComponent';
import CallHandler, { CallHandlerEvent } from '../CallHandler';
import dis from '../dispatcher/dispatcher';
import { MatrixClientPeg } from '../MatrixClientPeg';
import { _t } from '../languageHandler';
import RoomAvatar from '../components/views/avatars/RoomAvatar';
@ -46,49 +45,43 @@ export default class IncomingCallToast extends React.Component<IProps, IState> {
super(props);
this.state = {
silenced: CallHandler.sharedInstance().isCallSilenced(this.props.call.callId),
silenced: CallHandler.instance.isCallSilenced(this.props.call.callId),
};
}
public componentDidMount = (): void => {
CallHandler.sharedInstance().addListener(CallHandlerEvent.SilencedCallsChanged, this.onSilencedCallsChanged);
CallHandler.instance.addListener(CallHandlerEvent.SilencedCallsChanged, this.onSilencedCallsChanged);
};
public componentWillUnmount(): void {
CallHandler.sharedInstance().removeListener(CallHandlerEvent.SilencedCallsChanged, this.onSilencedCallsChanged);
CallHandler.instance.removeListener(CallHandlerEvent.SilencedCallsChanged, this.onSilencedCallsChanged);
}
private onSilencedCallsChanged = (): void => {
this.setState({ silenced: CallHandler.sharedInstance().isCallSilenced(this.props.call.callId) });
this.setState({ silenced: CallHandler.instance.isCallSilenced(this.props.call.callId) });
};
private onAnswerClick = (e: React.MouseEvent): void => {
e.stopPropagation();
dis.dispatch({
action: 'answer',
room_id: CallHandler.sharedInstance().roomIdForCall(this.props.call),
});
CallHandler.instance.answerCall(CallHandler.instance.roomIdForCall(this.props.call));
};
private onRejectClick= (e: React.MouseEvent): void => {
e.stopPropagation();
dis.dispatch({
action: 'reject',
room_id: CallHandler.sharedInstance().roomIdForCall(this.props.call),
});
CallHandler.instance.hangupOrReject(CallHandler.instance.roomIdForCall(this.props.call), true);
};
private onSilenceClick = (e: React.MouseEvent): void => {
e.stopPropagation();
const callId = this.props.call.callId;
this.state.silenced ?
CallHandler.sharedInstance().unSilenceCall(callId) :
CallHandler.sharedInstance().silenceCall(callId);
CallHandler.instance.unSilenceCall(callId) :
CallHandler.instance.silenceCall(callId);
};
public render() {
const call = this.props.call;
const room = MatrixClientPeg.get().getRoom(CallHandler.sharedInstance().roomIdForCall(call));
const room = MatrixClientPeg.get().getRoom(CallHandler.instance.roomIdForCall(call));
const isVoice = call.type === CallType.Voice;
const contentClass = classNames("mx_IncomingCallToast_content", {