diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f45fd2b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/helpers/plausible-tracker-sendbeacon"] + path = src/helpers/plausible-tracker-sendbeacon + url = https://github.com/orgrosua/plausible-tracker.git diff --git a/src/Main.tsx b/src/Main.tsx index 23bc138..c4a582f 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -5,7 +5,7 @@ import Home from "./Home" import { createSpotifyApi } from "./api" import App from "./app/App" import { Fallback } from "./components" -import { trackPlausibleEvent } from "./helpers/plausible" +import { PlausibleEvent, trackPlausibleEvent } from "./helpers/plausible" export default function Main() { const [spotify, setSpotify] = useState(null) @@ -26,7 +26,7 @@ export default function Main() { const { authenticated } = await sdk.authenticate() if (authenticated && !spotify) { setSpotify(sdk) - trackPlausibleEvent("Authenticated") + trackPlausibleEvent(PlausibleEvent.Authenticated) } } catch (e) { console.info("User is not authenticated", e) @@ -53,7 +53,7 @@ export default function Main() { Sentry.captureMessage("Authentication error", { extra: { error } }) } - trackPlausibleEvent("Authentication error", { props: { error } }) + trackPlausibleEvent(PlausibleEvent.AuthError, { props: { error } }) } }, []) @@ -65,7 +65,7 @@ export default function Main() { spotify.logOut() setSpotify(null) if (state !== "finished") { - trackPlausibleEvent("Logout", { props: { state } }) + trackPlausibleEvent(PlausibleEvent.Logout, { props: { state } }) } }} spotify={spotify} @@ -79,7 +79,7 @@ export default function Main() { { - trackPlausibleEvent("Login click") + trackPlausibleEvent(PlausibleEvent.LoginClick) try { setAuthError(null) const sdk = createSpotifyApi() @@ -93,7 +93,7 @@ export default function Main() { // @ts-ignore const error = new Error("Authenticating failed", { cause: e }) Sentry.captureException(error) - trackPlausibleEvent("Authentication failed") + trackPlausibleEvent(PlausibleEvent.AuthFailed) } }} /> diff --git a/src/app/App.tsx b/src/app/App.tsx index b292cdc..a49f671 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -2,6 +2,7 @@ import * as Sentry from "@sentry/react" import { SpotifyApi, User } from "@spotify/web-api-ts-sdk" import { useEffect, useState } from "preact/hooks" import { BaseButton, Button, Fallback, Scaffold } from "../components" +import { trackPlausibleEventPlaylistsUpdated } from "../helpers/plausible" import { NO_PROGRESS, PlaylistSelection as PlaylistWithSelection, @@ -76,7 +77,7 @@ export default function App({ } /** - * Move app's content here so error fallback still shows header and logout button. + * Move app's content here so error fallback still shows header and logout button */ const AppContent = ({ state, @@ -120,7 +121,7 @@ const AppContent = ({ return ( { + onDoReplace={async (selectedTracks, selectedVariants, metrics) => { try { setProgress(NO_PROGRESS) setState("replacing") @@ -149,6 +150,16 @@ const AppContent = ({ await replaceTracks(spotify, selectedPlaylists, setProgress), ) setState("finished") + + trackPlausibleEventPlaylistsUpdated( + selectedPlaylists.length, + selectedPlaylists.reduce( + (p, c) => p + c.stolenIdsToRemove.length, + 0, + ), + metrics.totalFoundTracks, + metrics.selectionCategories, + ) } catch (e) { setAsyncError(e) } diff --git a/src/app/playlisteditor/PlaylistEditor.tsx b/src/app/playlisteditor/PlaylistEditor.tsx index 349e386..b99b05b 100644 --- a/src/app/playlisteditor/PlaylistEditor.tsx +++ b/src/app/playlisteditor/PlaylistEditor.tsx @@ -18,14 +18,17 @@ export interface ReplaceViewData { const SELECTION_CATEGORIES = [ { + name: "replace-og-live", label: "Replace original live releases", predicate: (s: StolenVariants) => s.isLive, }, { + name: "replace-og-remixes", label: "Replace original remixes", predicate: (s: StolenVariants) => s.isRemix, }, { + name: "replace-og-special", label: ( <> Replace original special releases that don’t have a Taylor’s Version @@ -46,6 +49,12 @@ export default function PlaylistEditor({ onDoReplace: ( selectedTracks: Set[], selectedVariants: string[][], + metrics: { + selectionCategories: { + [name: string]: "yes" | "no" | "some" | "nonexistent" + } + totalFoundTracks: number + }, ) => void spotify: SpotifyApi }) { @@ -134,10 +143,11 @@ export default function PlaylistEditor({ return { exists, isAllSelected, isIndeterminate, toggle } } - const selectionCategories = SELECTION_CATEGORIES.map(c => ({ + const _selectionCategories = SELECTION_CATEGORIES.map(c => ({ ...c, ..._createCategory(c.predicate), - })).filter(c => c.exists) + })) + const selectionCategories = _selectionCategories.filter(c => c.exists) // ======================== // VARIANT EDITING @@ -202,7 +212,26 @@ export default function PlaylistEditor({