/** * Swipe Integration Manager * Allows seamless switching between original and enhanced swipe systems */ import { showToast, updateImageInfo } from './utils.js'; import EnhancedSwipeCard from '../components/enhanced-swipe-card.js'; export class SwipeIntegrationManager { constructor() { this.currentMode = this.detectOptimalMode(); this.swipeCard = null; this.isInitialized = false; // Configuration options this.config = { enablePhysics: true, enableVisualEffects: true, enableHapticFeedback: true, animationQuality: 'auto', // 'low', 'medium', 'high', 'auto' performanceMode: 'auto', // 'low', 'normal', 'high', 'auto' debugMode: false }; // Load user preferences this.loadUserPreferences(); console.log(`SwipeIntegrationManager initialized in ${this.currentMode} mode`); } /** * Detect optimal swipe mode based on device capabilities */ detectOptimalMode() { const userAgent = navigator.userAgent.toLowerCase(); const isMobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/.test(userAgent); const isLowEnd = /android.*chrome\/[1-6][0-9]/.test(userAgent); const hasReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; // Check device memory if available const deviceMemory = navigator.deviceMemory || 4; const hasLowMemory = deviceMemory < 2; // Check connection speed if available let hasSlowConnection = false; if ('connection' in navigator) { const connection = navigator.connection; hasSlowConnection = connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g'; } // Determine optimal mode if (hasReducedMotion || isLowEnd || hasLowMemory || hasSlowConnection) { return 'original'; } else if (isMobile) { return 'enhanced-lite'; } else { return 'enhanced'; } } /** * Initialize the swipe system */ async initialize(container, onSwipe, options = {}) { if (this.isInitialized) { console.warn('SwipeIntegrationManager already initialized'); return; } // Merge options with config this.config = { ...this.config, ...options }; try { switch (this.currentMode) { case 'enhanced': await this.initializeEnhancedMode(container, onSwipe); break; case 'enhanced-lite': await this.initializeEnhancedLiteMode(container, onSwipe); break; case 'original': default: await this.initializeOriginalMode(container, onSwipe); break; } this.isInitialized = true; this.logInitialization(); } catch (error) { console.error('Failed to initialize swipe system:', error); // Clean up any partially initialized swipe card if (this.swipeCard && typeof this.swipeCard.destroy === 'function') { this.swipeCard.destroy(); this.swipeCard = null; } // Fallback to original mode await this.initializeOriginalMode(container, onSwipe); this.currentMode = 'original'; this.isInitialized = true; } } /** * Initialize enhanced mode with full physics */ async initializeEnhancedMode(container, onSwipe) { this.swipeCard = new EnhancedSwipeCard({ container, onSwipe, threshold: 100, velocityThreshold: 2.5, springTension: 320, springFriction: 25, mass: 1.0, momentumDecay: 0.90 }); // Add enhanced CSS classes document.body.classList.add('enhanced-swipe-mode'); container.classList.add('enhanced-container'); // Load enhanced styles if not already loaded await this.loadEnhancedStyles(); } /** * Initialize enhanced lite mode for mobile devices */ async initializeEnhancedLiteMode(container, onSwipe) { this.swipeCard = new EnhancedSwipeCard({ container, onSwipe, threshold: 80, velocityThreshold: 2.0, springTension: 280, springFriction: 30, mass: 1.2, momentumDecay: 0.92 }); // Add lite mode classes document.body.classList.add('enhanced-swipe-lite-mode'); container.classList.add('enhanced-container-lite'); // Disable some heavy effects for performance this.config.enableVisualEffects = false; await this.loadEnhancedStyles(); } /** * Initialize original mode as fallback */ async initializeOriginalMode(container, onSwipe) { // Import and initialize fallback swipe card const { default: FallbackSwipeCard } = await import('../components/fallback-swipe-card.js'); this.swipeCard = new FallbackSwipeCard({ container, onSwipe, threshold: 100 }); document.body.classList.add('original-swipe-mode'); } /** * Load enhanced styles dynamically */ async loadEnhancedStyles() { return new Promise((resolve, reject) => { // Check if enhanced styles are already loaded if (document.querySelector('link[href*="enhanced-animations"]')) { resolve(); return; } const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = 'scss/enhanced-animations.css'; // Compiled CSS link.onload = resolve; link.onerror = reject; document.head.appendChild(link); }); } /** * Switch between swipe modes dynamically */ async switchMode(newMode) { if (newMode === this.currentMode) { console.log(`Already in ${newMode} mode`); return; } console.log(`Switching from ${this.currentMode} to ${newMode} mode`); // Clean up current mode if (this.swipeCard && typeof this.swipeCard.destroy === 'function') { this.swipeCard.destroy(); } // Remove current mode classes document.body.classList.remove( 'enhanced-swipe-mode', 'enhanced-swipe-lite-mode', 'original-swipe-mode' ); // Update mode and reinitialize this.currentMode = newMode; this.isInitialized = false; // Save user preference this.saveUserPreference('swipeMode', newMode); // Show feedback to user showToast(`Switched to ${newMode} swipe mode`, 'info'); } /** * Get current swipe card instance */ getSwipeCard() { return this.swipeCard; } /** * Get current mode */ getCurrentMode() { return this.currentMode; } /** * Get available modes */ getAvailableModes() { return ['original', 'enhanced-lite', 'enhanced']; } /** * Update configuration */ updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; // Apply config changes to current swipe card if applicable if (this.swipeCard && typeof this.swipeCard.updateConfig === 'function') { this.swipeCard.updateConfig(this.config); } // Save configuration this.saveUserPreference('swipeConfig', this.config); } /** * Get current configuration */ getConfig() { return { ...this.config }; } /** * Load user preferences from localStorage */ loadUserPreferences() { try { const savedMode = localStorage.getItem('swipeMode'); if (savedMode && this.getAvailableModes().includes(savedMode)) { this.currentMode = savedMode; } const savedConfig = localStorage.getItem('swipeConfig'); if (savedConfig) { this.config = { ...this.config, ...JSON.parse(savedConfig) }; } } catch (error) { console.warn('Failed to load user preferences:', error); } } /** * Save user preference to localStorage */ saveUserPreference(key, value) { try { if (typeof value === 'object') { localStorage.setItem(key, JSON.stringify(value)); } else { localStorage.setItem(key, value); } } catch (error) { console.warn('Failed to save user preference:', error); } } /** * Performance monitoring */ getPerformanceMetrics() { if (this.swipeCard && typeof this.swipeCard.getPerformanceMetrics === 'function') { return this.swipeCard.getPerformanceMetrics(); } return null; } /** * Debug information */ getDebugInfo() { return { currentMode: this.currentMode, config: this.config, isInitialized: this.isInitialized, deviceInfo: { userAgent: navigator.userAgent, deviceMemory: navigator.deviceMemory, hardwareConcurrency: navigator.hardwareConcurrency, connection: navigator.connection ? { effectiveType: navigator.connection.effectiveType, downlink: navigator.connection.downlink } : null }, performanceMetrics: this.getPerformanceMetrics() }; } /** * Log initialization details */ logInitialization() { if (this.config.debugMode) { console.group('SwipeIntegrationManager Initialization'); console.log('Mode:', this.currentMode); console.log('Config:', this.config); console.log('Debug Info:', this.getDebugInfo()); console.groupEnd(); } } /** * Destroy the swipe system */ destroy() { if (this.swipeCard && typeof this.swipeCard.destroy === 'function') { this.swipeCard.destroy(); } // Remove mode classes document.body.classList.remove( 'enhanced-swipe-mode', 'enhanced-swipe-lite-mode', 'original-swipe-mode' ); this.swipeCard = null; this.isInitialized = false; console.log('SwipeIntegrationManager destroyed'); } } /** * Create settings panel for swipe mode selection */ export function createSwipeSettingsPanel(integrationManager) { const panel = document.createElement('div'); panel.className = 'swipe-settings-panel'; panel.innerHTML = `

Swipe Settings

`; // Set current values const config = integrationManager.getConfig(); panel.querySelector('#swipe-mode-select').value = integrationManager.getCurrentMode(); panel.querySelector('#enable-physics').checked = config.enablePhysics; panel.querySelector('#enable-visual-effects').checked = config.enableVisualEffects; panel.querySelector('#enable-haptic').checked = config.enableHapticFeedback; panel.querySelector('#animation-quality').value = config.animationQuality; // Event listeners panel.querySelector('.close-settings').addEventListener('click', () => { panel.remove(); }); panel.querySelector('#apply-settings').addEventListener('click', () => { const newMode = panel.querySelector('#swipe-mode-select').value; const newConfig = { enablePhysics: panel.querySelector('#enable-physics').checked, enableVisualEffects: panel.querySelector('#enable-visual-effects').checked, enableHapticFeedback: panel.querySelector('#enable-haptic').checked, animationQuality: panel.querySelector('#animation-quality').value }; integrationManager.updateConfig(newConfig); if (newMode !== integrationManager.getCurrentMode()) { integrationManager.switchMode(newMode); } showToast('Settings applied successfully', 'success'); }); panel.querySelector('#reset-settings').addEventListener('click', () => { integrationManager.updateConfig({ enablePhysics: true, enableVisualEffects: true, enableHapticFeedback: true, animationQuality: 'auto', performanceMode: 'auto' }); // Reset form values panel.querySelector('#enable-physics').checked = true; panel.querySelector('#enable-visual-effects').checked = true; panel.querySelector('#enable-haptic').checked = true; panel.querySelector('#animation-quality').value = 'auto'; showToast('Settings reset to defaults', 'info'); }); return panel; } // Export singleton instance export const swipeIntegration = new SwipeIntegrationManager();