Bug fixes

This commit is contained in:
Aodhan Collins
2025-07-31 01:38:07 +01:00
parent ec6d40bf8f
commit 5e893a0c9d
12 changed files with 3917 additions and 212 deletions

471
js/swipe-integration.js Normal file
View File

@@ -0,0 +1,471 @@
/**
* 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 = `
<div class="settings-header">
<h3>Swipe Settings</h3>
<button class="close-settings">×</button>
</div>
<div class="settings-content">
<div class="setting-group">
<label>Swipe Mode:</label>
<select id="swipe-mode-select">
<option value="original">Original (Compatible)</option>
<option value="enhanced-lite">Enhanced Lite (Mobile)</option>
<option value="enhanced">Enhanced (Full Physics)</option>
</select>
</div>
<div class="setting-group">
<label>
<input type="checkbox" id="enable-physics"> Enable Physics
</label>
</div>
<div class="setting-group">
<label>
<input type="checkbox" id="enable-visual-effects"> Visual Effects
</label>
</div>
<div class="setting-group">
<label>
<input type="checkbox" id="enable-haptic"> Haptic Feedback
</label>
</div>
<div class="setting-group">
<label>Animation Quality:</label>
<select id="animation-quality">
<option value="auto">Auto</option>
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
</div>
<div class="settings-actions">
<button id="apply-settings" class="apply-btn">Apply</button>
<button id="reset-settings" class="reset-btn">Reset</button>
</div>
</div>
`;
// 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();