← 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();