user-agent-label.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /**
  2. * Plain-words names for a browser or phone, from its user agent. Pure, so the
  3. * signed-in devices list (server) and a new passkey's name (browser) say the
  4. * same thing about the same device.
  5. */
  6. /**
  7. * "Chrome on Windows", "Safari on iPhone": enough for a person to recognise
  8. * their own device in a mail or a list, from a user agent string. Not a
  9. * fingerprint; the cookie does that.
  10. */
  11. export function describeUserAgent(userAgent: string | null | undefined): string {
  12. const ua = userAgent ?? ''
  13. if (!ua) return 'Unknown device'
  14. if (/Torqvoice|Expo|okhttp|Dart|CFNetwork/i.test(ua) && !/Mozilla/i.test(ua)) {
  15. return 'Torqvoice technician app'
  16. }
  17. const os = /iPhone/.test(ua)
  18. ? 'iPhone'
  19. : /iPad/.test(ua)
  20. ? 'iPad'
  21. : /Android/.test(ua)
  22. ? 'Android'
  23. : /Windows/.test(ua)
  24. ? 'Windows'
  25. : /Mac OS X|Macintosh/.test(ua)
  26. ? 'Mac'
  27. : /CrOS/.test(ua)
  28. ? 'ChromeOS'
  29. : /Linux/.test(ua)
  30. ? 'Linux'
  31. : null
  32. const browser = /Edg\//.test(ua)
  33. ? 'Edge'
  34. : /OPR\/|Opera/.test(ua)
  35. ? 'Opera'
  36. : /SamsungBrowser/.test(ua)
  37. ? 'Samsung Internet'
  38. : /Firefox\//.test(ua)
  39. ? 'Firefox'
  40. : /Chrome\/|CriOS\//.test(ua)
  41. ? 'Chrome'
  42. : /Safari\//.test(ua)
  43. ? 'Safari'
  44. : null
  45. if (browser && os) return `${browser} on ${os}`
  46. return browser ?? os ?? 'Unknown device'
  47. }
  48. export type DeviceKind = 'phone' | 'tablet' | 'desktop' | 'app' | 'unknown'
  49. /** Phone, tablet or computer: which picture to draw beside a session. */
  50. export function classifyUserAgent(userAgent: string | null | undefined): DeviceKind {
  51. const ua = userAgent ?? ''
  52. if (!ua) return 'unknown'
  53. if (/Torqvoice|Expo|okhttp|Dart|CFNetwork/i.test(ua) && !/Mozilla/i.test(ua)) return 'app'
  54. if (/iPad|Tablet|PlayBook|Silk/i.test(ua) || (/Android/i.test(ua) && !/Mobile/i.test(ua))) {
  55. return 'tablet'
  56. }
  57. if (/iPhone|iPod|Android|Mobile|Windows Phone/i.test(ua)) return 'phone'
  58. if (/Windows|Macintosh|Mac OS X|CrOS|Linux|X11/i.test(ua)) return 'desktop'
  59. return 'unknown'
  60. }