Initial Countly work

This commit is contained in:
Michael Telatynski 2020-10-29 15:53:14 +00:00
parent 557d9ad90c
commit c3a355097d
33 changed files with 1416 additions and 72 deletions

View file

@ -29,6 +29,7 @@ import 'focus-visible';
import 'what-input';
import Analytics from "../../Analytics";
import CountlyAnalytics from "../../CountlyAnalytics";
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
import { MatrixClientPeg, IMatrixClientCreds } from "../../MatrixClientPeg";
import PlatformPeg from "../../PlatformPeg";
@ -349,6 +350,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
if (SettingsStore.getValue("analyticsOptIn")) {
Analytics.enable();
CountlyAnalytics.instance.enable(false);
} else {
CountlyAnalytics.instance.enable(true);
}
}
@ -364,6 +368,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
if (this.shouldTrackPageChange(prevState, this.state)) {
const durationMs = this.stopPageChangeTimer();
Analytics.trackPageChange(durationMs);
CountlyAnalytics.instance.trackPageChange(durationMs);
}
if (this.focusComposer) {
dis.fire(Action.FocusComposer);
@ -416,6 +421,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} else {
dis.dispatch({action: "view_welcome_page"});
}
} else if (SettingsStore.getValue("analyticsOptIn")) {
CountlyAnalytics.instance.enable(false);
}
});
// Note we don't catch errors from this: we catch everything within
@ -751,7 +758,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, true);
SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false);
hideAnalyticsToast();
Analytics.enable();
if (Analytics.canEnable()) {
Analytics.enable();
}
if (CountlyAnalytics.instance.canEnable()) {
CountlyAnalytics.instance.enable(false);
}
break;
case 'reject_cookies':
SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, false);
@ -1201,7 +1213,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
StorageManager.tryPersistStorage();
if (SettingsStore.getValue("showCookieBar") && Analytics.canEnable()) {
if (SettingsStore.getValue("showCookieBar") &&
(Analytics.canEnable() || CountlyAnalytics.instance.canEnable())
) {
showAnalyticsToast(this.props.config.piwik?.policyUrl);
}
}
@ -1582,6 +1596,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
action: 'require_registration',
});
} else if (screen === 'directory') {
if (this.state.view === Views.WELCOME) {
CountlyAnalytics.instance.track("onboarding_room_directory");
}
dis.fire(Action.ViewRoomDirectory);
} else if (screen === "start_sso" || screen === "start_cas") {
// TODO if logged in, skip SSO

View file

@ -33,6 +33,7 @@ import SettingsStore from "../../settings/SettingsStore";
import GroupFilterOrderStore from "../../stores/GroupFilterOrderStore";
import GroupStore from "../../stores/GroupStore";
import FlairStore from "../../stores/FlairStore";
import CountlyAnalytics from "../../CountlyAnalytics";
const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 800;
@ -49,6 +50,8 @@ export default class RoomDirectory extends React.Component {
constructor(props) {
super(props);
this.startTime = CountlyAnalytics.getTimestamp();
const selectedCommunityId = GroupFilterOrderStore.getSelectedTags()[0];
this.state = {
publicRooms: [],
@ -198,6 +201,11 @@ export default class RoomDirectory extends React.Component {
return;
}
if (this.state.filterString) {
const count = data.total_room_count_estimate || data.chunk.length;
CountlyAnalytics.instance.trackRoomDirectorySearch(count, this.state.filterString);
}
this.nextBatch = data.next_batch;
this.setState((s) => {
s.publicRooms.push(...(data.chunk || []));
@ -407,7 +415,7 @@ export default class RoomDirectory extends React.Component {
};
onCreateRoomClick = room => {
this.props.onFinished();
this.onFinished();
dis.dispatch({
action: 'view_create_room',
public: true,
@ -419,11 +427,12 @@ export default class RoomDirectory extends React.Component {
}
showRoom(room, room_alias, autoJoin = false, shouldPeek = false) {
this.props.onFinished();
this.onFinished();
const payload = {
action: 'view_room',
auto_join: autoJoin,
should_peek: shouldPeek,
_type: "room_directory", // instrumentation
};
if (room) {
// Don't let the user view a room they won't be able to either
@ -575,6 +584,11 @@ export default class RoomDirectory extends React.Component {
}
};
onFinished = () => {
CountlyAnalytics.instance.trackRoomDirectory(this.startTime);
this.props.onFinished();
};
render() {
const Loader = sdk.getComponent("elements.Spinner");
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
@ -693,7 +707,7 @@ export default class RoomDirectory extends React.Component {
<BaseDialog
className={'mx_RoomDirectory_dialog'}
hasCancel={true}
onFinished={this.props.onFinished}
onFinished={this.onFinished}
title={title}
>
<div className="mx_RoomDirectory">

View file

@ -1111,6 +1111,7 @@ export default class RoomView extends React.Component<IProps, IState> {
dis.dispatch({
action: 'join_room',
opts: { inviteSignUrl: signUrl, viaServers: this.props.viaServers },
_type: "unknown", // TODO: instrumentation
});
return Promise.resolve();
});

View file

@ -23,7 +23,7 @@ import { _t } from "../../languageHandler";
import { ContextMenuButton } from "./ContextMenu";
import {USER_NOTIFICATIONS_TAB, USER_SECURITY_TAB} from "../views/dialogs/UserSettingsDialog";
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
import RedesignFeedbackDialog from "../views/dialogs/RedesignFeedbackDialog";
import FeedbackDialog from "../views/dialogs/FeedbackDialog";
import Modal from "../../Modal";
import LogoutDialog from "../views/dialogs/LogoutDialog";
import SettingsStore from "../../settings/SettingsStore";
@ -186,7 +186,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
ev.preventDefault();
ev.stopPropagation();
Modal.createTrackedDialog('Report bugs & give feedback', '', RedesignFeedbackDialog);
Modal.createTrackedDialog('Feedback Dialog', '', FeedbackDialog);
this.setState({contextMenuPosition: null}); // also close the menu
};

View file

@ -26,6 +26,7 @@ import PasswordReset from "../../../PasswordReset";
import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
import classNames from 'classnames';
import AuthPage from "../../views/auth/AuthPage";
import CountlyAnalytics from "../../../CountlyAnalytics";
// Phases
// Show controls to configure server details
@ -64,6 +65,12 @@ export default class ForgotPassword extends React.Component {
serverRequiresIdServer: null,
};
constructor(props) {
super(props);
CountlyAnalytics.instance.track("onboarding_forgot_password_begin");
}
componentDidMount() {
this.reset = null;
this._checkServerLiveliness(this.props.serverConfig);
@ -299,6 +306,8 @@ export default class ForgotPassword extends React.Component {
value={this.state.email}
onChange={this.onInputChanged.bind(this, "email")}
autoFocus
onFocus={() => CountlyAnalytics.instance.track("onboarding_forgot_password_email_focus")}
onBlur={() => CountlyAnalytics.instance.track("onboarding_forgot_password_email_blur")}
/>
</div>
<div className="mx_AuthBody_fieldRow">
@ -308,6 +317,8 @@ export default class ForgotPassword extends React.Component {
label={_t('Password')}
value={this.state.password}
onChange={this.onInputChanged.bind(this, "password")}
onFocus={() => CountlyAnalytics.instance.track("onboarding_forgot_password_newPassword_focus")}
onBlur={() => CountlyAnalytics.instance.track("onboarding_forgot_password_newPassword_blur")}
/>
<Field
name="reset_password_confirm"
@ -315,6 +326,8 @@ export default class ForgotPassword extends React.Component {
label={_t('Confirm')}
value={this.state.password2}
onChange={this.onInputChanged.bind(this, "password2")}
onFocus={() => CountlyAnalytics.instance.track("onboarding_forgot_password_newPassword2_focus")}
onBlur={() => CountlyAnalytics.instance.track("onboarding_forgot_password_newPassword2_blur")}
/>
</div>
<span>{_t(

View file

@ -30,6 +30,7 @@ import SSOButton from "../../views/elements/SSOButton";
import PlatformPeg from '../../../PlatformPeg';
import SettingsStore from "../../../settings/SettingsStore";
import {UIFeature} from "../../../settings/UIFeature";
import CountlyAnalytics from "../../../CountlyAnalytics";
// For validating phone numbers without country codes
const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
@ -126,6 +127,8 @@ export default class LoginComponent extends React.Component {
'm.login.cas': () => this._renderSsoStep("cas"),
'm.login.sso': () => this._renderSsoStep("sso"),
};
CountlyAnalytics.instance.track("onboarding_login_begin");
}
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event