ref(analytics) Convert to TS (#12099)

This commit is contained in:
Robert Pintilii 2022-09-06 15:51:50 +03:00 committed by GitHub
parent 9323b86e3c
commit f4b46128bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 189 additions and 102 deletions

View File

@ -72,13 +72,13 @@ export const VIDEO_MUTE = 'video.mute';
* Creates an event which indicates that a certain action was requested through
* the jitsi-meet API.
*
* @param {Object} action - The action which was requested through the
* @param {string} action - The action which was requested through the
* jitsi-meet API.
* @param {Object} attributes - Attributes to attach to the event.
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createApiEvent(action, attributes = {}) {
export function createApiEvent(action: string, attributes = {}) {
return {
action,
attributes,
@ -93,7 +93,7 @@ export function createApiEvent(action, attributes = {}) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createAudioOnlyChangedEvent(enabled) {
export function createAudioOnlyChangedEvent(enabled: boolean) {
return {
action: `audio.only.${enabled ? 'enabled' : 'disabled'}`
};
@ -107,7 +107,7 @@ export function createAudioOnlyChangedEvent(enabled) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createConnectionEvent(action, attributes = {}) {
export function createConnectionEvent(action: string, attributes = {}) {
return {
action,
actionSubject: 'connection',
@ -124,7 +124,7 @@ export function createConnectionEvent(action, attributes = {}) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createCalendarClickedEvent(eventName, attributes = {}) {
export function createCalendarClickedEvent(eventName: string, attributes = {}) {
return {
action: 'clicked',
actionSubject: eventName,
@ -175,7 +175,7 @@ export function createCalendarConnectedEvent(attributes = {}) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createRecentClickedEvent(eventName, attributes = {}) {
export function createRecentClickedEvent(eventName: string, attributes = {}) {
return {
action: 'clicked',
actionSubject: eventName,
@ -193,7 +193,7 @@ export function createRecentClickedEvent(eventName, attributes = {}) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createChromeExtensionBannerEvent(installPressed, attributes = {}) {
export function createChromeExtensionBannerEvent(installPressed: boolean, attributes = {}) {
return {
action: installPressed ? 'install' : 'cancel',
attributes,
@ -229,7 +229,7 @@ export function createRecentSelectedEvent(attributes = {}) {
* sendAnalytics.
*/
export function createDeepLinkingPageEvent(
action, actionSubject, attributes = {}) {
action: string, actionSubject: string, attributes = {}) {
return {
action,
actionSubject,
@ -247,7 +247,7 @@ export function createDeepLinkingPageEvent(
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createDeviceChangedEvent(mediaType, deviceType) {
export function createDeviceChangedEvent(mediaType: string, deviceType: string) {
return {
action: 'device.changed',
attributes: {
@ -264,7 +264,7 @@ export function createDeviceChangedEvent(mediaType, deviceType) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createE2EEEvent(action) {
export function createE2EEEvent(action: string) {
return {
action,
actionSubject: 'e2ee'
@ -293,7 +293,7 @@ export function createFeedbackOpenEvent() {
* sendAnalytics.
*/
export function createInviteDialogEvent(
action, actionSubject, attributes = {}) {
action: string, actionSubject: string, attributes = {}) {
return {
action,
actionSubject,
@ -310,8 +310,13 @@ export function createInviteDialogEvent(
* @param {Object} [details] - Extra info, see {@code NetworkInfo} type defined by the 'base/net-info' feature.
* @returns {Object}
*/
export function createNetworkInfoEvent({ isOnline, networkType, details }) {
const attributes = { isOnline };
export function createNetworkInfoEvent({ isOnline, networkType, details }:
{ details?: Object, isOnline: boolean, networkType?: string }) {
const attributes: {
details?: Object;
isOnline: boolean;
networkType?: string;
} = { isOnline };
// Do no include optional stuff or Amplitude handler will log warnings.
networkType && (attributes.networkType = networkType);
@ -345,7 +350,7 @@ export function createOfferAnswerFailedEvent() {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createPageReloadScheduledEvent(reason, timeout, details) {
export function createPageReloadScheduledEvent(reason: string, timeout: number, details: Object) {
return {
action: 'page.reload.scheduled',
attributes: {
@ -365,7 +370,7 @@ export function createPageReloadScheduledEvent(reason, timeout, details) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createPinnedEvent(action, participantId, attributes) {
export function createPinnedEvent(action: string, participantId: string, attributes = {}) {
return {
type: TYPE_TRACK,
action,
@ -392,7 +397,7 @@ export function createPinnedEvent(action, participantId, attributes) {
* @param {string} action - The action.
* @returns {Object}
*/
export function createPollEvent(action) {
export function createPollEvent(action: string) {
return {
action: `poll.${action}`
};
@ -407,7 +412,7 @@ export function createPollEvent(action) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createProfilePanelButtonEvent(buttonName, attributes = {}) {
export function createProfilePanelButtonEvent(buttonName: string, attributes = {}) {
return {
action: 'clicked',
actionSubject: buttonName,
@ -429,7 +434,7 @@ export function createProfilePanelButtonEvent(buttonName, attributes = {}) {
* sendAnalytics.
*/
export function createRecordingDialogEvent(
dialogName, buttonName, attributes = {}) {
dialogName: string, buttonName: string, attributes = {}) {
return {
action: 'clicked',
actionSubject: buttonName,
@ -449,7 +454,7 @@ export function createRecordingDialogEvent(
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createLiveStreamingDialogEvent(dialogName, buttonName) {
export function createLiveStreamingDialogEvent(dialogName: string, buttonName: string) {
return {
action: 'clicked',
actionSubject: buttonName,
@ -465,7 +470,14 @@ export function createLiveStreamingDialogEvent(dialogName, buttonName) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createLocalTracksDurationEvent(duration) {
export function createLocalTracksDurationEvent(duration: {
audio: { value: number };
conference: { value: number };
video: {
camera: { value: number };
desktop: { value: number };
};
}) {
const { audio, video, conference } = duration;
const { camera, desktop } = video;
@ -491,7 +503,7 @@ export function createLocalTracksDurationEvent(duration) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createRecordingEvent(action, type, value) {
export function createRecordingEvent(action: string, type: string, value: number) {
return {
action,
actionSubject: `recording.${type}`,
@ -509,7 +521,11 @@ export function createRecordingEvent(action, type, value) {
* @param {number} timeSinceLeft - How many seconds since the last conference was left.
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
*/
export function createRejoinedEvent({ url, lastConferenceDuration, timeSinceLeft }) {
export function createRejoinedEvent({ url, lastConferenceDuration, timeSinceLeft }: {
lastConferenceDuration: number;
timeSinceLeft: number;
url: string;
}) {
return {
action: 'rejoined',
attributes: {
@ -530,7 +546,7 @@ export function createRejoinedEvent({ url, lastConferenceDuration, timeSinceLeft
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createRemoteMuteConfirmedEvent(participantId, mediaType) {
export function createRemoteMuteConfirmedEvent(participantId: string, mediaType: string) {
return {
action: 'clicked',
attributes: {
@ -551,7 +567,7 @@ export function createRemoteMuteConfirmedEvent(participantId, mediaType) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createRemoteVideoMenuButtonEvent(buttonName, attributes) {
export function createRemoteVideoMenuButtonEvent(buttonName: string, attributes = {}) {
return {
action: 'clicked',
actionSubject: buttonName,
@ -569,8 +585,13 @@ export function createRemoteVideoMenuButtonEvent(buttonName, attributes) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createRTCStatsTraceCloseEvent(closeEvent) {
const event = {
export function createRTCStatsTraceCloseEvent(closeEvent: {code: string; reason: string;}) {
const event: {
action: string;
code?: string;
reason?: string;
source: string;
} = {
action: 'trace.onclose',
source: 'rtcstats'
};
@ -590,7 +611,7 @@ export function createRTCStatsTraceCloseEvent(closeEvent) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createScreenSharingEvent(action, value = null) {
export function createScreenSharingEvent(action: string, value = null) {
return {
action,
actionSubject: 'screen.sharing',
@ -606,7 +627,7 @@ export function createScreenSharingEvent(action, value = null) {
* @param {Object} attributes - Additional information that describes the issue.
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
*/
export function createScreenSharingIssueEvent(attributes) {
export function createScreenSharingIssueEvent(attributes = {}) {
return {
action: 'screen.sharing.issue',
attributes
@ -621,7 +642,7 @@ export function createScreenSharingIssueEvent(attributes) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createSharedVideoEvent(action, attributes = {}) {
export function createSharedVideoEvent(action: string, attributes = {}) {
return {
action,
attributes,
@ -646,7 +667,7 @@ export function createSharedVideoEvent(action, attributes = {}) {
* sendAnalytics.
*/
export function createShortcutEvent(
shortcut,
shortcut: string,
action = ACTION_SHORTCUT_TRIGGERED,
attributes = {},
source = 'keyboard.shortcut') {
@ -666,7 +687,7 @@ export function createShortcutEvent(
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createStartAudioOnlyEvent(audioOnly) {
export function createStartAudioOnlyEvent(audioOnly: boolean) {
return {
action: 'start.audio.only',
attributes: {
@ -693,7 +714,7 @@ export function createStartSilentEvent() {
* @param {string} elementID - The ID of the HTMLAudioElement.
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
*/
export function createAudioPlayErrorEvent(elementID) {
export function createAudioPlayErrorEvent(elementID: string) {
return {
action: 'audio.play.error',
attributes: {
@ -708,7 +729,7 @@ export function createAudioPlayErrorEvent(elementID) {
* @param {string} elementID - The ID of the HTMLAudioElement.
* @returns {Object} The event in a format suitable for sending via sendAnalytics.
*/
export function createAudioPlaySuccessEvent(elementID) {
export function createAudioPlaySuccessEvent(elementID: string) {
return {
action: 'audio.play.success',
attributes: {
@ -731,9 +752,9 @@ export function createAudioPlaySuccessEvent(elementID) {
* sendAnalytics.
*/
export function createStartMutedConfigurationEvent(
source,
audioMute,
videoMute) {
source: string,
audioMute: boolean,
videoMute: boolean) {
return {
action: 'start.muted.configuration',
attributes: {
@ -754,7 +775,7 @@ export function createStartMutedConfigurationEvent(
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createSyncTrackStateEvent(mediaType, muted) {
export function createSyncTrackStateEvent(mediaType: string, muted: boolean) {
return {
action: 'sync.track.state',
attributes: {
@ -776,7 +797,7 @@ export function createSyncTrackStateEvent(mediaType, muted) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createToolbarEvent(buttonName, attributes = {}) {
export function createToolbarEvent(buttonName: string, attributes = {}) {
return {
action: 'clicked',
actionSubject: buttonName,
@ -794,7 +815,7 @@ export function createToolbarEvent(buttonName, attributes = {}) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createReactionMenuEvent(buttonName) {
export function createReactionMenuEvent(buttonName: string) {
return {
action: 'clicked',
actionSubject: 'button',
@ -830,7 +851,7 @@ export function createReactionSoundsDisabledEvent() {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createTrackMutedEvent(mediaType, reason, muted = true) {
export function createTrackMutedEvent(mediaType: string, reason: string, muted = true) {
return {
action: 'track.muted',
attributes: {
@ -848,7 +869,7 @@ export function createTrackMutedEvent(mediaType, reason, muted = true) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createVpaasConferenceJoinedEvent(tenant) {
export function createVpaasConferenceJoinedEvent(tenant: string) {
return {
action: 'vpaas.conference.joined',
attributes: {
@ -866,7 +887,7 @@ export function createVpaasConferenceJoinedEvent(tenant) {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createWelcomePageEvent(action, actionSubject, attributes = {}) {
export function createWelcomePageEvent(action: string, actionSubject: string, attributes = {}) {
return {
action,
actionSubject,
@ -894,7 +915,7 @@ export function createScreensharingCaptureTakenEvent() {
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createBreakoutRoomsEvent(actionSubject) {
export function createBreakoutRoomsEvent(actionSubject: string) {
return {
action: 'clicked',
actionSubject: `${actionSubject}.button`,

View File

@ -1,7 +1,10 @@
// @flow
/* eslint-disable lines-around-comment */
// @ts-ignore
import { API_ID } from '../../../modules/API/constants';
// @ts-ignore
import { getName as getAppName } from '../app/functions';
import { IStore } from '../app/types';
// @ts-ignore
import { getAnalyticsRoomName } from '../base/conference';
import {
checkChromeExtensionsInstalled,
@ -11,11 +14,16 @@ import JitsiMeetJS, {
analytics,
browser
} from '../base/lib-jitsi-meet';
// @ts-ignore
import { isAnalyticsEnabled } from '../base/lib-jitsi-meet/functions';
import { getJitsiMeetGlobalNS, loadScript, parseURIString } from '../base/util';
// @ts-ignore
import { loadScript } from '../base/util';
import { getJitsiMeetGlobalNS } from '../base/util/helpers';
import { inIframe } from '../base/util/iframeUtils';
import { parseURIString } from '../base/util/uri';
import { AmplitudeHandler, MatomoHandler } from './handlers';
import AmplitudeHandler from './handlers/AmplitudeHandler';
import MatomoHandler from './handlers/MatomoHandler';
import logger from './logger';
/**
@ -155,7 +163,7 @@ export async function createHandlers({ getState }: { getState: Function }) {
* @param {Array<Object>} handlers - The analytics handlers.
* @returns {void}
*/
export function initAnalytics(store: Store, handlers: Array<Object>) {
export function initAnalytics(store: IStore, handlers: Array<Object>) {
const { getState, dispatch } = store;
if (!isAnalyticsEnabled(getState) || handlers.length === 0) {
@ -168,9 +176,9 @@ export function initAnalytics(store: Store, handlers: Array<Object>) {
deploymentInfo
} = config;
const { group, server } = state['features/base/jwt'];
const { locationURL = {} } = state['features/base/connection'];
const { locationURL = { href: '' } } = state['features/base/connection'];
const { tenant } = parseURIString(locationURL.href) || {};
const permanentProperties = {};
const permanentProperties: any = {};
if (server) {
permanentProperties.server = server;
@ -199,7 +207,7 @@ export function initAnalytics(store: Store, handlers: Array<Object>) {
if (deploymentInfo) {
for (const key in deploymentInfo) {
if (deploymentInfo.hasOwnProperty(key)) {
permanentProperties[key] = deploymentInfo[key];
permanentProperties[key] = deploymentInfo[key as keyof typeof deploymentInfo];
}
}
}
@ -232,7 +240,7 @@ export function initAnalytics(store: Store, handlers: Array<Object>) {
* @returns {Promise} Resolves with the handlers that have been successfully loaded and rejects if there are no handlers
* loaded or the analytics is disabled.
*/
function _loadHandlers(scriptURLs = [], handlerConstructorOptions) {
function _loadHandlers(scriptURLs: any[] = [], handlerConstructorOptions: Object) {
const promises = [];
for (const url of scriptURLs) {
@ -241,7 +249,7 @@ function _loadHandlers(scriptURLs = [], handlerConstructorOptions) {
() => {
return { type: 'success' };
},
error => {
(error: Error) => {
return {
type: 'error',
error,

View File

@ -1,13 +1,44 @@
export interface IEvent {
action?: string;
actionSubject?: string;
attributes?: {
[key: string]: string|undefined;
},
name?: string;
source?: string;
type?: string;
}
interface Options {
amplitudeAPPKey?: string;
blackListedEvents?: string[];
envType?: string;
googleAnalyticsTrackingId?: string;
group?: string;
host?: string;
matomoEndpoint?: string;
matomoSiteID?: string;
product?: string;
subproduct?: string;
user?: string;
version?: string;
whiteListedEvents?: string[];
}
/**
* Abstract implementation of analytics handler.
*/
export default class AbstractHandler {
_enabled: boolean;
_whiteListedEvents: Array<string>|undefined;
_blackListedEvents: Array<string>|undefined;
/**
* Creates new instance.
*
* @param {Object} options - Optional parameters.
*/
constructor(options = {}) {
constructor(options: Options = {}) {
this._enabled = false;
this._whiteListedEvents = options.whiteListedEvents;
@ -28,7 +59,7 @@ export default class AbstractHandler {
* @param {Object} event - The analytics event.
* @returns {string} - The extracted name.
*/
_extractName(event) {
_extractName(event: IEvent) {
// Page events have a single 'name' field.
if (event.type === 'page') {
return event.name;
@ -65,12 +96,12 @@ export default class AbstractHandler {
* @param {Object} event - The event.
* @returns {boolean}
*/
_shouldIgnore(event) {
_shouldIgnore(event: IEvent) {
if (!event || !this._enabled) {
return true;
}
const name = this._extractName(event);
const name = this._extractName(event) ?? '';
if (Array.isArray(this._whiteListedEvents)) {
return this._whiteListedEvents.indexOf(name) === -1;

View File

@ -1,13 +1,18 @@
/* eslint-disable lines-around-comment */
import logger from '../logger';
import AbstractHandler from './AbstractHandler';
import AbstractHandler, { IEvent } from './AbstractHandler';
// @ts-ignore
import { fixDeviceID } from './amplitude/fixDeviceID';
// @ts-ignore
import amplitude from './amplitude/lib';
/**
* Analytics handler for Amplitude.
*/
export default class AmplitudeHandler extends AbstractHandler {
_deviceId: string;
_userId: Object;
/**
* Creates new instance of the Amplitude analytics handler.
*
@ -15,14 +20,14 @@ export default class AmplitudeHandler extends AbstractHandler {
* @param {string} options.amplitudeAPPKey - The Amplitude app key required
* by the Amplitude API.
*/
constructor(options) {
constructor(options: any) {
super(options);
const { amplitudeAPPKey, user } = options;
this._enabled = true;
const onError = e => {
const onError = (e: Error) => {
logger.error('Error initializing Amplitude', e);
this._enabled = false;
};
@ -31,7 +36,7 @@ export default class AmplitudeHandler extends AbstractHandler {
amplitude.getInstance().init(amplitudeAPPKey);
fixDeviceID(amplitude.getInstance()).then(() => {
amplitude.getInstance().getDeviceId()
.then(deviceId => {
.then((deviceId: string) => {
this._deviceId = deviceId;
});
});
@ -57,7 +62,7 @@ export default class AmplitudeHandler extends AbstractHandler {
* @param {Object} userProps - The user portperties.
* @returns {void}
*/
setUserProperties(userProps) {
setUserProperties(userProps: Object) {
if (this._enabled) {
amplitude.getInstance().setUserProperties(userProps);
}
@ -71,7 +76,7 @@ export default class AmplitudeHandler extends AbstractHandler {
* lib-jitsi-meet.
* @returns {void}
*/
sendEvent(event) {
sendEvent(event: IEvent) {
if (this._shouldIgnore(event)) {
return;
}

View File

@ -1,13 +1,15 @@
/* global ga */
import { getJitsiMeetGlobalNS } from '../../base/util';
import { getJitsiMeetGlobalNS } from '../../base/util/helpers';
import AbstractHandler from './AbstractHandler';
import AbstractHandler, { IEvent } from './AbstractHandler';
/**
* Analytics handler for Google Analytics.
*/
class GoogleAnalyticsHandler extends AbstractHandler {
_userProperties: Object;
_userPropertiesString: string;
/**
* Creates new instance of the GA analytics handler.
@ -16,7 +18,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* @param {string} options.googleAnalyticsTrackingId - The GA track id
* required by the GA API.
*/
constructor(options) {
constructor(options: any) {
super(options);
this._userProperties = {};
@ -37,16 +39,20 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* required by the GA API.
* @returns {void}
*/
_initGoogleAnalytics(options) {
_initGoogleAnalytics(options: any) {
/**
* TODO: Keep this local, there's no need to add it to window.
*/
/* eslint-disable */
/* eslint-disable */ // @ts-ignore
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
// @ts-ignore
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
/* eslint-enable */
// @ts-ignore
ga('create', options.googleAnalyticsTrackingId, 'auto');
// @ts-ignore
ga('send', 'pageview');
}
@ -60,11 +66,11 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* suitable value.
* @private
*/
_extractValue(event) {
let value = event && event.attributes && event.attributes.value;
_extractValue(event: IEvent) {
let value: string|number|undefined = event && event.attributes && event.attributes.value;
// Try to extract an integer from the "value" attribute.
value = Math.round(parseFloat(value));
value = Math.round(parseFloat(value ?? ''));
return value;
}
@ -78,7 +84,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* analytics event.
* @private
*/
_extractLabel(event) {
_extractLabel(event: IEvent) {
const { attributes = {} } = event;
const labelsArray
= Object.keys(attributes).map(key => `${key}=${attributes[key]}`);
@ -94,7 +100,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* @param {Object} userProps - The permanent portperties.
* @returns {void}
*/
setUserProperties(userProps = {}) {
setUserProperties(userProps: any = {}) {
if (!this._enabled) {
return;
}
@ -120,12 +126,17 @@ class GoogleAnalyticsHandler extends AbstractHandler {
* lib-jitsi-meet.
* @returns {void}
*/
sendEvent(event) {
sendEvent(event: IEvent) {
if (this._shouldIgnore(event)) {
return;
}
const gaEvent = {
const gaEvent: {
eventAction?: string;
eventCategory: string;
eventLabel: string;
eventValue?: number;
} = {
'eventCategory': 'jitsi-meet',
'eventAction': this._extractName(event),
'eventLabel': this._extractLabel(event)
@ -136,6 +147,7 @@ class GoogleAnalyticsHandler extends AbstractHandler {
gaEvent.eventValue = value;
}
// @ts-ignore
ga('send', 'event', gaEvent);
}

View File

@ -1,13 +1,14 @@
/* global _paq */
import { getJitsiMeetGlobalNS } from '../../base/util';
import { getJitsiMeetGlobalNS } from '../../base/util/helpers';
import AbstractHandler from './AbstractHandler';
import AbstractHandler, { IEvent } from './AbstractHandler';
/**
* Analytics handler for Matomo.
*/
export default class MatomoHandler extends AbstractHandler {
_userProperties: Object;
/**
* Creates new instance of the Matomo handler.
@ -16,7 +17,7 @@ export default class MatomoHandler extends AbstractHandler {
* @param {string} options.matomoEndpoint - The Matomo endpoint.
* @param {string} options.matomoSiteID - The site ID.
*/
constructor(options) {
constructor(options: any) {
super(options);
this._userProperties = {};
@ -43,9 +44,11 @@ export default class MatomoHandler extends AbstractHandler {
* @param {string} options.matomoSiteID - The site ID.
* @returns {void}
*/
_initMatomo(options) {
_initMatomo(options: any) {
// @ts-ignore
const _paq = window._paq || [];
// @ts-ignore
window._paq = _paq;
_paq.push([ 'trackPageView' ]);
@ -70,7 +73,7 @@ export default class MatomoHandler extends AbstractHandler {
g.async = true;
g.defer = true;
g.src = `${u}matomo.js`;
s.parentNode.insertBefore(g, s);
s.parentNode?.insertBefore(g, s);
})();
}
@ -84,11 +87,11 @@ export default class MatomoHandler extends AbstractHandler {
* suitable value.
* @private
*/
_extractValue(event) {
_extractValue(event: IEvent) {
const value = event && event.attributes && event.attributes.value;
// Try to extract an integer from the 'value' attribute.
return Math.round(parseFloat(value));
return Math.round(parseFloat(value ?? ''));
}
/**
@ -97,7 +100,7 @@ export default class MatomoHandler extends AbstractHandler {
* @param {Object} userProps - The permanent properties.
* @returns {void}
*/
setUserProperties(userProps = {}) {
setUserProperties(userProps: any = {}) {
if (!this._enabled) {
return;
}
@ -108,6 +111,7 @@ export default class MatomoHandler extends AbstractHandler {
Object.keys(userProps)
.filter(key => visitScope.indexOf(key) === -1)
.forEach((key, index) => {
// @ts-ignore
_paq.push([
'setCustomVariable',
1 + index,
@ -122,6 +126,7 @@ export default class MatomoHandler extends AbstractHandler {
Object.keys(userProps)
.filter(key => visitScope.indexOf(key) !== -1)
.forEach((key, index) => {
// @ts-ignore
_paq.push([
'setCustomVariable',
1 + index,
@ -141,18 +146,19 @@ export default class MatomoHandler extends AbstractHandler {
* lib-jitsi-meet.
* @returns {void}
*/
sendEvent(event) {
sendEvent(event: IEvent) {
if (this._shouldIgnore(event)) {
return;
}
const value = this._extractValue(event);
const matomoEvent = [ 'trackEvent', 'jitsi-meet', this._extractName(event) ];
const matomoEvent: Array<string|number|undefined> = [ 'trackEvent', 'jitsi-meet', this._extractName(event) ];
if (!isNaN(value)) {
matomoEvent.push(value);
}
// @ts-ignore
_paq.push(matomoEvent);
}
}

View File

@ -7,7 +7,7 @@ import DeviceInfo from 'react-native-device-info';
* @param {AmplitudeClient} amplitude - The amplitude instance.
* @returns {void}
*/
export async function fixDeviceID(amplitude) {
export async function fixDeviceID(amplitude: any) {
await DefaultPreference.setName('jitsi-preferences');
const current = await DefaultPreference.get('amplitudeDeviceId');

View File

@ -4,6 +4,6 @@
* @param {AmplitudeClient} amplitude - The amplitude instance.
* @returns {void}
*/
export function fixDeviceID(amplitude) { // eslint-disable-line no-unused-vars
export function fixDeviceID(amplitude: any) { // eslint-disable-line @typescript-eslint/no-unused-vars
}

View File

@ -1,3 +1,4 @@
// @ts-ignore
import amplitude from 'amplitude-js';
export default amplitude;

View File

@ -1,5 +1,3 @@
// @flow
import { getLogger } from '../base/logging/functions';
export default getLogger('features/analytics');

View File

@ -1,20 +1,23 @@
// @flow
/* eslint-disable lines-around-comment */
import { IState } from '../app/types';
import {
CONFERENCE_JOINED,
CONFERENCE_WILL_LEAVE,
SET_ROOM
} from '../base/conference';
import { SET_CONFIG } from '../base/config';
import { SET_NETWORK_INFO } from '../base/net-info';
import { MiddlewareRegistry } from '../base/redux';
} from '../base/conference/actionTypes';
import { SET_CONFIG } from '../base/config/actionTypes';
import { SET_NETWORK_INFO } from '../base/net-info/actionTypes';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import {
getLocalAudioTrack,
getLocalVideoTrack,
TRACK_ADDED,
TRACK_REMOVED,
TRACK_UPDATED
} from '../base/tracks';
} from '../base/tracks/actionTypes';
import {
getLocalAudioTrack,
getLocalVideoTrack
// @ts-ignore
} from '../base/tracks/functions';
import { createLocalTracksDurationEvent, createNetworkInfoEvent } from './AnalyticsEvents';
import { UPDATE_LOCAL_TRACKS_DURATION } from './actionTypes';
@ -26,7 +29,7 @@ import { createHandlers, initAnalytics, resetAnalytics, sendAnalytics } from './
* @param {Object} state - The redux state.
* @returns {Object} - The local tracks duration.
*/
function calculateLocalTrackDuration(state) {
function calculateLocalTrackDuration(state: IState) {
const now = Date.now();
const { localTracksDuration } = state['features/analytics'];
const { conference } = state['features/base/conference'];
@ -60,8 +63,8 @@ function calculateLocalTrackDuration(state) {
} else {
const { videoType } = videoTrack;
if (video[videoType].startedTime === -1) {
newDuration.video[videoType].startedTime = now;
if (video[videoType as keyof typeof video].startedTime === -1) {
newDuration.video[videoType as keyof typeof video].startedTime = now;
}
}

View File

@ -4,7 +4,9 @@ import { equals } from '../redux/functions';
import { SET_JWT } from './actionTypes';
export interface IJwtState {
group?: string;
jwt?: string;
server?: string;
}
/**

View File

@ -341,7 +341,7 @@ module.exports = (_env, argv) => {
}),
Object.assign({}, config, {
entry: {
'analytics-ga': './react/features/analytics/handlers/GoogleAnalyticsHandler.js'
'analytics-ga': './react/features/analytics/handlers/GoogleAnalyticsHandler.ts'
},
plugins: [
...config.plugins,