import { OperatingSystem } from '@/domain/OperatingSystem'; import { DetectorBuilder } from './DetectorBuilder'; import { IBrowserOsDetector } from './IBrowserOsDetector'; export class BrowserOsDetector implements IBrowserOsDetector { private readonly detectors = BrowserDetectors; public detect(userAgent: string): OperatingSystem | undefined { if (!userAgent) { return undefined; } for (const detector of this.detectors) { const os = detector.detect(userAgent); if (os !== undefined) { return os; } } return undefined; } } // Reference: https://github.com/keithws/browser-report/blob/master/index.js#L304 const BrowserDetectors = [ define(OperatingSystem.KaiOS, (b) => b.mustInclude('KAIOS')), define(OperatingSystem.ChromeOS, (b) => b.mustInclude('CrOS')), define(OperatingSystem.BlackBerryOS, (b) => b.mustInclude('BlackBerry')), define(OperatingSystem.BlackBerryTabletOS, (b) => b.mustInclude('RIM Tablet OS')), define(OperatingSystem.BlackBerry, (b) => b.mustInclude('BB10')), define(OperatingSystem.Android, (b) => b.mustInclude('Android').mustNotInclude('Windows Phone')), define(OperatingSystem.Android, (b) => b.mustInclude('Adr').mustNotInclude('Windows Phone')), define(OperatingSystem.iOS, (b) => b.mustInclude('like Mac OS X')), define(OperatingSystem.Linux, (b) => b.mustInclude('Linux').mustNotInclude('Android').mustNotInclude('Adr')), define(OperatingSystem.Windows, (b) => b.mustInclude('Windows').mustNotInclude('Windows Phone')), define(OperatingSystem.WindowsPhone, (b) => b.mustInclude('Windows Phone')), define(OperatingSystem.macOS, (b) => b.mustInclude('OS X').mustNotInclude('Android').mustNotInclude('like Mac OS X')), ]; function define(os: OperatingSystem, applyRules: (builder: DetectorBuilder) => DetectorBuilder): IBrowserOsDetector { const builder = new DetectorBuilder(os); applyRules(builder); return builder.build(); }