chore: Remove tracking (#2722)

* chore: Remove tracking

* process

* rename

* remove

* prod

* Update public/index.html

Co-authored-by: David Luzar <luzar.david@gmail.com>

* Update public/index.html

* eol

* more

* stats

Co-authored-by: David Luzar <luzar.david@gmail.com>
This commit is contained in:
Lipis 2021-01-05 20:06:14 +02:00 committed by GitHub
parent 4acdc47ef0
commit 3aa01ad272
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 182 additions and 435 deletions

View File

@ -1 +1 @@
REACT_APP_INCLUDE_GTAG=true
REACT_APP_GOOGLE_ANALYTICS_ID=UA-387204-13

View File

@ -5,7 +5,6 @@ WORKDIR /opt/node_app
COPY package.json package-lock.json ./
RUN npm i --no-optional
ARG REACT_APP_INCLUDE_GTAG=false
ARG NODE_ENV=production
COPY . .

View File

@ -1,64 +0,0 @@
| Excalidraw | Category | Name | Label | Value |
| ----------------------- | -------- | ---------------------------------- | ------------------------------- | --------- |
| Shape / Selection | shape | selection, rectangle, diamond, etc | `toolbar` or `shortcut` |
| Text on double click | shape | text | `double-click` |
| Lock selection | shape | lock | `on` or `off` |
| Clear canvas | action | clear canvas |
| Zoom in | action | zoom | in | `zoom` |
| Zoom out | action | zoom | out | `zoom` |
| Zoom fit | action | zoom | fit | `zoom` |
| Zoom reset | action | zoom | reset | `zoom` |
| Scroll back to content | action | scroll to content |
| Load file | io | load | `MIME type` |
| Import from URL | io | import |
| Save | io | save |
| Save as | io | save as |
| Export to backend | io | export | backend |
| Export as SVG | io | export | `svg` or `clipboard-svg` |
| Export to PNG | io | export | `png` or `clipboard-png` |
| Canvas color | change | canvas color | `color` |
| Background color | change | background color | `color` |
| Stroke color | change | stroke color | `color` |
| Stroke width | change | stroke | width | `width` |
| Stroke style | change | style | `solid` or `dashed` or `dotted` |
| Stroke sloppiness | change | stroke | sloppiness | `value` |
| Fill | change | fill | `value` |
| Edge | change | edge | `value` |
| Opacity | change | opacity | value | `opacity` |
| Project name | change | title |
| Theme | change | theme | `light` or `dark` |
| Change language | change | language | `language` |
| Send to back | layer | move | `back` |
| Send backward | layer | move | `down` |
| Bring to front | layer | move | `front` |
| Bring forward | layer | move | `up` |
| Align left | align | align | `left` |
| Align right | align | align | `right` |
| Align top | align | align | `top` |
| Align bottom | align | align | `bottom` |
| Center horizontally | align | horizontally | `center` |
| Center vertically | align | vertically | `center` |
| Distribute horizontally | align | distribute | `horizontally` |
| Distribute vertically | align | distribute | `vertically` |
| Start session | share | session start |
| Join session | share | session join |
| Start end | share | session end |
| Copy room link | share | copy link |
| Go to collaborator | share | go to collaborator |
| Change name | share | name |
| Add to library | library | add |
| Remove from library | library | remove |
| Load library | library | load |
| Save library | library | save |
| Import library | library | import |
| Shortcuts dialog | dialog | shortcuts |
| Collaboration dialog | dialog | collaboration |
| Export dialog | dialog | export |
| Library dialog | dialog | library |
| E2EE shield | exit | e2ee shield |
| GitHub corner | exit | github |
| Excalidraw blog | exit | blog |
| Excalidraw guides | exit | guides |
| File issues | exit | issues |
| First load | load | first load |
| Load from stroage | load | storage | size | `bytes` |

View File

@ -81,8 +81,8 @@
"private": true,
"scripts": {
"build-node": "node ./scripts/build-node.js",
"build:app:docker": "REACT_APP_INCLUDE_GTAG=false REACT_APP_DISABLE_SENTRY=true react-scripts build",
"build:app": "REACT_APP_INCLUDE_GTAG=true REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build",
"build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build",
"build:app": "REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build",
"build:version": "node ./scripts/build-version.js",
"build": "npm run build:app && npm run build:version",
"eject": "react-scripts eject",

View File

@ -86,10 +86,10 @@
<link rel="stylesheet" href="fonts.css" type="text/css" />
<% if (process.env.REACT_APP_INCLUDE_GTAG === 'true') { %>
<% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %>
<script
async
src="https://www.googletagmanager.com/gtag/js?id=UA-387204-13"
src="https://www.googletagmanager.com/gtag/js?id=%REACT_APP_GOOGLE_ANALYTICS_ID%"
></script>
<script>
window.dataLayer = window.dataLayer || [];
@ -97,7 +97,7 @@
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "UA-387204-13");
gtag("config", "%REACT_APP_GOOGLE_ANALYTICS_ID%");
</script>
<% } %>

View File

@ -3,7 +3,6 @@ import { getSelectedElements } from "../scene";
import { getNonDeletedElements } from "../element";
import { deepCopyElement } from "../element/newElement";
import { Library } from "../data/library";
import { EVENT_LIBRARY, trackEvent } from "../analytics";
export const actionAddToLibrary = register({
name: "addToLibrary",
@ -16,7 +15,6 @@ export const actionAddToLibrary = register({
Library.loadLibrary().then((items) => {
Library.saveLibrary([...items, selectedElements.map(deepCopyElement)]);
});
trackEvent(EVENT_LIBRARY, "add");
return false;
},
contextMenuOrder: 6,

View File

@ -1,7 +1,5 @@
import React from "react";
import { KEYS } from "../keys";
import { t } from "../i18n";
import { register } from "./register";
import { alignElements, Alignment } from "../align";
import {
AlignBottomIcon,
AlignLeftIcon,
@ -10,14 +8,15 @@ import {
CenterHorizontallyIcon,
CenterVerticallyIcon,
} from "../components/icons";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getElementMap, getNonDeletedElements } from "../element";
import { ToolButton } from "../components/ToolButton";
import { getElementMap, getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { AppState } from "../types";
import { alignElements, Alignment } from "../align";
import { getShortcutKey } from "../utils";
import { trackEvent, EVENT_ALIGN } from "../analytics";
import { register } from "./register";
const enableActionGroup = (
elements: readonly ExcalidrawElement[],
@ -44,7 +43,6 @@ const alignSelectedElements = (
export const actionAlignTop = register({
name: "alignTop",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "align", "top");
return {
appState,
elements: alignSelectedElements(elements, appState, {
@ -74,7 +72,6 @@ export const actionAlignTop = register({
export const actionAlignBottom = register({
name: "alignBottom",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "align", "bottom");
return {
appState,
elements: alignSelectedElements(elements, appState, {
@ -104,7 +101,6 @@ export const actionAlignBottom = register({
export const actionAlignLeft = register({
name: "alignLeft",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "align", "left");
return {
appState,
elements: alignSelectedElements(elements, appState, {
@ -134,7 +130,6 @@ export const actionAlignLeft = register({
export const actionAlignRight = register({
name: "alignRight",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "align", "right");
return {
appState,
elements: alignSelectedElements(elements, appState, {
@ -164,7 +159,6 @@ export const actionAlignRight = register({
export const actionAlignVerticallyCentered = register({
name: "alignVerticallyCentered",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "vertically", "center");
return {
appState,
elements: alignSelectedElements(elements, appState, {
@ -190,7 +184,6 @@ export const actionAlignVerticallyCentered = register({
export const actionAlignHorizontallyCentered = register({
name: "alignHorizontallyCentered",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "horizontally", "center");
return {
appState,
elements: alignSelectedElements(elements, appState, {

View File

@ -1,7 +1,5 @@
import React from "react";
import { EVENT_ACTION, EVENT_CHANGE, trackEvent } from "../analytics";
import { getDefaultAppState } from "../appState";
import colors from "../colors";
import { ColorPicker } from "../components/ColorPicker";
import { resetZoom, trash, zoomIn, zoomOut } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
@ -21,15 +19,6 @@ import { register } from "./register";
export const actionChangeViewBackgroundColor = register({
name: "changeViewBackgroundColor",
perform: (_, appState, value) => {
if (value !== appState.viewBackgroundColor) {
trackEvent(
EVENT_CHANGE,
"canvas color",
colors.canvasBackground.includes(value)
? `${value} (picker ${colors.canvasBackground.indexOf(value)})`
: value,
);
}
return {
appState: { ...appState, viewBackgroundColor: value },
commitToHistory: true,
@ -52,7 +41,6 @@ export const actionChangeViewBackgroundColor = register({
export const actionClearCanvas = register({
name: "clearCanvas",
perform: (elements, appState: AppState) => {
trackEvent(EVENT_ACTION, "clear canvas");
return {
elements: elements.map((element) =>
newElementWith(element, { isDeleted: true }),
@ -98,7 +86,6 @@ export const actionZoomIn = register({
{ left: appState.offsetLeft, top: appState.offsetTop },
{ x: appState.width / 2, y: appState.height / 2 },
);
trackEvent(EVENT_ACTION, "zoom", "in", zoom.value * 100);
return {
appState: {
...appState,
@ -133,7 +120,6 @@ export const actionZoomOut = register({
{ x: appState.width / 2, y: appState.height / 2 },
);
trackEvent(EVENT_ACTION, "zoom", "out", zoom.value * 100);
return {
appState: {
...appState,
@ -161,7 +147,6 @@ export const actionZoomOut = register({
export const actionResetZoom = register({
name: "resetZoom",
perform: (_elements, appState) => {
trackEvent(EVENT_ACTION, "zoom", "reset", 100);
return {
appState: {
...appState,
@ -234,12 +219,10 @@ const zoomToFitElements = (
left: appState.offsetLeft,
top: appState.offsetTop,
});
const action = zoomToSelection ? "selection" : "fit";
const [x1, y1, x2, y2] = commonBounds;
const centerX = (x1 + x2) / 2;
const centerY = (y1 + y2) / 2;
trackEvent(EVENT_ACTION, "zoom", action, newZoom.value * 100);
return {
appState: {
...appState,

View File

@ -1,19 +1,18 @@
import React from "react";
import { CODES } from "../keys";
import { t } from "../i18n";
import { register } from "./register";
import {
DistributeHorizontallyIcon,
DistributeVerticallyIcon,
} from "../components/icons";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getElementMap, getNonDeletedElements } from "../element";
import { ToolButton } from "../components/ToolButton";
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { distributeElements, Distribution } from "../disitrubte";
import { getElementMap, getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { CODES } from "../keys";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { AppState } from "../types";
import { getShortcutKey } from "../utils";
import { EVENT_ALIGN, trackEvent } from "../analytics";
import { register } from "./register";
const enableActionGroup = (
elements: readonly ExcalidrawElement[],
@ -40,7 +39,6 @@ const distributeSelectedElements = (
export const distributeHorizontally = register({
name: "distributeHorizontally",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "distribute", "horizontally");
return {
appState,
elements: distributeSelectedElements(elements, appState, {
@ -69,7 +67,6 @@ export const distributeHorizontally = register({
export const distributeVertically = register({
name: "distributeVertically",
perform: (elements, appState) => {
trackEvent(EVENT_ALIGN, "distribute", "vertically");
return {
appState,
elements: distributeSelectedElements(elements, appState, {

View File

@ -1,22 +1,21 @@
import React from "react";
import { EVENT_CHANGE, EVENT_IO, trackEvent } from "../analytics";
import { load, save, saveAs } from "../components/icons";
import { trackEvent } from "../analytics";
import { load, questionCircle, save, saveAs } from "../components/icons";
import { ProjectName } from "../components/ProjectName";
import { ToolButton } from "../components/ToolButton";
import "../components/ToolIcon.scss";
import { Tooltip } from "../components/Tooltip";
import { questionCircle } from "../components/icons";
import { loadFromJSON, saveAsJSON } from "../data";
import { t } from "../i18n";
import useIsMobile from "../is-mobile";
import { KEYS } from "../keys";
import { muteFSAbortError } from "../utils";
import { register } from "./register";
import "../components/ToolIcon.scss";
export const actionChangeProjectName = register({
name: "changeProjectName",
perform: (_elements, appState, value) => {
trackEvent(EVENT_CHANGE, "title");
trackEvent("change", "title");
return { appState: { ...appState, name: value }, commitToHistory: false };
},
PanelComponent: ({ appState, updateData }) => (
@ -100,7 +99,6 @@ export const actionSaveScene = register({
perform: async (elements, appState, value) => {
try {
const { fileHandle } = await saveAsJSON(elements, appState);
trackEvent(EVENT_IO, "save");
return { commitToHistory: false, appState: { ...appState, fileHandle } };
} catch (error) {
if (error?.name !== "AbortError") {
@ -131,7 +129,6 @@ export const actionSaveAsScene = register({
...appState,
fileHandle: null,
});
trackEvent(EVENT_IO, "save as");
return { commitToHistory: false, appState: { ...appState, fileHandle } };
} catch (error) {
if (error?.name !== "AbortError") {

View File

@ -7,7 +7,6 @@ import { register } from "./register";
import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils";
import { CODES, KEYS } from "../keys";
import { HelpIcon } from "../components/HelpIcon";
import { EVENT_DIALOG, trackEvent } from "../analytics";
export const actionToggleCanvasMenu = register({
name: "toggleCanvasMenu",
@ -72,7 +71,6 @@ export const actionFullScreen = register({
export const actionShortcuts = register({
name: "toggleShortcuts",
perform: (_elements, appState) => {
trackEvent(EVENT_DIALOG, "shortcuts");
return {
appState: {
...appState,

View File

@ -1,16 +1,14 @@
import React from "react";
import { Avatar } from "../components/Avatar";
import { register } from "./register";
import { getClientColors, getClientInitials } from "../clients";
import { Collaborator } from "../types";
import { Avatar } from "../components/Avatar";
import { centerScrollOn } from "../scene/scroll";
import { EVENT_SHARE, trackEvent } from "../analytics";
import { Collaborator } from "../types";
import { register } from "./register";
export const actionGoToCollaborator = register({
name: "goToCollaborator",
perform: (_elements, appState, value) => {
const point = value as Collaborator["pointer"];
trackEvent(EVENT_SHARE, "go to collaborator");
if (!point) {
return { appState, commitToHistory: false };
}

View File

@ -1,56 +1,53 @@
import React from "react";
import { getLanguage } from "../i18n";
import {
ExcalidrawElement,
ExcalidrawTextElement,
TextAlign,
FontFamily,
ExcalidrawLinearElement,
Arrowhead,
} from "../element/types";
import {
getCommonAttributeOfSelectedElements,
isSomeElementSelected,
getTargetElements,
canChangeSharpness,
canHaveArrowheads,
} from "../scene";
import { ButtonSelect } from "../components/ButtonSelect";
import { AppState } from "../../src/types";
import { ButtonIconSelect } from "../components/ButtonIconSelect";
import { ButtonSelect } from "../components/ButtonSelect";
import { ColorPicker } from "../components/ColorPicker";
import { IconPicker } from "../components/IconPicker";
import {
isTextElement,
redrawTextBoundingBox,
getNonDeletedElements,
} from "../element";
import { isLinearElement, isLinearElementType } from "../element/typeChecks";
import { ColorPicker } from "../components/ColorPicker";
import { AppState } from "../../src/types";
import { t } from "../i18n";
import { register } from "./register";
import { newElementWith } from "../element/mutateElement";
import { DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY } from "../constants";
import { randomInteger } from "../random";
import {
FillHachureIcon,
FillCrossHatchIcon,
FillSolidIcon,
StrokeWidthIcon,
StrokeStyleSolidIcon,
StrokeStyleDashedIcon,
StrokeStyleDottedIcon,
EdgeSharpIcon,
EdgeRoundIcon,
SloppinessArchitectIcon,
SloppinessArtistIcon,
SloppinessCartoonistIcon,
ArrowheadArrowIcon,
ArrowheadBarIcon,
ArrowheadDotIcon,
ArrowheadNoneIcon,
EdgeRoundIcon,
EdgeSharpIcon,
FillCrossHatchIcon,
FillHachureIcon,
FillSolidIcon,
SloppinessArchitectIcon,
SloppinessArtistIcon,
SloppinessCartoonistIcon,
StrokeStyleDashedIcon,
StrokeStyleDottedIcon,
StrokeStyleSolidIcon,
StrokeWidthIcon,
} from "../components/icons";
import { EVENT_CHANGE, trackEvent } from "../analytics";
import colors from "../colors";
import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE } from "../constants";
import {
getNonDeletedElements,
isTextElement,
redrawTextBoundingBox,
} from "../element";
import { newElementWith } from "../element/mutateElement";
import { isLinearElement, isLinearElementType } from "../element/typeChecks";
import {
Arrowhead,
ExcalidrawElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
FontFamily,
TextAlign,
} from "../element/types";
import { getLanguage, t } from "../i18n";
import { randomInteger } from "../random";
import {
canChangeSharpness,
canHaveArrowheads,
getCommonAttributeOfSelectedElements,
getTargetElements,
isSomeElementSelected,
} from "../scene";
import { register } from "./register";
const changeProperty = (
elements: readonly ExcalidrawElement[],
@ -92,15 +89,6 @@ const getFormValue = function <T>(
export const actionChangeStrokeColor = register({
name: "changeStrokeColor",
perform: (elements, appState, value) => {
if (value !== appState.currentItemStrokeColor) {
trackEvent(
EVENT_CHANGE,
"stroke color",
colors.elementStroke.includes(value)
? `${value} (picker ${colors.elementStroke.indexOf(value)})`
: value,
);
}
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -132,16 +120,6 @@ export const actionChangeStrokeColor = register({
export const actionChangeBackgroundColor = register({
name: "changeBackgroundColor",
perform: (elements, appState, value) => {
if (value !== appState.currentItemBackgroundColor) {
trackEvent(
EVENT_CHANGE,
"background color",
colors.elementBackground.includes(value)
? `${value} (picker ${colors.elementBackground.indexOf(value)})`
: value,
);
}
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -173,7 +151,6 @@ export const actionChangeBackgroundColor = register({
export const actionChangeFillStyle = register({
name: "changeFillStyle",
perform: (elements, appState, value) => {
trackEvent(EVENT_CHANGE, "fill", value);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -223,7 +200,6 @@ export const actionChangeFillStyle = register({
export const actionChangeStrokeWidth = register({
name: "changeStrokeWidth",
perform: (elements, appState, value) => {
trackEvent(EVENT_CHANGE, "stroke", "width", value);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -286,7 +262,6 @@ export const actionChangeStrokeWidth = register({
export const actionChangeSloppiness = register({
name: "changeSloppiness",
perform: (elements, appState, value) => {
trackEvent(EVENT_CHANGE, "stroke", "sloppiness", value);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -335,7 +310,6 @@ export const actionChangeSloppiness = register({
export const actionChangeStrokeStyle = register({
name: "changeStrokeStyle",
perform: (elements, appState, value) => {
trackEvent(EVENT_CHANGE, "style", value);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -383,7 +357,6 @@ export const actionChangeStrokeStyle = register({
export const actionChangeOpacity = register({
name: "changeOpacity",
perform: (elements, appState, value) => {
trackEvent(EVENT_CHANGE, "opacity", "value", value);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -580,7 +553,6 @@ export const actionChangeSharpness = register({
const shouldUpdateForLinearElements = targetElements.length
? targetElements.every(isLinearElement)
: isLinearElementType(appState.elementType);
trackEvent(EVENT_CHANGE, "edge", value);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -642,12 +614,6 @@ export const actionChangeArrowhead = register({
return {
elements: changeProperty(elements, appState, (el) => {
if (isLinearElement(el)) {
trackEvent(
EVENT_CHANGE,
`arrowhead ${value.position}`,
value.type || "none",
);
const { position, type } = value;
if (position === "start") {

View File

@ -1,18 +1,7 @@
export const EVENT_ACTION = "action";
export const EVENT_ALIGN = "align";
export const EVENT_CHANGE = "change";
export const EVENT_DIALOG = "dialog";
export const EVENT_EXIT = "exit";
export const EVENT_IO = "io";
export const EVENT_LAYER = "layer";
export const EVENT_LIBRARY = "library";
export const EVENT_LOAD = "load";
export const EVENT_SHAPE = "shape";
export const EVENT_SHARE = "share";
export const EVENT_MAGIC = "magic";
export const trackEvent =
typeof window !== "undefined" && window.gtag
process.env.REACT_APP_GOOGLE_ANALYTICS_ID &&
typeof window !== "undefined" &&
window.gtag
? (category: string, name: string, label?: string, value?: number) => {
window.gtag("event", name, {
event_category: category,
@ -23,5 +12,6 @@ export const trackEvent =
: typeof process !== "undefined" && process?.env?.JEST_WORKER_ID
? (category: string, name: string, label?: string, value?: number) => {}
: (category: string, name: string, label?: string, value?: number) => {
console.info("Track Event", category, name, label, value);
// Uncomment the next line to track locally
// console.info("Track Event", category, name, label, value);
};

View File

@ -1,4 +1,4 @@
import { EVENT_MAGIC, trackEvent } from "./analytics";
import { trackEvent } from "./analytics";
import colors from "./colors";
import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, ENV } from "./constants";
import { newElement, newLinearElement, newTextElement } from "./element";
@ -473,7 +473,7 @@ export const renderSpreadsheet = (
x: number,
y: number,
): ChartElements => {
trackEvent(EVENT_MAGIC, "chart", chartType, spreadsheet.values.length);
trackEvent("magic", "chart", chartType, spreadsheet.values.length);
if (chartType === "line") {
return chartTypeLine(spreadsheet, x, y);
}

View File

@ -1,23 +1,22 @@
import React from "react";
import { AppState, Zoom } from "../types";
import { ExcalidrawElement } from "../element/types";
import { ActionManager } from "../actions/manager";
import { getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import useIsMobile from "../is-mobile";
import {
hasBackground,
hasStroke,
canChangeSharpness,
hasText,
canHaveArrowheads,
getTargetElements,
hasBackground,
hasStroke,
hasText,
} from "../scene";
import { t } from "../i18n";
import { SHAPES } from "../shapes";
import { ToolButton } from "./ToolButton";
import { AppState, Zoom } from "../types";
import { capitalizeString, isTransparent, setCursorForShape } from "../utils";
import Stack from "./Stack";
import useIsMobile from "../is-mobile";
import { getNonDeletedElements } from "../element";
import { trackEvent, EVENT_SHAPE, EVENT_DIALOG } from "../analytics";
import { ToolButton } from "./ToolButton";
export const SelectedShapeActions = ({
appState,
@ -181,7 +180,6 @@ export const ShapesSwitcher = ({
aria-keyshortcuts={shortcut}
data-testid={value}
onChange={() => {
trackEvent(EVENT_SHAPE, value, "toolbar");
setAppState({
elementType: value,
multiElement: null,
@ -203,9 +201,6 @@ export const ShapesSwitcher = ({
title={`${capitalizeString(t("toolBar.library"))} — 9`}
aria-label={capitalizeString(t("toolBar.library"))}
onClick={() => {
if (!isLibraryOpen) {
trackEvent(EVENT_DIALOG, "library");
}
setAppState({ isLibraryOpen: !isLibraryOpen });
}}
/>

View File

@ -8,12 +8,7 @@ import { createRedoAction, createUndoAction } from "../actions/actionHistory";
import { ActionManager } from "../actions/manager";
import { actions } from "../actions/register";
import { ActionResult } from "../actions/types";
import {
EVENT_DIALOG,
EVENT_LIBRARY,
EVENT_SHAPE,
trackEvent,
} from "../analytics";
import { trackEvent } from "../analytics";
import { getDefaultAppState } from "../appState";
import {
copyToClipboard,
@ -111,7 +106,7 @@ import {
selectGroupsForSelectedElements,
} from "../groups";
import { createHistory, SceneHistory } from "../history";
import { t, getLanguage, setLanguage, languages, defaultLang } from "../i18n";
import { defaultLang, getLanguage, languages, setLanguage, t } from "../i18n";
import {
CODES,
getResizeCenterPointKey,
@ -504,7 +499,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
)
) {
await Library.importLibrary(blob);
trackEvent(EVENT_LIBRARY, "import");
this.setState({
isLibraryOpen: true,
});
@ -1134,7 +1128,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
toggleLock = () => {
this.setState((prevState) => {
trackEvent(EVENT_SHAPE, "lock", !prevState.elementLocked ? "on" : "off");
return {
elementLocked: !prevState.elementLocked,
elementType: prevState.elementLocked
@ -1158,7 +1151,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
toggleStats = () => {
if (!this.state.showStats) {
trackEvent(EVENT_DIALOG, "stats");
trackEvent("dialog", "stats");
}
this.setState({
showStats: !this.state.showStats,
@ -1270,9 +1263,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
}
if (event.code === CODES.NINE) {
if (!this.state.isLibraryOpen) {
trackEvent(EVENT_DIALOG, "library");
}
this.setState({ isLibraryOpen: !this.state.isLibraryOpen });
}
@ -1357,7 +1347,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
) {
const shape = findShapeByKey(event.key);
if (shape) {
trackEvent(EVENT_SHAPE, shape, "shortcut");
this.selectShapeTool(shape);
} else if (event.key === KEYS.Q) {
this.toggleLock();
@ -1741,7 +1730,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
resetCursor();
if (!event[KEYS.CTRL_OR_CMD]) {
trackEvent(EVENT_SHAPE, "text", "double-click");
this.startTextEditing({
sceneX,
sceneY,

View File

@ -1,6 +1,5 @@
import React from "react";
import { ActionManager } from "../actions/manager";
import { EVENT_CHANGE, trackEvent } from "../analytics";
import { AppState } from "../types";
import { DarkModeToggle } from "./DarkModeToggle";
@ -19,8 +18,6 @@ export const BackgroundPickerAndDarkModeToggle = ({
<DarkModeToggle
value={appState.appearance}
onChange={(appearance) => {
// TODO: track the theme on the first load too
trackEvent(EVENT_CHANGE, "theme", appearance);
setAppState({ appearance });
}}
/>

View File

@ -6,7 +6,6 @@ import useIsMobile from "../is-mobile";
import { users } from "./icons";
import "./CollabButton.scss";
import { EVENT_DIALOG, trackEvent } from "../analytics";
const CollabButton = ({
isCollaborating,
@ -23,10 +22,7 @@ const CollabButton = ({
className={clsx("CollabButton", {
"is-collaborating": isCollaborating,
})}
onClick={() => {
trackEvent(EVENT_DIALOG, "collaboration");
onClick();
}}
onClick={onClick}
icon={users}
type="button"
title={t("buttons.roomDialog")}

View File

@ -1,7 +1,6 @@
import React, { useEffect, useRef, useState } from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { ActionsManagerInterface } from "../actions/types";
import { EVENT_DIALOG, trackEvent } from "../analytics";
import { probablySupportsClipboardBlob } from "../clipboard";
import { canvasToBlob } from "../data/blob";
import { NonDeletedExcalidrawElement } from "../element/types";
@ -251,7 +250,6 @@ export const ExportDialog = ({
<>
<ToolButton
onClick={() => {
trackEvent(EVENT_DIALOG, "export");
setModalIsShown(true);
}}
icon={exportFile}

View File

@ -1,6 +1,5 @@
import React from "react";
import oc from "open-color";
import { EVENT_EXIT, trackEvent } from "../analytics";
import React from "react";
// https://github.com/tholman/github-corners
export const GitHubCorner = React.memo(
@ -17,9 +16,6 @@ export const GitHubCorner = React.memo(
target="_blank"
rel="noopener noreferrer"
aria-label="GitHub repository"
onClick={() => {
trackEvent(EVENT_EXIT, "github");
}}
>
<path
d="M0 0l115 115h15l12 27 108 108V0z"

View File

@ -1,56 +1,46 @@
import clsx from "clsx";
import React, {
RefObject,
useCallback,
useEffect,
useRef,
useState,
RefObject,
useEffect,
useCallback,
} from "react";
import { showSelectedShapeActions } from "../element";
import { calculateScrollCenter, getSelectedElements } from "../scene";
import { exportCanvas } from "../data";
import { AppState, LibraryItems, LibraryItem } from "../types";
import { NonDeletedExcalidrawElement } from "../element/types";
import { ActionManager } from "../actions/manager";
import { Island } from "./Island";
import Stack from "./Stack";
import { FixedSideContainer } from "./FixedSideContainer";
import { UserList } from "./UserList";
import { LockIcon } from "./LockIcon";
import { ExportDialog, ExportCB } from "./ExportDialog";
import { CLASSES } from "../constants";
import { exportCanvas } from "../data";
import { importLibraryFromJSON, saveLibraryAsJSON } from "../data/json";
import { Library } from "../data/library";
import { showSelectedShapeActions } from "../element";
import { NonDeletedExcalidrawElement } from "../element/types";
import { Language, t } from "../i18n";
import { HintViewer } from "./HintViewer";
import useIsMobile from "../is-mobile";
import { calculateScrollCenter, getSelectedElements } from "../scene";
import { ExportType } from "../scene/types";
import { MobileMenu } from "./MobileMenu";
import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions";
import { Section } from "./Section";
import { AppState, LibraryItem, LibraryItems } from "../types";
import { muteFSAbortError } from "../utils";
import { SelectedShapeActions, ShapesSwitcher, ZoomActions } from "./Actions";
import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
import CollabButton from "./CollabButton";
import { ErrorDialog } from "./ErrorDialog";
import { ShortcutsDialog } from "./ShortcutsDialog";
import { LoadingMessage } from "./LoadingMessage";
import { CLASSES } from "../constants";
import { shield, exportFile, load } from "./icons";
import { ExportCB, ExportDialog } from "./ExportDialog";
import { FixedSideContainer } from "./FixedSideContainer";
import { GitHubCorner } from "./GitHubCorner";
import { Tooltip } from "./Tooltip";
import { HintViewer } from "./HintViewer";
import { exportFile, load, shield } from "./icons";
import { Island } from "./Island";
import "./LayerUI.scss";
import { LibraryUnit } from "./LibraryUnit";
import { ToolButton } from "./ToolButton";
import { saveLibraryAsJSON, importLibraryFromJSON } from "../data/json";
import { muteFSAbortError } from "../utils";
import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
import clsx from "clsx";
import { Library } from "../data/library";
import {
EVENT_ACTION,
EVENT_EXIT,
EVENT_LIBRARY,
trackEvent,
} from "../analytics";
import { LoadingMessage } from "./LoadingMessage";
import { LockIcon } from "./LockIcon";
import { MobileMenu } from "./MobileMenu";
import { PasteChartDialog } from "./PasteChartDialog";
import { Section } from "./Section";
import { ShortcutsDialog } from "./ShortcutsDialog";
import Stack from "./Stack";
import { ToolButton } from "./ToolButton";
import { Tooltip } from "./Tooltip";
import { UserList } from "./UserList";
interface LayerUIProps {
actionManager: ActionManager;
@ -159,13 +149,7 @@ const LibraryMenuItems = ({
}}
/>
<a
href="https://libraries.excalidraw.com"
target="_excalidraw_libraries"
onClick={() => {
trackEvent(EVENT_EXIT, "libraries");
}}
>
<a href="https://libraries.excalidraw.com" target="_excalidraw_libraries">
{t("labels.libraries")}
</a>
</div>,
@ -267,7 +251,6 @@ const LibraryMenu = ({
const items = await Library.loadLibrary();
const nextItems = items.filter((_, index) => index !== indexToRemove);
Library.saveLibrary(nextItems);
trackEvent(EVENT_LIBRARY, "remove");
setLibraryItems(nextItems);
}, []);
@ -276,7 +259,6 @@ const LibraryMenu = ({
const items = await Library.loadLibrary();
const nextItems = [...items, elements];
onAddToLibrary();
trackEvent(EVENT_LIBRARY, "add");
Library.saveLibrary(nextItems);
setLibraryItems(nextItems);
},
@ -328,9 +310,6 @@ const LayerUI = ({
href="https://blog.excalidraw.com/end-to-end-encryption/"
target="_blank"
rel="noopener noreferrer"
onClick={() => {
trackEvent(EVENT_EXIT, "e2ee shield");
}}
>
<Tooltip label={t("encrypted.tooltip")} position="above" long={true}>
{shield}
@ -567,7 +546,6 @@ const LayerUI = ({
<button
className="scroll-back-to-content"
onClick={() => {
trackEvent(EVENT_ACTION, "scroll to content");
setAppState({
...calculateScrollCenter(elements, appState, canvas),
});

View File

@ -16,7 +16,6 @@ import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars";
import { LockIcon } from "./LockIcon";
import { UserList } from "./UserList";
import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
import { EVENT_ACTION, trackEvent } from "../analytics";
type MobileMenuProps = {
appState: AppState;
@ -149,7 +148,6 @@ export const MobileMenu = ({
<button
className="scroll-back-to-content"
onClick={() => {
trackEvent(EVENT_ACTION, "scroll to content");
setAppState({
...calculateScrollCenter(elements, appState, canvas),
});

View File

@ -4,7 +4,6 @@ import { isDarwin } from "../keys";
import { Dialog } from "./Dialog";
import { getShortcutKey } from "../utils";
import "./ShortcutsDialog.scss";
import { EVENT_EXIT, trackEvent } from "../analytics";
const Columns = (props: { children: React.ReactNode }) => (
<div
@ -92,9 +91,6 @@ const Footer = () => (
href="https://blog.excalidraw.com"
target="_blank"
rel="noopener noreferrer"
onClick={() => {
trackEvent(EVENT_EXIT, "blog");
}}
>
{t("shortcutsDialog.blog")}
</a>
@ -102,9 +98,6 @@ const Footer = () => (
href="https://howto.excalidraw.com"
target="_blank"
rel="noopener noreferrer"
onClick={() => {
trackEvent(EVENT_EXIT, "guides");
}}
>
{t("shortcutsDialog.howto")}
</a>
@ -112,9 +105,6 @@ const Footer = () => (
href="https://github.com/excalidraw/excalidraw/issues"
target="_blank"
rel="noopener noreferrer"
onClick={() => {
trackEvent(EVENT_EXIT, "issues");
}}
>
{t("shortcutsDialog.github")}
</a>

View File

@ -1,4 +1,3 @@
import { EVENT_IO, trackEvent } from "../analytics";
import { cleanAppStateForExport } from "../appState";
import { MIME_TYPES } from "../constants";
import { clearElementsForExport } from "../element";
@ -111,7 +110,6 @@ export const loadFromBlob = async (
localAppState,
);
trackEvent(EVENT_IO, "load", getMimeType(blob));
return result;
} catch (error) {
console.error(error.message);

View File

@ -1,5 +1,4 @@
import { fileSave } from "browser-nativefs";
import { EVENT_IO, trackEvent } from "../analytics";
import {
copyCanvasToClipboardAsPng,
copyTextToSystemClipboard,
@ -8,8 +7,8 @@ import { NonDeletedExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { exportToCanvas, exportToSvg } from "../scene/export";
import { ExportType } from "../scene/types";
import { canvasToBlob } from "./blob";
import { AppState } from "../types";
import { canvasToBlob } from "./blob";
import { serializeAsJSON } from "./json";
export { loadFromBlob } from "./blob";
@ -60,10 +59,8 @@ export const exportCanvas = async (
fileName: `${name}.svg`,
extensions: [".svg"],
});
trackEvent(EVENT_IO, "export", "svg");
return;
} else if (type === "clipboard-svg") {
trackEvent(EVENT_IO, "export", "clipboard-svg");
copyTextToSystemClipboard(tempSvg.outerHTML);
return;
}
@ -95,11 +92,9 @@ export const exportCanvas = async (
fileName,
extensions: [".png"],
});
trackEvent(EVENT_IO, "export", "png");
} else if (type === "clipboard") {
try {
await copyCanvasToClipboardAsPng(tempCanvas);
trackEvent(EVENT_IO, "export", "clipboard-png");
} catch (error) {
if (error.name === "CANVAS_POSSIBLY_TOO_BIG") {
throw error;

View File

@ -1,13 +1,11 @@
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { cleanAppStateForExport } from "../appState";
import { fileOpen, fileSave } from "browser-nativefs";
import { loadFromBlob } from "./blob";
import { Library } from "./library";
import { cleanAppStateForExport } from "../appState";
import { MIME_TYPES } from "../constants";
import { clearElementsForExport } from "../element";
import { EVENT_LIBRARY, trackEvent } from "../analytics";
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { loadFromBlob } from "./blob";
import { Library } from "./library";
export const serializeAsJSON = (
elements: readonly ExcalidrawElement[],
@ -84,7 +82,6 @@ export const saveLibraryAsJSON = async () => {
description: "Excalidraw library file",
extensions: [".excalidrawlib"],
});
trackEvent(EVENT_LIBRARY, "save");
};
export const importLibraryFromJSON = async () => {
@ -93,6 +90,5 @@ export const importLibraryFromJSON = async () => {
extensions: [".json", ".excalidrawlib"],
mimeTypes: ["application/json"],
});
trackEvent(EVENT_LIBRARY, "load");
Library.importLibrary(blob);
};

View File

@ -1,40 +1,36 @@
import React, { PureComponent } from "react";
import throttle from "lodash.throttle";
import React, { PureComponent } from "react";
import { ExcalidrawImperativeAPI } from "../../components/App";
import { ErrorDialog } from "../../components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "../../constants";
import {
decryptAESGEM,
SocketUpdateDataSource,
getCollaborationLinkData,
generateCollaborationLink,
SOCKET_SERVER,
} from "../data";
import { isSavedToFirebase, saveToFirebase } from "../data/firebase";
import Portal from "./Portal";
import { AppState, Collaborator, Gesture } from "../../types";
import { ImportedDataState } from "../../data/types";
import { ExcalidrawElement } from "../../element/types";
import {
importUsernameFromLocalStorage,
saveUsernameToLocalStorage,
STORAGE_KEYS,
} from "../data/localStorage";
import { resolvablePromise, withBatchedUpdates } from "../../utils";
import {
getSceneVersion,
getSyncableElements,
} from "../../packages/excalidraw/index";
import RoomDialog from "./RoomDialog";
import { ErrorDialog } from "../../components/ErrorDialog";
import { ImportedDataState } from "../../data/types";
import { ExcalidrawImperativeAPI } from "../../components/App";
import { AppState, Collaborator, Gesture } from "../../types";
import { resolvablePromise, withBatchedUpdates } from "../../utils";
import {
INITIAL_SCENE_UPDATE_TIMEOUT,
SCENE,
SYNC_FULL_SCENE_INTERVAL_MS,
} from "../app_constants";
import { EVENT_SHARE, trackEvent } from "../../analytics";
import {
decryptAESGEM,
generateCollaborationLink,
getCollaborationLinkData,
SocketUpdateDataSource,
SOCKET_SERVER,
} from "../data";
import { isSavedToFirebase, saveToFirebase } from "../data/firebase";
import {
importUsernameFromLocalStorage,
saveUsernameToLocalStorage,
STORAGE_KEYS,
} from "../data/localStorage";
import Portal from "./Portal";
import RoomDialog from "./RoomDialog";
interface CollabState {
isCollaborating: boolean;
@ -168,7 +164,6 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
elements,
commitToHistory: true,
});
trackEvent(EVENT_SHARE, "session start");
return this.initializeSocketClient();
};
@ -176,7 +171,6 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
this.saveCollabRoomToFirebase();
window.history.pushState({}, APP_NAME, window.location.origin);
this.destroySocketClient();
trackEvent(EVENT_SHARE, "session end");
};
private destroySocketClient = () => {

View File

@ -1,12 +1,10 @@
import React, { useRef } from "react";
import { t } from "../../i18n";
import { Dialog } from "../../components/Dialog";
import { copyTextToSystemClipboard } from "../../clipboard";
import { ToolButton } from "../../components/ToolButton";
import { Dialog } from "../../components/Dialog";
import { clipboard, start, stop } from "../../components/icons";
import { ToolButton } from "../../components/ToolButton";
import { t } from "../../i18n";
import "./RoomDialog.scss";
import { EVENT_SHARE, trackEvent } from "../../analytics";
const RoomDialog = ({
handleClose,
@ -30,7 +28,6 @@ const RoomDialog = ({
const copyRoomLink = async () => {
try {
await copyTextToSystemClipboard(activeRoomLink);
trackEvent(EVENT_SHARE, "copy link");
} catch (error) {
setErrorMessage(error.message);
}
@ -95,7 +92,6 @@ const RoomDialog = ({
value={username || ""}
className="RoomDialog-username TextInput"
onChange={(event) => onUsernameChange(event.target.value)}
onBlur={() => trackEvent(EVENT_SHARE, "name")}
onKeyPress={(event) => event.key === "Enter" && handleClose()}
/>
</div>

View File

@ -1,10 +1,9 @@
import { t } from "../../i18n";
import { ExcalidrawElement } from "../../element/types";
import { AppState } from "../../types";
import { ImportedDataState } from "../../data/types";
import { restore } from "../../data/restore";
import { EVENT_ACTION, EVENT_IO, trackEvent } from "../../analytics";
import { serializeAsJSON } from "../../data/json";
import { restore } from "../../data/restore";
import { ImportedDataState } from "../../data/types";
import { ExcalidrawElement } from "../../element/types";
import { t } from "../../i18n";
import { AppState } from "../../types";
const byteToHex = (byte: number): string => `0${byte.toString(16)}`.slice(-2);
@ -192,7 +191,6 @@ const importFromBackend = async (
data = await response.json();
}
trackEvent(EVENT_ACTION, "import");
return {
elements: data.elements || null,
appState: data.appState || null,
@ -276,7 +274,6 @@ export const exportToBackend = async (
url.hash = `json=${json.id},${exportedKey.k!}`;
const urlString = url.toString();
window.prompt(`🔒${t("alerts.uploadedSecurly")}`, urlString);
trackEvent(EVENT_IO, "export", "backend");
} else if (json.error_class === "RequestTooLargeError") {
window.alert(t("alerts.couldNotCreateShareableLinkTooBig"));
} else {

View File

@ -1,45 +1,38 @@
import React, {
useState,
useLayoutEffect,
useEffect,
useRef,
useCallback,
} from "react";
import LanguageDetector from "i18next-browser-languagedetector";
import Excalidraw, {
languages,
defaultLang,
} from "../packages/excalidraw/index";
import {
getTotalStorageSize,
importFromLocalStorage,
saveToLocalStorage,
STORAGE_KEYS,
} from "./data/localStorage";
import { ImportedDataState } from "../data/types";
import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
import { TopErrorBoundary } from "../components/TopErrorBoundary";
import { Language, t } from "../i18n";
import { exportToBackend, loadScene } from "./data";
import { getCollaborationLinkData } from "./data";
import { EVENT } from "../constants";
import { loadFromFirebase } from "./data/firebase";
import React, {
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { getDefaultAppState } from "../appState";
import { ExcalidrawImperativeAPI } from "../components/App";
import { debounce, ResolvablePromise, resolvablePromise } from "../utils";
import { AppState, ExcalidrawAPIRefValue } from "../types";
import { ErrorDialog } from "../components/ErrorDialog";
import { TopErrorBoundary } from "../components/TopErrorBoundary";
import { APP_NAME, EVENT, TITLE_TIMEOUT } from "../constants";
import { ImportedDataState } from "../data/types";
import {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "../element/types";
import { Language, t } from "../i18n";
import Excalidraw, {
defaultLang,
languages,
} from "../packages/excalidraw/index";
import { AppState, ExcalidrawAPIRefValue } from "../types";
import { debounce, ResolvablePromise, resolvablePromise } from "../utils";
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./app_constants";
import { EVENT_LOAD, EVENT_SHARE, trackEvent } from "../analytics";
import { ErrorDialog } from "../components/ErrorDialog";
import { getDefaultAppState } from "../appState";
import { APP_NAME, TITLE_TIMEOUT } from "../constants";
import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
import { LanguageList } from "./components/LanguageList";
import { exportToBackend, getCollaborationLinkData, loadScene } from "./data";
import { loadFromFirebase } from "./data/firebase";
import {
importFromLocalStorage,
saveToLocalStorage,
STORAGE_KEYS,
} from "./data/localStorage";
const languageDetector = new LanguageDetector();
languageDetector.init({
@ -163,7 +156,6 @@ const initializeScene = async (opts: {
// into the remote scene
opts.resetScene();
const scenePromise = opts.initializeSocketClient();
trackEvent(EVENT_SHARE, "session join");
try {
const [, roomId, roomKey] = getCollaborationLinkData(
@ -231,12 +223,6 @@ function ExcalidrawWrapper(props: { collab: CollabAPI }) {
const { collab } = props;
useEffect(() => {
const storageSize = getTotalStorageSize();
if (storageSize) {
trackEvent(EVENT_LOAD, "storage", "size", storageSize);
} else {
trackEvent(EVENT_LOAD, "first time");
}
excalidrawRef.current!.readyPromise.then((excalidrawApi) => {
initializeScene({
resetScene: excalidrawApi.resetScene,

View File

@ -1,5 +1,3 @@
import { EVENT_CHANGE, trackEvent } from "./analytics";
import fallbackLangData from "./locales/en.json";
import percentages from "./locales/percentages.json";
@ -67,7 +65,6 @@ export const setLanguage = async (lang: Language) => {
currentLangData = await import(
/* webpackChunkName: "i18n-[request]" */ `./locales/${currentLang.code}.json`
);
trackEvent(EVENT_CHANGE, "language", currentLang.code);
};
export const setLanguageFirstTime = async (lang: Language) => {

View File

@ -1,8 +1,7 @@
import { AppState } from "./types";
import { ExcalidrawElement } from "./element/types";
import { getElementsInGroup } from "./groups";
import { findLastIndex, findIndex } from "./utils";
import { trackEvent, EVENT_LAYER } from "./analytics";
import { AppState } from "./types";
import { findIndex, findLastIndex } from "./utils";
/**
* Returns indices of elements to move based on selected elements.
@ -176,7 +175,6 @@ const shiftElements = (
];
});
trackEvent(EVENT_LAYER, "move", direction === "left" ? "down" : "up");
return elements;
};
@ -234,7 +232,6 @@ const shiftElementsToEnd = (
const leadingElements = elements.slice(0, leadingIndex);
const trailingElements = elements.slice(trailingIndex + 1);
trackEvent(EVENT_LAYER, "move", direction === "left" ? "back" : "front");
return direction === "left"
? [
...leadingElements,