193 lines
4.7 KiB
JavaScript
193 lines
4.7 KiB
JavaScript
// 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(),
|
|
}
|
|
},
|
|
}
|