| |
| |
|
|
| class ConnectHubEnhancer { |
| constructor() { |
| this.isDarkMode = false; |
| this.voiceWaveform = null; |
| this.notificationPermission = false; |
| this.isOnline = navigator.onLine; |
| this.setupEventListeners(); |
| this.initializeEnhancements(); |
| } |
|
|
| |
| setupEventListeners() { |
| |
| window.addEventListener('online', () => { |
| this.isOnline = true; |
| this.showNetworkStatus(true); |
| }); |
|
|
| window.addEventListener('offline', () => { |
| this.isOnline = false; |
| this.showNetworkStatus(false); |
| }); |
|
|
| |
| document.addEventListener('keydown', (e) => { |
| this.handleKeyboardNavigation(e); |
| }); |
|
|
| |
| document.addEventListener('focusin', (e) => { |
| this.enhanceFocus(e.target); |
| }); |
| } |
|
|
| |
| async initializeEnhancements() { |
| await this.requestNotificationPermission(); |
| this.initializeDarkMode(); |
| this.enhanceVoiceRecording(); |
| this.improveAccessibility(); |
| this.addPerformanceOptimizations(); |
| this.setupNetworkStatus(); |
| } |
|
|
| |
| async requestNotificationPermission() { |
| if ('Notification' in window) { |
| const permission = await Notification.requestPermission(); |
| this.notificationPermission = permission === 'granted'; |
| |
| if (this.notificationPermission) { |
| console.log('✅ تم تفعيل الإشعارات'); |
| this.showNotification('مرحباً بك في ConnectHub!', { |
| body: 'ستتلقى إشعارات الأصدقاء والمنشورات الجديدة', |
| icon: '🌐' |
| }); |
| } |
| } |
| } |
|
|
| |
| initializeDarkMode() { |
| |
| const savedDarkMode = localStorage.getItem('darkMode') === 'true'; |
| |
| if (savedDarkMode) { |
| this.toggleDarkMode(true); |
| } |
|
|
| |
| this.addDarkModeToggle(); |
| } |
|
|
| |
| addDarkModeToggle() { |
| const navbar = document.querySelector('.navbar'); |
| if (!navbar) return; |
|
|
| const darkModeBtn = document.createElement('div'); |
| darkModeBtn.className = 'nav-icon dark-mode-toggle'; |
| darkModeBtn.innerHTML = '<i class="fas fa-moon"></i>'; |
| darkModeBtn.title = 'تبديل الوضع المظلم'; |
| darkModeBtn.setAttribute('aria-label', 'تبديل الوضع المظلم'); |
| darkModeBtn.tabIndex = 0; |
| |
| darkModeBtn.addEventListener('click', () => { |
| this.toggleDarkMode(); |
| }); |
|
|
| darkModeBtn.addEventListener('keydown', (e) => { |
| if (e.key === 'Enter' || e.key === ' ') { |
| e.preventDefault(); |
| this.toggleDarkMode(); |
| } |
| }); |
|
|
| |
| const navRight = navbar.querySelector('.nav-right'); |
| if (navRight) { |
| navRight.insertBefore(darkModeBtn, navRight.firstChild); |
| } |
| } |
|
|
| |
| toggleDarkMode(force = null) { |
| this.isDarkMode = force !== null ? force : !this.isDarkMode; |
| |
| document.body.classList.toggle('dark-mode', this.isDarkMode); |
| |
| |
| localStorage.setItem('darkMode', this.isDarkMode); |
| |
| |
| const toggleBtn = document.querySelector('.dark-mode-toggle i'); |
| if (toggleBtn) { |
| toggleBtn.className = this.isDarkMode ? 'fas fa-sun' : 'fas fa-moon'; |
| } |
|
|
| |
| const modeText = this.isDarkMode ? 'الوضع المظلم' : 'الوضع الفاتح'; |
| this.showNotification(`تم تفعيل ${modeText}`, { |
| body: 'يمكنك تغيير هذا الإعداد في أي وقت', |
| silent: true |
| }); |
| } |
|
|
| |
| enhanceVoiceRecording() { |
| |
| const voiceRecordingContainer = document.querySelector('.voice-recording-container'); |
| if (voiceRecordingContainer) { |
| const waveformContainer = document.createElement('div'); |
| waveformContainer.className = 'voice-waveform-container'; |
| waveformContainer.innerHTML = ` |
| <canvas class="voice-waveform" width="300" height="50"></canvas> |
| <div class="waveform-instructions">${getCurrentTranslation('hold_to_record') || 'اضغط مع الاستمرار للتسجيل'}</div> |
| `; |
| voiceRecordingContainer.appendChild(waveformContainer); |
| } |
|
|
| |
| this.enhanceMediaRecorder(); |
| } |
|
|
| |
| enhanceMediaRecorder() { |
| const originalGetUserMedia = navigator.mediaDevices.getUserMedia; |
| |
| navigator.mediaDevices.getUserMedia = async function(constraints) { |
| try { |
| const stream = await originalGetUserMedia.call(this, constraints); |
| |
| |
| if (stream.getAudioTracks().length > 0) { |
| |
| const audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
| const analyser = audioContext.createAnalyser(); |
| const source = audioContext.createMediaStreamSource(stream); |
| |
| analyser.fftSize = 256; |
| source.connect(analyser); |
| |
| |
| window.audioAnalyser = analyser; |
| } |
| |
| return stream; |
| } catch (error) { |
| console.error('خطأ في الوصول للميكروفون:', error); |
| throw error; |
| } |
| }; |
| } |
|
|
| |
| improveAccessibility() { |
| |
| this.addAriaLabels(); |
| |
| |
| this.enhanceKeyboardNavigation(); |
| |
| |
| this.enhanceAltTexts(); |
| |
| |
| this.enhanceContrast(); |
| } |
|
|
| |
| addAriaLabels() { |
| |
| const navIcons = document.querySelectorAll('.nav-icon'); |
| navIcons.forEach((icon, index) => { |
| const labels = [ |
| 'الصفحة الرئيسية', |
| 'الأصدقاء', |
| 'الفيديو المباشر', |
| 'المتجر', |
| 'المجموعات' |
| ]; |
| |
| if (labels[index]) { |
| icon.setAttribute('aria-label', labels[index]); |
| icon.setAttribute('role', 'button'); |
| } |
| }); |
|
|
| |
| const actionButtons = document.querySelectorAll('button'); |
| actionButtons.forEach(button => { |
| if (!button.getAttribute('aria-label') && !button.textContent.trim()) { |
| button.setAttribute('aria-label', 'زر إجراء'); |
| } |
| }); |
| } |
|
|
| |
| enhanceKeyboardNavigation() { |
| |
| if (!document.activeElement || document.activeElement === document.body) { |
| const firstInteractive = document.querySelector('button, [tabindex]:not([tabindex="-1"])'); |
| if (firstInteractive) { |
| firstInteractive.focus(); |
| } |
| } |
|
|
| |
| const style = document.createElement('style'); |
| style.textContent = ` |
| *:focus { |
| outline: 2px solid #667eea !important; |
| outline-offset: 2px !important; |
| } |
| |
| .keyboard-nav *:focus { |
| box-shadow: 0 0 0 2px #667eea, 0 0 0 4px rgba(102, 126, 234, 0.3) !important; |
| } |
| `; |
| document.head.appendChild(style); |
| } |
|
|
| |
| handleKeyboardNavigation(e) { |
| |
| if (e.ctrlKey && e.key === 'd') { |
| e.preventDefault(); |
| this.toggleDarkMode(); |
| } |
|
|
| |
| if (e.key === 'Escape') { |
| const modals = document.querySelectorAll('.modal, .popup'); |
| modals.forEach(modal => { |
| if (modal.style.display !== 'none') { |
| modal.style.display = 'none'; |
| } |
| }); |
| } |
|
|
| |
| if (e.ctrlKey && e.key === '/') { |
| e.preventDefault(); |
| this.showKeyboardShortcuts(); |
| } |
| } |
|
|
| |
| enhanceContrast() { |
| |
| const contrastStyle = document.createElement('style'); |
| contrastStyle.textContent = ` |
| @media (prefers-contrast: high) { |
| .login-box, |
| .signup-box, |
| .post-card, |
| .friend-card { |
| border: 2px solid #000; |
| background: #fff; |
| color: #000; |
| } |
| |
| .nav-icon:hover { |
| background-color: #000; |
| color: #fff; |
| } |
| } |
| `; |
| document.head.appendChild(contrastStyle); |
| } |
|
|
| |
| addPerformanceOptimizations() { |
| |
| this.optimizeImages(); |
| |
| |
| this.optimizeJavaScript(); |
| |
| |
| this.optimizeCSS(); |
| } |
|
|
| |
| optimizeImages() { |
| |
| const images = document.querySelectorAll('img'); |
| images.forEach(img => { |
| if (img.src.startsWith('https://via.placeholder.com')) { |
| |
| img.loading = 'lazy'; |
| img.decoding = 'async'; |
| |
| |
| img.addEventListener('load', function() { |
| this.style.opacity = '1'; |
| this.style.transition = 'opacity 0.3s ease'; |
| }); |
| } |
| }); |
| } |
|
|
| |
| optimizeJavaScript() { |
| |
| this.cacheElements(); |
| |
| |
| this.optimizeEventListeners(); |
| |
| |
| this.optimizeMemory(); |
| } |
|
|
| |
| cacheElements() { |
| this.cachedElements = { |
| navbar: document.querySelector('.navbar'), |
| mainPage: document.getElementById('mainPage'), |
| postsContainer: document.querySelector('.posts-container'), |
| friendsContainer: document.querySelector('.friends-container'), |
| notificationsContainer: document.querySelector('.notifications-container') |
| }; |
| } |
|
|
| |
| optimizeEventListeners() { |
| |
| document.addEventListener('click', (e) => { |
| this.handleClickOptimized(e); |
| }); |
| } |
|
|
| |
| optimizeMemory() { |
| |
| setInterval(() => { |
| this.cleanupUnusedData(); |
| }, 300000); |
| } |
|
|
| |
| setupNetworkStatus() { |
| this.createNetworkStatusIndicator(); |
| |
| |
| setInterval(() => { |
| this.updateNetworkStatus(); |
| }, 30000); |
| } |
|
|
| |
| createNetworkStatusIndicator() { |
| const indicator = document.createElement('div'); |
| indicator.className = 'network-status-indicator'; |
| indicator.innerHTML = ` |
| <div class="network-status ${this.isOnline ? 'online' : 'offline'}"> |
| <i class="fas ${this.isOnline ? 'fa-wifi' : 'fa-wifi-slash'}"></i> |
| <span>${this.isOnline ? 'متصل' : 'غير متصل'}</span> |
| </div> |
| `; |
| |
| |
| const style = document.createElement('style'); |
| style.textContent = ` |
| .network-status-indicator { |
| position: fixed; |
| top: 10px; |
| right: 10px; |
| z-index: 10000; |
| transition: all 0.3s ease; |
| } |
| |
| .network-status { |
| padding: 8px 16px; |
| border-radius: 20px; |
| font-size: 12px; |
| font-weight: 600; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
| } |
| |
| .network-status.online { |
| background: #10b981; |
| color: white; |
| } |
| |
| .network-status.offline { |
| background: #ef4444; |
| color: white; |
| } |
| `; |
| document.head.appendChild(style); |
| document.body.appendChild(indicator); |
| } |
|
|
| |
| showNetworkStatus(isOnline) { |
| const indicator = document.querySelector('.network-status-indicator'); |
| if (indicator) { |
| const status = indicator.querySelector('.network-status'); |
| const icon = status.querySelector('i'); |
| const text = status.querySelector('span'); |
| |
| status.className = `network-status ${isOnline ? 'online' : 'offline'}`; |
| icon.className = `fas ${isOnline ? 'fa-wifi' : 'fa-wifi-slash'}`; |
| text.textContent = isOnline ? 'متصل' : 'غير متصل'; |
| |
| |
| if (isOnline) { |
| setTimeout(() => { |
| indicator.style.opacity = '0'; |
| setTimeout(() => { |
| indicator.style.display = 'none'; |
| }, 300); |
| }, 3000); |
| } else { |
| indicator.style.display = 'block'; |
| indicator.style.opacity = '1'; |
| } |
| } |
| } |
|
|
| |
| showNotification(title, options = {}) { |
| if (this.notificationPermission && 'Notification' in window) { |
| new Notification(title, { |
| icon: options.icon || '🌐', |
| body: options.body || '', |
| silent: options.silent || false, |
| tag: options.tag || 'connecthub-notification', |
| requireInteraction: options.requireInteraction || false |
| }); |
| } |
| } |
|
|
| |
| addProgressiveWebAppFeatures() { |
| |
| this.createAppManifest(); |
| |
| |
| this.createServiceWorker(); |
| } |
|
|
| |
| createAppManifest() { |
| const manifest = { |
| name: "ConnectHub - منصة التواصل الاجتماعي المتقدمة", |
| short_name: "ConnectHub", |
| description: "منصة تواصل اجتماعي حديثة ومبتكرة", |
| start_url: "/", |
| display: "standalone", |
| background_color: "#f0f2f5", |
| theme_color: "#667eea", |
| orientation: "portrait-primary", |
| icons: [ |
| { |
| src: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192' viewBox='0 0 24 24'%3E%3Cpath fill='%23667eea' d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z'/%3E%3C/svg%3E", |
| sizes: "192x192", |
| type: "image/svg+xml" |
| } |
| ] |
| }; |
|
|
| const manifestBlob = new Blob([JSON.stringify(manifest, null, 2)], { type: 'application/json' }); |
| const manifestUrl = URL.createObjectURL(manifestBlob); |
| |
| const manifestLink = document.createElement('link'); |
| manifestLink.rel = 'manifest'; |
| manifestLink.href = manifestUrl; |
| document.head.appendChild(manifestLink); |
| } |
|
|
| |
| createServiceWorker() { |
| if ('serviceWorker' in navigator) { |
| const swCode = ` |
| const CACHE_NAME = 'connecthub-v1'; |
| const urlsToCache = [ |
| '/', |
| '/styles.css', |
| '/script.js', |
| '/translations.js' |
| ]; |
| |
| self.addEventListener('install', (event) => { |
| event.waitUntil( |
| caches.open(CACHE_NAME) |
| .then((cache) => cache.addAll(urlsToCache)) |
| ); |
| }); |
| |
| self.addEventListener('fetch', (event) => { |
| event.respondWith( |
| caches.match(event.request) |
| .then((response) => { |
| // إرجاع النسخة المخزنة إذا كانت متوفرة |
| if (response) { |
| return response; |
| } |
| return fetch(event.request); |
| }) |
| ); |
| }); |
| `; |
|
|
| const swBlob = new Blob([swCode], { type: 'application/javascript' }); |
| const swUrl = URL.createObjectURL(swBlob); |
| |
| navigator.serviceWorker.register(swUrl) |
| .then((registration) => { |
| console.log('✅ تم تسجيل Service Worker بنجاح'); |
| }) |
| .catch((error) => { |
| console.log('❌ فشل في تسجيل Service Worker:', error); |
| }); |
| } |
| } |
|
|
| |
| showKeyboardShortcuts() { |
| const shortcuts = ` |
| اختصارات لوحة المفاتيح في ConnectHub: |
| |
| الأساسي: |
| • Ctrl + D - تبديل الوضع المظلم |
| • Escape - إغلاق النوافذ المنبثقة |
| • Ctrl + / - عرض هذه المساعدة |
| |
| التنقل: |
| • Tab - التنقل للأمام |
| • Shift + Tab - التنقل للخلف |
| • Enter/Space - تفعيل العنصر |
| |
| الوصول: |
| • Alt + S - التركيز على البحث |
| • Alt + N - التركيز على الإشعارات |
| • Alt + P - التركيز على الملف الشخصي |
| `; |
|
|
| alert(shortcuts); |
| } |
| } |
|
|
| |
| document.addEventListener('DOMContentLoaded', () => { |
| window.connectHubEnhancer = new ConnectHubEnhancer(); |
| }); |
|
|
| |
| if (typeof module !== 'undefined' && module.exports) { |
| module.exports = ConnectHubEnhancer; |
| } |