chore: add ga for most actions (#4829)

This commit is contained in:
David Luzar 2022-03-28 14:46:40 +02:00 committed by GitHub
parent e940aeb1a3
commit f242721f3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 221 additions and 93 deletions

View file

@ -24,6 +24,7 @@ import {
import Stack from "./Stack";
import { ToolButton } from "./ToolButton";
import { hasStrokeColor } from "../scene/comparisons";
import { trackEvent } from "../analytics";
import { hasBoundTextElement, isBoundToContainer } from "../element/typeChecks";
export const SelectedShapeActions = ({
@ -209,6 +210,9 @@ export const ShapesSwitcher = ({
activeToolType: typeof SHAPES[number]["value"];
pointerType: PointerType | null;
}) => {
if (appState.activeTool.type !== activeToolType) {
trackEvent("toolbar", activeToolType, "ui");
}
if (!appState.penDetected && pointerType === "pen") {
setAppState({
penDetected: true,

View file

@ -38,7 +38,6 @@ import { ActionResult } from "../actions/types";
import { trackEvent } from "../analytics";
import { getDefaultAppState, isEraserActive } from "../appState";
import {
copyToClipboard,
parseClipboard,
probablySupportsClipboardBlob,
probablySupportsClipboardWriteText,
@ -1291,12 +1290,11 @@ class App extends React.Component<AppProps, AppState> {
});
private cutAll = () => {
this.copyAll();
this.actionManager.executeAction(actionDeleteSelected);
this.actionManager.executeAction(actionCut, "keyboard");
};
private copyAll = () => {
copyToClipboard(this.scene.getElements(), this.state, this.files);
this.actionManager.executeAction(actionCopy, "keyboard");
};
private static resetTapTwice() {
@ -1570,7 +1568,14 @@ class App extends React.Component<AppProps, AppState> {
gesture.pointers.delete(event.pointerId);
};
toggleLock = () => {
toggleLock = (source: "keyboard" | "ui" = "ui") => {
if (!this.state.elementLocked) {
trackEvent(
"toolbar",
"toggleLock",
`${source} (${this.deviceType.isMobile ? "mobile" : "desktop"})`,
);
}
this.setState((prevState) => {
return {
elementLocked: !prevState.elementLocked,
@ -1594,9 +1599,6 @@ class App extends React.Component<AppProps, AppState> {
};
toggleStats = () => {
if (!this.state.showStats) {
trackEvent("dialog", "stats");
}
this.actionManager.executeAction(actionToggleStats);
};
@ -1851,9 +1853,16 @@ class App extends React.Component<AppProps, AppState> {
) {
const shape = findShapeByKey(event.key);
if (shape) {
if (this.state.activeTool.type !== shape) {
trackEvent(
"toolbar",
shape,
`keyboard (${this.deviceType.isMobile ? "mobile" : "desktop"})`,
);
}
this.setActiveTool({ type: shape });
} else if (event.key === KEYS.Q) {
this.toggleLock();
this.toggleLock("keyboard");
}
}
if (event.key === KEYS.SPACE && gesture.pointers.size === 0) {
@ -5493,6 +5502,7 @@ class App extends React.Component<AppProps, AppState> {
options: [
this.deviceType.isMobile &&
navigator.clipboard && {
trackEvent: false,
name: "paste",
perform: (elements, appStates) => {
this.pasteFromClipboard(null);
@ -5549,6 +5559,7 @@ class App extends React.Component<AppProps, AppState> {
this.deviceType.isMobile &&
navigator.clipboard && {
name: "paste",
trackEvent: false,
perform: (elements, appStates) => {
this.pasteFromClipboard(null);
return {

View file

@ -70,7 +70,9 @@ const ContextMenu = ({
dangerous: actionName === "deleteSelectedElements",
checkmark: option.checked?.(appState),
})}
onClick={() => actionManager.executeAction(option)}
onClick={() =>
actionManager.executeAction(option, "contextMenu")
}
>
<div className="context-menu-option__label">{label}</div>
<kbd className="context-menu-option__shortcut">

View file

@ -1,6 +1,5 @@
import React, { useEffect, useRef, useState } from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { ActionsManagerInterface } from "../actions/types";
import { probablySupportsClipboardBlob } from "../clipboard";
import { canvasToBlob } from "../data/blob";
import { NonDeletedExcalidrawElement } from "../element/types";
@ -19,6 +18,7 @@ import OpenColor from "open-color";
import { CheckboxItem } from "./CheckboxItem";
import { DEFAULT_EXPORT_PADDING } from "../constants";
import { nativeFileSystemSupported } from "../data/filesystem";
import { ActionManager } from "../actions/manager";
const supportsContextFilters =
"filter" in document.createElement("canvas").getContext("2d")!;
@ -90,7 +90,7 @@ const ImageExportModal = ({
elements: readonly NonDeletedExcalidrawElement[];
files: BinaryFiles;
exportPadding?: number;
actionManager: ActionsManagerInterface;
actionManager: ActionManager;
onExportToPng: ExportCB;
onExportToSvg: ExportCB;
onExportToClipboard: ExportCB;
@ -229,7 +229,7 @@ export const ImageExportDialog = ({
elements: readonly NonDeletedExcalidrawElement[];
files: BinaryFiles;
exportPadding?: number;
actionManager: ActionsManagerInterface;
actionManager: ActionManager;
onExportToPng: ExportCB;
onExportToSvg: ExportCB;
onExportToClipboard: ExportCB;

View file

@ -1,5 +1,4 @@
import React, { useState } from "react";
import { ActionsManagerInterface } from "../actions/types";
import { NonDeletedExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { useDeviceType } from "./App";
@ -12,6 +11,9 @@ import { Card } from "./Card";
import "./ExportDialog.scss";
import { nativeFileSystemSupported } from "../data/filesystem";
import { trackEvent } from "../analytics";
import { ActionManager } from "../actions/manager";
import { getFrame } from "../utils";
export type ExportCB = (
elements: readonly NonDeletedExcalidrawElement[],
@ -29,7 +31,7 @@ const JSONExportModal = ({
appState: AppState;
files: BinaryFiles;
elements: readonly NonDeletedExcalidrawElement[];
actionManager: ActionsManagerInterface;
actionManager: ActionManager;
onCloseRequest: () => void;
exportOpts: ExportOpts;
canvas: HTMLCanvasElement | null;
@ -54,7 +56,7 @@ const JSONExportModal = ({
aria-label={t("exportDialog.disk_button")}
showAriaLabel={true}
onClick={() => {
actionManager.executeAction(actionSaveFileToDisk);
actionManager.executeAction(actionSaveFileToDisk, "ui");
}}
/>
</Card>
@ -70,9 +72,10 @@ const JSONExportModal = ({
title={t("exportDialog.link_button")}
aria-label={t("exportDialog.link_button")}
showAriaLabel={true}
onClick={() =>
onExportToBackend(elements, appState, files, canvas)
}
onClick={() => {
onExportToBackend(elements, appState, files, canvas);
trackEvent("export", "link", `ui (${getFrame()})`);
}}
/>
</Card>
)}
@ -94,7 +97,7 @@ export const JSONExportDialog = ({
elements: readonly NonDeletedExcalidrawElement[];
appState: AppState;
files: BinaryFiles;
actionManager: ActionsManagerInterface;
actionManager: ActionManager;
exportOpts: ExportOpts;
canvas: HTMLCanvasElement | null;
}) => {

View file

@ -36,6 +36,7 @@ import { LibraryMenu } from "./LibraryMenu";
import "./LayerUI.scss";
import "./Toolbar.scss";
import { PenModeButton } from "./PenModeButton";
import { trackEvent } from "../analytics";
import { useDeviceType } from "../components/App";
interface LayerUIProps {
@ -122,6 +123,7 @@ const LayerUI = ({
const createExporter =
(type: ExportType): ExportCB =>
async (exportedElements) => {
trackEvent("export", type, "ui");
const fileHandle = await exportCanvas(
type,
exportedElements,
@ -326,7 +328,7 @@ const LayerUI = ({
<LockButton
zenModeEnabled={zenModeEnabled}
checked={appState.elementLocked}
onChange={onLockToggle}
onChange={() => onLockToggle()}
title={t("toolBar.lock")}
/>
<Island
@ -531,7 +533,7 @@ const LayerUI = ({
renderImageExportDialog={renderImageExportDialog}
setAppState={setAppState}
onCollabButtonClick={onCollabButtonClick}
onLockToggle={onLockToggle}
onLockToggle={() => onLockToggle()}
onPenModeToggle={onPenModeToggle}
canvas={canvas}
isCollaborating={isCollaborating}

View file

@ -19,6 +19,7 @@ import LibraryMenuItems from "./LibraryMenuItems";
import { EVENT } from "../constants";
import { KEYS } from "../keys";
import { arrayToMap } from "../utils";
import { trackEvent } from "../analytics";
const useOnClickOutside = (
ref: RefObject<HTMLElement>,
@ -157,6 +158,7 @@ export const LibraryMenu = ({
const addToLibrary = useCallback(
async (elements: LibraryItem["elements"]) => {
trackEvent("element", "addToLibrary", "ui");
if (elements.some((element) => element.type === "image")) {
return setAppState({
errorMessage: "Support for adding images to the library coming soon!",