Skip to content

Commit

Permalink
feat(smartAvatar): ACT-759 download speed
Browse files Browse the repository at this point in the history
  • Loading branch information
yuri-wolf3d committed Aug 2, 2024
1 parent 084784c commit fd5f755
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 9 deletions.
55 changes: 46 additions & 9 deletions src/hooks/useDeviceDetector/use-device-detector.hook.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { getGPUTier, TierResult } from 'detect-gpu';
import { getGPUTier, TierResult as GpuTierResult } from 'detect-gpu';
import { stringify } from 'qs';
import { checkDownloadSpeed } from 'src/services/DownloadSpeed.service';

type TierPresets = { [key: number]: Record<string, any> };

Expand All @@ -16,25 +17,48 @@ const TIER_PRESETS: TierPresets = {
}
};

type NetworkTierResult = {
downloadSpeed: number;
tier: number;
};

// in mbps
const networkTierGrades = {
1: 1,
2: 3,
3: Infinity
};

type DeviceDetectorServiceProps = {
gpuTierResult: TierResult;
gpuTierResult: GpuTierResult;
networkTierResult: NetworkTierResult;
tierPresets?: TierPresets;
};

class DeviceDetectorService {
private tierPresets: TierPresets = TIER_PRESETS;

private gpuTierResult: TierResult;
private gpuTierResult: GpuTierResult;

private networkTierResult: NetworkTierResult;

constructor(props: DeviceDetectorServiceProps) {
this.gpuTierResult = props.gpuTierResult;
this.networkTierResult = props.networkTierResult;
if (props.tierPresets) {
this.tierPresets = props.tierPresets;
this.tierPresets = { ...TIER_PRESETS, ...props.tierPresets };
}
}

get result() {
return {
gpu: this.gpuTierResult,
network: this.networkTierResult
};
}

toQueryString() {
return stringify(this.tierPresets[this.gpuTierResult.tier]);
return stringify(this.tierPresets[Math.min(this.gpuTierResult.tier, this.networkTierResult.tier)]);
}
}

Expand All @@ -47,20 +71,33 @@ export function useDeviceDetector(options?: DeviceDetectorHookProps) {

useEffect(() => {
const fetchDeviceDetector = async () => {
let gpuTierResult: TierResult = { type: 'BENCHMARK', tier: 3 };

let gpuTierResult: GpuTierResult = { type: 'BENCHMARK', tier: 3 };
let networkTierResult: NetworkTierResult = { downloadSpeed: 100, tier: 3 };
try {
gpuTierResult = await getGPUTier();

// Safari fails to detect the GPU tier, so we set it to the highest tier
if (gpuTierResult.type !== 'BENCHMARK') {
gpuTierResult.tier = 3;
}

const downloadSpeed = await checkDownloadSpeed('https://models.readyplayer.me/6613f5defa73bfcb698a92fd.png');

let tier = 3;
if (downloadSpeed < networkTierGrades[1]) {
tier = 1;
} else if (downloadSpeed < networkTierGrades[2]) {
tier = 2;
}

networkTierResult = {
downloadSpeed,
tier
};
} catch (error) {
console.error(error);

Check warning on line 97 in src/hooks/useDeviceDetector/use-device-detector.hook.ts

View workflow job for this annotation

GitHub Actions / Linting

Unexpected console statement
}

setDeviceDetector(new DeviceDetectorService({ gpuTierResult, ...options }));
setDeviceDetector(new DeviceDetectorService({ gpuTierResult, networkTierResult, ...options }));
};
fetchDeviceDetector();
}, []);

Check warning on line 103 in src/hooks/useDeviceDetector/use-device-detector.hook.ts

View workflow job for this annotation

GitHub Actions / Linting

React Hook useEffect has a missing dependency: 'options'. Either include it or remove the dependency array. If 'setDeviceDetector' needs the current value of 'options', you can also switch to useReducer instead of useState and read 'options' in the reducer
Expand Down
17 changes: 17 additions & 0 deletions src/services/DownloadSpeed.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export async function checkDownloadSpeed(baseUrl: string): Promise<number> {
const startTime = performance.now();

const response = await fetch(baseUrl);

const data = await response.blob();

const endTime = performance.now();

const duration = (endTime - startTime) / 1000; // convert to seconds
const sizeInBytes = data.size;
const sizeInMegabits = (sizeInBytes * 8) / (1024 * 1024); // convert to megabits

const speedMbps = sizeInMegabits / duration;

return speedMbps;
}

0 comments on commit fd5f755

Please sign in to comment.