← back to Jill Website
public/js/connection-speed.js
196 lines
/**
* Connection Speed Detection Utility
* Detects user's connection speed and provides adaptive loading recommendations
*/
class ConnectionSpeedDetector {
constructor() {
this.connectionType = 'unknown';
this.effectiveType = 'unknown';
this.downlink = null;
this.rtt = null;
this.speedCategory = 'medium'; // slow, medium, fast
this.init();
}
/**
* Initialize connection speed detection
*/
init() {
// Use Network Information API if available
if ('connection' in navigator || 'mozConnection' in navigator || 'webkitConnection' in navigator) {
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
this.effectiveType = connection.effectiveType || 'unknown';
this.downlink = connection.downlink || null;
this.rtt = connection.rtt || null;
// Listen for connection changes
connection.addEventListener('change', () => {
this.updateConnectionInfo(connection);
});
this.categorizeSpeed();
}
}
// Fallback: Measure connection speed with a small image download
if (this.speedCategory === 'medium' && this.effectiveType === 'unknown') {
this.measureConnectionSpeed();
}
}
/**
* Update connection information
*/
updateConnectionInfo(connection) {
this.effectiveType = connection.effectiveType || 'unknown';
this.downlink = connection.downlink || null;
this.rtt = connection.rtt || null;
this.categorizeSpeed();
// Dispatch event for other components to react
window.dispatchEvent(new CustomEvent('connectionchange', {
detail: {
speedCategory: this.speedCategory,
effectiveType: this.effectiveType
}
}));
}
/**
* Categorize connection speed into slow, medium, or fast
*/
categorizeSpeed() {
// Based on effectiveType from Network Information API
// slow-2g, 2g, 3g, 4g
if (this.effectiveType === 'slow-2g' || this.effectiveType === '2g') {
this.speedCategory = 'slow';
} else if (this.effectiveType === '3g') {
this.speedCategory = 'medium';
} else if (this.effectiveType === '4g') {
this.speedCategory = 'fast';
}
// Use downlink speed if available (Mbps)
if (this.downlink !== null) {
if (this.downlink < 1) {
this.speedCategory = 'slow';
} else if (this.downlink < 5) {
this.speedCategory = 'medium';
} else {
this.speedCategory = 'fast';
}
}
// Use RTT (round-trip time) if available (ms)
if (this.rtt !== null) {
if (this.rtt > 500) {
this.speedCategory = 'slow';
} else if (this.rtt > 200) {
this.speedCategory = 'medium';
} else if (this.speedCategory !== 'slow') {
this.speedCategory = 'fast';
}
}
}
/**
* Measure connection speed with a test download
*/
async measureConnectionSpeed() {
try {
const startTime = performance.now();
// Use a small test image (1x1 pixel)
const testImage = new Image();
const imageUrl = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
// Use a real test - download a small resource
const response = await fetch('/css/style.css', {
method: 'HEAD',
cache: 'no-store'
});
const endTime = performance.now();
const duration = endTime - startTime;
// Categorize based on response time
if (duration > 1000) {
this.speedCategory = 'slow';
} else if (duration > 300) {
this.speedCategory = 'medium';
} else {
this.speedCategory = 'fast';
}
console.log(`Connection speed measured: ${duration.toFixed(0)}ms - Category: ${this.speedCategory}`);
} catch (error) {
console.warn('Failed to measure connection speed:', error);
// Default to medium if measurement fails
this.speedCategory = 'medium';
}
}
/**
* Get recommended image quality based on connection speed
*/
getImageQuality() {
switch (this.speedCategory) {
case 'slow':
return 'low'; // Low resolution, highly compressed
case 'medium':
return 'medium'; // Medium resolution
case 'fast':
return 'high'; // Full resolution
default:
return 'medium';
}
}
/**
* Check if videos should be enabled
*/
shouldEnableVideos() {
return this.speedCategory !== 'slow';
}
/**
* Get recommended video quality
*/
getVideoQuality() {
switch (this.speedCategory) {
case 'slow':
return 'disabled'; // Videos disabled
case 'medium':
return '480p'; // Lower quality
case 'fast':
return '1080p'; // Full HD
default:
return '720p';
}
}
/**
* Get connection information for debugging
*/
getInfo() {
return {
speedCategory: this.speedCategory,
effectiveType: this.effectiveType,
downlink: this.downlink,
rtt: this.rtt,
imageQuality: this.getImageQuality(),
videoQuality: this.getVideoQuality(),
videosEnabled: this.shouldEnableVideos()
};
}
}
// Export as global singleton
window.ConnectionSpeedDetector = ConnectionSpeedDetector;
window.connectionSpeed = new ConnectionSpeedDetector();