init
This commit is contained in:
192
videocall-frontend/src/services/utils.js
Normal file
192
videocall-frontend/src/services/utils.js
Normal file
@@ -0,0 +1,192 @@
|
||||
// src/services/utils.js - Utility functions
|
||||
export const utils = {
|
||||
/**
|
||||
* Generate random string
|
||||
*/
|
||||
generateRandomString(length = 8) {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
let result = ''
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += chars.charAt(Math.floor(Math.random() * chars.length))
|
||||
}
|
||||
return result
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy text to clipboard
|
||||
*/
|
||||
async copyToClipboard(text) {
|
||||
try {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
await navigator.clipboard.writeText(text)
|
||||
return { success: true }
|
||||
} else {
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement('textarea')
|
||||
textArea.value = text
|
||||
textArea.style.position = 'fixed'
|
||||
textArea.style.left = '-999999px'
|
||||
textArea.style.top = '-999999px'
|
||||
document.body.appendChild(textArea)
|
||||
textArea.focus()
|
||||
textArea.select()
|
||||
|
||||
const success = document.execCommand('copy')
|
||||
textArea.remove()
|
||||
|
||||
return { success }
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to copy to clipboard:', error)
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Debounce function
|
||||
*/
|
||||
debounce(func, wait) {
|
||||
let timeout
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout)
|
||||
func(...args)
|
||||
}
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(later, wait)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Throttle function
|
||||
*/
|
||||
throttle(func, limit) {
|
||||
let inThrottle
|
||||
return function (...args) {
|
||||
if (!inThrottle) {
|
||||
func.apply(this, args)
|
||||
inThrottle = true
|
||||
setTimeout(() => (inThrottle = false), limit)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Format time duration
|
||||
*/
|
||||
formatDuration(seconds) {
|
||||
const hrs = Math.floor(seconds / 3600)
|
||||
const mins = Math.floor((seconds % 3600) / 60)
|
||||
const secs = Math.floor(seconds % 60)
|
||||
|
||||
if (hrs > 0) {
|
||||
return `${hrs}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
||||
} else {
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Format relative time
|
||||
*/
|
||||
formatRelativeTime(date) {
|
||||
const now = new Date()
|
||||
const diffInSeconds = Math.floor((now - date) / 1000)
|
||||
|
||||
if (diffInSeconds < 60) {
|
||||
return 'Just now'
|
||||
} else if (diffInSeconds < 3600) {
|
||||
const minutes = Math.floor(diffInSeconds / 60)
|
||||
return `${minutes} minute${minutes === 1 ? '' : 's'} ago`
|
||||
} else if (diffInSeconds < 86400) {
|
||||
const hours = Math.floor(diffInSeconds / 3600)
|
||||
return `${hours} hour${hours === 1 ? '' : 's'} ago`
|
||||
} else {
|
||||
const days = Math.floor(diffInSeconds / 86400)
|
||||
return `${days} day${days === 1 ? '' : 's'} ago`
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Validate URL
|
||||
*/
|
||||
isValidUrl(string) {
|
||||
try {
|
||||
new URL(string)
|
||||
return true
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate QR code data URL
|
||||
*/
|
||||
async generateQRCode(text, options = {}) {
|
||||
const QRCode = await import('qrcode')
|
||||
|
||||
const defaultOptions = {
|
||||
width: 256,
|
||||
margin: 2,
|
||||
color: {
|
||||
dark: '#000000',
|
||||
light: '#ffffff',
|
||||
},
|
||||
}
|
||||
|
||||
try {
|
||||
const dataURL = await QRCode.toDataURL(text, { ...defaultOptions, ...options })
|
||||
return { success: true, dataURL }
|
||||
} catch (error) {
|
||||
console.error('Failed to generate QR code:', error)
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Detect mobile device
|
||||
*/
|
||||
isMobileDevice() {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||
navigator.userAgent,
|
||||
)
|
||||
},
|
||||
|
||||
/**
|
||||
* Detect iOS device
|
||||
*/
|
||||
isIOSDevice() {
|
||||
return /iPad|iPhone|iPod/.test(navigator.userAgent)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get browser info
|
||||
*/
|
||||
getBrowserInfo() {
|
||||
const userAgent = navigator.userAgent
|
||||
let browserName = 'Unknown'
|
||||
let browserVersion = 'Unknown'
|
||||
|
||||
if (userAgent.indexOf('Chrome') > -1) {
|
||||
browserName = 'Chrome'
|
||||
browserVersion = userAgent.match(/Chrome\/([0-9.]+)/)?.[1] || 'Unknown'
|
||||
} else if (userAgent.indexOf('Safari') > -1) {
|
||||
browserName = 'Safari'
|
||||
browserVersion = userAgent.match(/Version\/([0-9.]+)/)?.[1] || 'Unknown'
|
||||
} else if (userAgent.indexOf('Firefox') > -1) {
|
||||
browserName = 'Firefox'
|
||||
browserVersion = userAgent.match(/Firefox\/([0-9.]+)/)?.[1] || 'Unknown'
|
||||
} else if (userAgent.indexOf('Edge') > -1) {
|
||||
browserName = 'Edge'
|
||||
browserVersion = userAgent.match(/Edge\/([0-9.]+)/)?.[1] || 'Unknown'
|
||||
}
|
||||
|
||||
return {
|
||||
name: browserName,
|
||||
version: browserVersion,
|
||||
userAgent: userAgent,
|
||||
isMobile: this.isMobileDevice(),
|
||||
isIOS: this.isIOSDevice(),
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user