Log more user events

This commit is contained in:
Jordan Eldredge 2020-08-26 21:19:04 -07:00
parent 7032212002
commit 5e086ffeea
10 changed files with 112 additions and 14 deletions

View file

@ -46,6 +46,12 @@ export function attachLogger(webamp: WebmapLazy) {
action: "ToggleDoublesizeMode",
});
});
webamp._actionEmitter.on("TOGGLE_VISUALIZER_STYLE", () => {
log({
category: "Display",
action: "ToggleVisualizerStyle",
});
});
webamp._actionEmitter.on("SET_SKIN_DATA", () => {
log({
category: "Display",
@ -131,12 +137,14 @@ export function attachLogger(webamp: WebmapLazy) {
action: "InvertSelection",
});
});
/* This is triggered programatically when you load a new track
webamp._actionEmitter.on("REMOVE_ALL_TRACKS", () => {
log({
category: "Playlist",
action: "RemoveAllTracks",
});
});
*/
webamp._actionEmitter.on("REVERSE_LIST", () => {
log({
category: "Playlist",
@ -183,4 +191,32 @@ export function attachLogger(webamp: WebmapLazy) {
label: `${action.windowId}:${action.hidden ? "hidden" : "visibile"}`,
});
});
webamp._actionEmitter.on("MAIN_CONTEXT_MENU_OPENED", () => {
log({
category: "ContextMenu",
action: "MainContextMenuOpened",
});
});
webamp._actionEmitter.on("DROPPED_FILES", (action) => {
log({
category: "DroppedFiles",
action: action.windowId,
label: action.firstFileName ?? "[UNKNOWN]",
value: action.count,
});
});
webamp._actionEmitter.on("OPENED_FILES", (action) => {
log({
category: "OpenedFiles",
action: action.expectedType,
label: action.firstFileName ?? "[UNKNOWN]",
value: action.count,
});
});
webamp._actionEmitter.on("TOGGLE_LLAMA_MODE", () => {
log({
category: "Hotkeys",
action: "ToggledLlamaMode",
});
});
}

View file

@ -2,15 +2,18 @@ export function log({
category,
action,
label,
value,
}: {
category: string;
action: string;
label?: string;
value?: number;
}) {
// @ts-ignore
if (window.ga != null) {
window.ga("send", "event", category, action, label);
// @ts-ignore
window.ga("send", "event", category, action, label, value);
} else {
// console.log({ category, action, label });
// console.log({ category, action, label, value });
}
}

View file

@ -34,7 +34,14 @@ import LoadQueue from "../loadQueue";
import { removeAllTracks } from "./playlist";
import { setPreamp, setEqBand } from "./equalizer";
import { LoadStyle, Thunk, Track, EqfPreset, SkinData } from "../types";
import {
LoadStyle,
Thunk,
Track,
EqfPreset,
SkinData,
WindowId,
} from "../types";
// Lower is better
const DURATION_VISIBLE_PRIORITY = 5;
@ -138,23 +145,32 @@ export function setSkinFromUrl(url: string): Thunk {
// This function is private, since Winamp consumers can provide means for
// opening files via other methods. Only use the file type specific
// versions below, since they can defer to the user-defined behavior.
function _openFileDialog(accept: string | null): Thunk {
function _openFileDialog(
accept: string | null,
expectedType: "SKIN" | "MEDIA" | "EQ"
): Thunk {
return async (dispatch) => {
const fileReferences = await promptForFileReferences({ accept });
dispatch({
type: "OPENED_FILES",
expectedType,
count: fileReferences.length,
firstFileName: fileReferences[0]?.name,
});
dispatch(loadFilesFromReferences(fileReferences));
};
}
export function openEqfFileDialog(): Thunk {
return _openFileDialog(".eqf");
return _openFileDialog(".eqf", "EQ");
}
export function openMediaFileDialog(): Thunk {
return _openFileDialog(null);
return _openFileDialog(null, "MEDIA");
}
export function openSkinFileDialog() {
return _openFileDialog(".zip, .wsz");
return _openFileDialog(".zip, .wsz", "SKIN");
}
export function fetchMediaDuration(url: string, id: number): Thunk {
@ -443,3 +459,13 @@ export function saveFilesToList(): Thunk {
}
};
}
export function droppedFiles(e: React.DragEvent, windowId: WindowId): Thunk {
return (dispatch) =>
dispatch({
type: "DROPPED_FILES",
count: e.dataTransfer.files.length,
firstFileName: e.dataTransfer.files[0]?.name,
windowId,
});
}

View file

@ -96,6 +96,7 @@ export {
addFilesFromUrl,
addFilesFromList,
saveFilesToList,
droppedFiles,
} from "./files";
export {
cropPlaylist,

View file

@ -1,4 +1,7 @@
import React, { useCallback } from "react";
import { useActionCreator } from "../hooks";
import * as Actions from "../actionCreators";
import { WindowId } from "../types";
interface Coord {
x: number;
@ -7,6 +10,7 @@ interface Coord {
interface Props extends React.HTMLAttributes<HTMLDivElement> {
handleDrop(e: React.DragEvent<HTMLDivElement>, coord: Coord): void;
windowId: WindowId;
}
function supress(e: React.DragEvent<HTMLDivElement>) {
@ -20,12 +24,16 @@ const DropTarget = (props: Props) => {
const {
// eslint-disable-next-line no-shadow, no-unused-vars
handleDrop,
windowId,
...passThroughProps
} = props;
const droppedFiles = useActionCreator(Actions.droppedFiles);
const onDrop = useCallback(
(e: React.DragEvent<HTMLDivElement>) => {
supress(e);
droppedFiles(e, windowId);
// TODO: We could probably move this coordinate logic into the playlist.
// I think that's the only place it gets used.
const { currentTarget } = e;
@ -36,7 +44,7 @@ const DropTarget = (props: Props) => {
const { left: x, top: y } = currentTarget.getBoundingClientRect();
handleDrop(e, { x, y });
},
[handleDrop]
[handleDrop, droppedFiles, windowId]
);
return (
<div

View file

@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect } from "react";
import * as Actions from "../../actionCreators";
import * as Selectors from "../../selectors";
import { LOAD_STYLE } from "../../constants";
@ -13,7 +13,7 @@ interface Props {
filePickers: FilePicker[];
}
const MainContextMenu = React.memo((props: Props) => {
const MainContextMenu = React.memo(({ filePickers }: Props) => {
const networkConnected = useTypedSelector(Selectors.getNetworkConnected);
const genWindows = useTypedSelector(Selectors.getGenWindows);
@ -21,6 +21,12 @@ const MainContextMenu = React.memo((props: Props) => {
const openMediaFileDialog = useActionCreator(Actions.openMediaFileDialog);
const loadMediaFiles = useActionCreator(Actions.loadMediaFiles);
const toggleWindow = useActionCreator(Actions.toggleWindow);
const menuOpened = useActionCreator(() => ({
type: "MAIN_CONTEXT_MENU_OPENED",
}));
useEffect(() => {
menuOpened();
}, [menuOpened]);
return (
<React.Fragment>
@ -32,8 +38,8 @@ const MainContextMenu = React.memo((props: Props) => {
<Hr />
<Parent label="Play">
<Node onClick={openMediaFileDialog} label="File..." hotkey="L" />
{props.filePickers &&
props.filePickers.map(
{filePickers != null &&
filePickers.map(
(picker, i) =>
(networkConnected || !picker.requiresNetwork) && (
<Node

View file

@ -75,6 +75,7 @@ const MainWindow = React.memo(({ analyser, filePickers }: Props) => {
return (
<DropTarget
id="main-window"
windowId={WINDOWS.MAIN}
className={className}
handleDrop={loadMedia}
onWheel={scrollVolume}

View file

@ -133,7 +133,10 @@ function Milkdrop({ analyser }: Props) {
return (
<MilkdropContextMenu>
<Background>
<DropTarget handleDrop={handlePresetDrop}>
<DropTarget
windowId={WINDOWS.MILKDROP}
handleDrop={handlePresetDrop}
>
{overlay && <PresetOverlay {...size} />}
<Fullscreen enabled={fullscreen} onChange={setFullscreen}>
<div onDoubleClick={toggleFullscreen}>

View file

@ -93,6 +93,7 @@ function PlaylistWindow({ analyser }: Props) {
<FocusTarget windowId={WINDOWS.PLAYLIST}>
<DropTarget
id="playlist-window"
windowId={WINDOWS.PLAYLIST}
className={classes}
style={style}
handleDrop={handleDrop}

View file

@ -535,7 +535,20 @@ export type Action =
index: number;
transitionType: TransitionType;
}
| { type: "TOGGLE_PRESET_OVERLAY" };
| { type: "TOGGLE_PRESET_OVERLAY" }
| { type: "MAIN_CONTEXT_MENU_OPENED" }
| {
type: "DROPPED_FILES";
count: number;
firstFileName: string | null;
windowId: WindowId;
}
| {
type: "OPENED_FILES";
expectedType: "SKIN" | "MEDIA" | "EQ";
count: number;
firstFileName: string | null;
};
export type MediaTagRequestStatus =
| "INITIALIZED"