Skip to content

Commit

Permalink
fix: report usage stats
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 committed Oct 17, 2021
1 parent 047fac7 commit 9982134
Show file tree
Hide file tree
Showing 19 changed files with 120 additions and 16 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"start": "concurrently --kill-others-on-fail -n extension,services -c magenta,cyan \"pnpm start:extension\" \"pnpm start:services\"",
"start:chrome": "concurrently --kill-others-on-fail -n extension,services -c magenta,cyan \"pnpm start:extension -- --for chrome\" \"pnpm start:services\"",
"start:extension": "ts-node vite.build.ts --watch",
"start:prod": "ts-node vite.build.ts --watch --mode prod",
"start:services": "docker-compose -f docker/docker-compose.yml up --abort-on-container-exit",
"compile": "vue-tsc --noEmit",
"test": "jest --runInBand",
Expand All @@ -38,6 +39,7 @@
},
"dependencies": {
"@anime-skip/ui": "^1.2.5",
"@anime-skip/usage-stats-client": "^1.1.4",
"async-mutex": "^0.3.2",
"axios": "^0.21.1",
"axios-auth-refresh": "^3.1.0",
Expand Down
12 changes: 11 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/common/api/login.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GqlLoginData, GqlPreferences } from '@anime-skip/axios-api';
import { GqlAccount, GqlLoginData, GqlPreferences } from '@anime-skip/axios-api';

export type Preferences = Pick<
GqlPreferences,
Expand All @@ -18,8 +18,7 @@ export type Preferences = Pick<
| 'skipNewCredits'
| 'skipPreview'
>;
export interface Account {
// extends Pick<GqlAccount, ...>
export interface Account extends Pick<GqlAccount, 'id'> {
preferences: Preferences;
}
export interface LoginResponse extends Pick<GqlLoginData, 'authToken' | 'refreshToken'> {
Expand All @@ -33,6 +32,7 @@ export const PREFERENCES_QUERY = `{
export const LOGIN_QUERY = `{
authToken refreshToken
account {
id
preferences ${PREFERENCES_QUERY}
}
}`;
2 changes: 2 additions & 0 deletions src/common/hooks/useApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createCustomAnimeSkipClient } from '~/common/utils/CustomApiClient';
import { useClearTokens } from '../state/useAuth';
import { useResetPreferences } from '../state/useGeneralPreferences';
import { LogoutError } from '../utils/LogoutError';
import UsageStats from '../utils/UsageStats';
import Utils from '../utils/Utils';
import useTokenRefresher from './useTokenRefresher';

Expand Down Expand Up @@ -107,6 +108,7 @@ export function useApiClient() {
console.warn('Logging out...');
clearTokens();
resetPreferences();
void UsageStats.saveEvent('forced_logout').then(UsageStats.clearUserId);
}
throw err;
}
Expand Down
3 changes: 3 additions & 0 deletions src/common/hooks/useLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import md5 from 'md5';
import * as Api from '~api';
import { useUpdateAuth } from '../state/useAuth';
import { useUpdateGeneralPreferences } from '../state/useGeneralPreferences';
import UsageStats from '../utils/UsageStats';
import { useApiClient } from './useApiClient';

export function useLogin(api = useApiClient()) {
Expand All @@ -21,6 +22,8 @@ export function useLogin(api = useApiClient()) {
updatePreferences({
...res.account.preferences,
});
await UsageStats.setUserId(res.account.id);
void UsageStats.saveEvent('login');

return res;
};
Expand Down
2 changes: 2 additions & 0 deletions src/common/hooks/useTokenRefresher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AxiosResponse } from 'axios';
import * as Api from '~api';
import { getAuthAsync, updateAuthAsync } from '../state/useAuth';
import { LogoutError } from '../utils/LogoutError';
import UsageStats from '../utils/UsageStats';

const lock = new Mutex();

Expand Down Expand Up @@ -46,6 +47,7 @@ export default function useTokenRefresher(client: ReturnType<typeof createAnimeS
refreshToken: auth.refreshToken,
});
await updateAuthAsync({ refreshToken: newTokens.refreshToken, token: newTokens.authToken });
void UsageStats.saveEvent('login_refresh');
console.log('Refreshed token!');
release();
} catch (err) {
Expand Down
33 changes: 33 additions & 0 deletions src/common/utils/UsageStats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { createUsageStatsClient } from '@anime-skip/usage-stats-client';
import { browser } from 'webextension-polyfill-ts';
import Browser from './Browser';

declare const EXTENSION_VERSION: string;

export const USAGE_STATS_USER_ID_STORAGE_KEY = 'usage-stats-user-id';

const client = createUsageStatsClient({
app: 'Anime Skip Player',
appVersion: EXTENSION_VERSION,
browser: Browser.detect(),
async getUserId() {
const results = await browser.storage.local.get(USAGE_STATS_USER_ID_STORAGE_KEY);
return results[USAGE_STATS_USER_ID_STORAGE_KEY];
},
log: console.log,
async persistGuestUserId(userId) {
browser.storage.local.set({ [USAGE_STATS_USER_ID_STORAGE_KEY]: userId });
},
send: import.meta.env.VITE_EXT_MODE === 'prod' || import.meta.env.VITE_EXT_MODE === 'beta',
source: 'browser',
});

export default {
async setUserId(userId: string): Promise<void> {
await browser.storage.local.set({ [USAGE_STATS_USER_ID_STORAGE_KEY]: userId });
},
async clearUserId(): Promise<void> {
await browser.storage.local.remove(USAGE_STATS_USER_ID_STORAGE_KEY);
},
...client,
};
7 changes: 7 additions & 0 deletions src/content-scripts/player/components/TimelineWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { computed, ref, watch } from 'vue';
import { useIsLoggedIn } from '~/common/state/useAuth';
import { useGeneralPreferences } from '~/common/state/useGeneralPreferences';
import { TIMESTAMP_TYPES } from '~/common/utils/Constants';
import UsageStats from '~/common/utils/UsageStats';
import Utils from '~/common/utils/Utils';
import * as Api from '~api';
import { useDisplayedTimestamps } from '../hooks/useDisplayedTimestamps';
Expand Down Expand Up @@ -156,6 +157,12 @@ watch(currentTime, (newTime, oldTime) => {
if (wasAtBeginning && haveNotSkippedFromBeginning && shouldSkipFirstTimestamp) {
updatePlayHistory({ hasSkippedFromZero: true });
goToNextTimestampOnTimeChange(newTime);
void UsageStats.saveEvent('skipped_timestamp', {
fromTime: oldTime,
toTime: newTime,
skippedDuration: oldTime - newTime,
typeId: oldNext.typeId,
});
return;
}
Expand Down
2 changes: 2 additions & 0 deletions src/content-scripts/player/hooks/useCreateNewTimestamp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useIsLoggedIn } from '~/common/state/useAuth';
import { TIMESTAMP_TYPE_NOT_SELECTED } from '~/common/utils/Constants';
import UsageStats from '~/common/utils/UsageStats';
import Utils from '~/common/utils/Utils';
import { TimestampSource } from '~api';
import { useShowDialog, useShowLoginOverlay } from '../state/useDialogState';
Expand Down Expand Up @@ -38,6 +39,7 @@ export function useCreateNewTimestamp() {
return;
}

void UsageStats.saveEvent('started_creating_timestamp', { atTime: video.currentTime });
startEditing(() => {
updateEditTimestampMode(EditTimestampMode.ADD);
updateActiveTimestamp({
Expand Down
6 changes: 5 additions & 1 deletion src/content-scripts/player/hooks/useKeyboardShortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
usePrimaryKeyboardShortcutPrefs,
useSecondaryKeyboardShortcutPrefs,
} from '~/common/state/useKeyboardShortcutPrefs';
import UsageStats from '~/common/utils/UsageStats';
import Utils from '~/common/utils/Utils';

export function useKeyboardShortcuts(
Expand All @@ -29,7 +30,10 @@ export function useKeyboardShortcuts(

console.debug(`[${componentName}] Pressed ${keyCombo} -> [${keyActions.join(', ')}]`);
setTimeout(() => {
keyActions.forEach(action => shortcuts[action]?.());
keyActions.forEach(action => {
void UsageStats.saveEvent('used_keyboard_shortcut', { keyCombo, operation: action });
shortcuts[action]?.();
});
}, 0);
};

Expand Down
12 changes: 12 additions & 0 deletions src/content-scripts/player/hooks/useVideoElement.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import UsageStats from '~/common/utils/UsageStats';
import {
useIncrementPlayTicks,
usePlayHistory,
Expand All @@ -22,6 +23,9 @@ export function useVideoElement() {
updateCurrentTime();
};
const startedPlaying = () => {
if (playHistory.isInitialBuffer && videoState.duration) {
void UsageStats.saveEvent('episode_started', { episodeDuration: videoState.duration });
}
controls.clearBuffering();
updatePlayHistory({ isInitialBuffer: false });
if (video.value && !video.value.paused) {
Expand Down Expand Up @@ -103,6 +107,12 @@ export function useVideoElement() {
}
);

const onVideoEnded = () => {
if (videoState.duration) {
void UsageStats.saveEvent('episode_finished', { episodeDuration: videoState.duration });
}
};

const setListeners = (video: HTMLVideoElement) => {
video.addEventListener('durationchange', updateDuration);
video.addEventListener('loadedmetadata', initialLoad);
Expand All @@ -112,6 +122,7 @@ export function useVideoElement() {
video.addEventListener('timeupdate', updateCurrentTime);
video.addEventListener('volumechange', enforceVolumeChange);
video.addEventListener('waiting', setBuffering);
video.addEventListener('ended', onVideoEnded);
};
const clearListeners = (video: HTMLVideoElement) => {
video.removeEventListener('durationchange', updateDuration);
Expand All @@ -122,6 +133,7 @@ export function useVideoElement() {
video.removeEventListener('timeupdate', updateCurrentTime);
video.removeEventListener('volumechange', enforceVolumeChange);
video.removeEventListener('waiting', setBuffering);
video.removeEventListener('ended', onVideoEnded);
};
window.onVideoChanged(newVideo => {
if (video.value) clearListeners(video.value);
Expand Down
2 changes: 2 additions & 0 deletions src/content-scripts/player/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'vue-global-api';
import FakeRouterLink from '~/common/components/FakeRouterLink.vue';
import '~/common/styles';
import { loadedLog } from '~/common/utils/loadedLog';
import UsageStats from '~/common/utils/UsageStats';
import Container from './Container.vue';

loadedLog('content-scripts/player/index.ts');
Expand Down Expand Up @@ -52,6 +53,7 @@ async function injectPlayer() {
document.querySelector(rootQuery)?.appendChild(mountedApp.$el);

console.log(`Added player to ${rootQuery}`);
void UsageStats.saveEvent('player_injected');
} catch (err) {
console.warn('Failed to inject player UI', err);
}
Expand Down
3 changes: 3 additions & 0 deletions src/content-scripts/player/state/useVideoState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Utils as UiUtils } from '@anime-skip/ui';
import { createProvideInject } from '~/common/utils/createProvideInject';
import UsageStats from '~/common/utils/UsageStats';

export interface VideoState {
/**
Expand Down Expand Up @@ -83,6 +84,8 @@ export function useVideoController() {
update({ isPaused: true });
},
togglePlayPause(): void {
if (state.isPaused) void UsageStats.saveEvent('play', { atTime: state.currentTime });
else void UsageStats.saveEvent('pause', { atTime: state.currentTime });
update({ isPaused: !state.isPaused });
},
setPlaybackRate(newPlaybackRate: number): void {
Expand Down
1 change: 1 addition & 0 deletions src/manifest.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"tabs",
"{{chrome}}.declarativeContent",
"{{firefox}}.*://api.anime-skip.com/*",
"{{firefox}}.*://usage-stats.anime-skip.com/*",
"{{firefox}}.*://staged.api.anime-skip.com/*"
],
"{{manifest-v3:remove-this-qualifier-once-v3}}.host_permissions": [
Expand Down
5 changes: 5 additions & 0 deletions src/views/options/Options.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
import { computed } from 'vue';
import { useIsLoggedIn } from '~/common/state/useAuth';
import { useGeneralPreferences, useToggleBooleanPref } from '~/common/state/useGeneralPreferences';
import UsageStats from '~/common/utils/UsageStats';
onMounted(() => {
void UsageStats.saveEvent('opened_all_settings');
});
const isLoggedIn = useIsLoggedIn();
const preferences = useGeneralPreferences();
Expand Down
5 changes: 5 additions & 0 deletions src/views/popup/Popup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
<script lang="ts" setup>
import { useIsLoggedIn } from '~/common/state/useAuth';
import Browser from '~/common/utils/Browser';
import UsageStats from '~/common/utils/UsageStats';
defineProps<{
small?: boolean;
}>();
onMounted(() => {
void UsageStats.saveEvent('opened_popup');
});
const browser = Browser.detect();
const isLoggedIn = useIsLoggedIn();
Expand Down
13 changes: 2 additions & 11 deletions src/views/popup/components/PopupPreferences.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,11 @@

<script lang="ts" setup>
import useRequestState from 'vue-use-request-state';
import { useClearTokens } from '~/common/state/useAuth';
import { useResetPreferences } from '~/common/state/useGeneralPreferences';
import { sleep } from '~/common/utils/EventLoop';
import Messenger from '~/common/utils/Messenger';
const clearTokens = useClearTokens();
const resetPreferences = useResetPreferences();
import { useLogout } from '../composition/useLogout';
const { wrapRequest, isLoading: isLoggingOut } = useRequestState();
const logOut = wrapRequest(async () => {
await sleep(500);
clearTokens();
resetPreferences();
});
const logOut = wrapRequest(useLogout());
const openExtensionOptions = () => {
new Messenger<RuntimeMessageTypes>('General Settings').send(
Expand Down
16 changes: 16 additions & 0 deletions src/views/popup/composition/useLogout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useClearTokens } from '~/common/state/useAuth';
import { useResetPreferences } from '~/common/state/useGeneralPreferences';
import { sleep } from '~/common/utils/EventLoop';
import UsageStats from '~/common/utils/UsageStats';

export function useLogout() {
const clearTokens = useClearTokens();
const resetPreferences = useResetPreferences();

return async () => {
await sleep(500);
clearTokens();
resetPreferences();
void UsageStats.saveEvent('logout').then(UsageStats.clearUserId);
};
}
4 changes: 4 additions & 0 deletions vite.build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import path from 'path';
import * as Vite from 'vite';
import ViteComponents from 'vite-plugin-components';
import ViteIcons, { ViteIconsResolver } from 'vite-plugin-icons';
import packageJson from './package.json';
import { rootPath } from './scripts/utils';
import { getManifest } from './src/manifest';
import AssetsRewrite from './vite/plugin-assets-rewrite';
Expand Down Expand Up @@ -84,6 +85,9 @@ async function getConfig(
}
: undefined,
},
define: {
EXTENSION_VERSION: `'${packageJson.version}'`,
},
mode: options.watch ? 'development' : 'production',
resolve: {
alias: {
Expand Down

0 comments on commit 9982134

Please sign in to comment.