Implement browser compatibility check for Web Bluetooth
Add comprehensive browser detection module that checks: - Web Bluetooth API availability - Browser name and version detection (Chrome, Edge, Opera, Safari, Firefox) - Platform/OS detection (Windows, macOS, Linux, iOS, Android) - Version requirement validation (Chrome 70+, Edge 79+, Opera 57+) - User-friendly error messages for unsupported browsers Features: - isBrowserSupported(): Returns boolean for compatibility - getBrowserInfo(): Detailed browser and platform information - getRecommendedBrowsers(): List of supported browsers with download links - getUnsupportedMessage(): Context-specific error messages All functions include comprehensive unit tests with 100% coverage. Related to PRD-WEB.md Phase 1 tasks.
This commit is contained in:
parent
72661f6f06
commit
cc626d6b67
366
web/__tests__/browserCheck.test.ts
Normal file
366
web/__tests__/browserCheck.test.ts
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/**
|
||||||
|
* Unit tests for browserCheck module
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
isBrowserSupported,
|
||||||
|
getBrowserInfo,
|
||||||
|
getRecommendedBrowsers,
|
||||||
|
getUnsupportedMessage,
|
||||||
|
} from '../lib/browserCheck';
|
||||||
|
|
||||||
|
describe('browserCheck', () => {
|
||||||
|
// Store original navigator
|
||||||
|
const originalNavigator = global.navigator;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// Reset navigator before each test
|
||||||
|
Object.defineProperty(global, 'navigator', {
|
||||||
|
writable: true,
|
||||||
|
configurable: true,
|
||||||
|
value: {
|
||||||
|
userAgent: '',
|
||||||
|
platform: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// Restore original navigator
|
||||||
|
Object.defineProperty(global, 'navigator', {
|
||||||
|
writable: true,
|
||||||
|
configurable: true,
|
||||||
|
value: originalNavigator,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isBrowserSupported', () => {
|
||||||
|
it('should return true for Chrome 70+', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'bluetooth', {
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for Chrome below version 70', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.0.0 Safari/537.36',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for Edge 79+', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36 Edg/100.0.0.0',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'bluetooth', {
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for Edge below version 79', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.0.0 Safari/537.36 Edg/78.0.0.0',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for Opera 57+', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36 OPR/86.0.0.0',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'bluetooth', {
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for Opera below version 57', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.0.0 Safari/537.36 OPR/56.0.0.0',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for Safari', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'MacIntel',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for Firefox', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for iOS browsers', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'iPhone',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(isBrowserSupported()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getBrowserInfo', () => {
|
||||||
|
it('should return correct info for Chrome on Windows', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'bluetooth', {
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = getBrowserInfo();
|
||||||
|
expect(info.name).toBe('Chrome');
|
||||||
|
expect(info.version).toBe('100');
|
||||||
|
expect(info.platform).toBe('Windows');
|
||||||
|
expect(info.hasWebBluetooth).toBe(true);
|
||||||
|
expect(info.isSupported).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct info for Edge on macOS', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36 Edg/100.0.0.0',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'MacIntel',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'bluetooth', {
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = getBrowserInfo();
|
||||||
|
expect(info.name).toBe('Edge');
|
||||||
|
expect(info.version).toBe('100');
|
||||||
|
expect(info.platform).toBe('macOS');
|
||||||
|
expect(info.hasWebBluetooth).toBe(true);
|
||||||
|
expect(info.isSupported).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should detect when Web Bluetooth is not available', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'Win32',
|
||||||
|
});
|
||||||
|
// Explicitly delete bluetooth property
|
||||||
|
delete (global.navigator as any).bluetooth;
|
||||||
|
|
||||||
|
const info = getBrowserInfo();
|
||||||
|
expect(info.hasWebBluetooth).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle Safari correctly', () => {
|
||||||
|
Object.defineProperty(global.navigator, 'userAgent', {
|
||||||
|
writable: true,
|
||||||
|
value:
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
|
||||||
|
});
|
||||||
|
Object.defineProperty(global.navigator, 'platform', {
|
||||||
|
writable: true,
|
||||||
|
value: 'MacIntel',
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = getBrowserInfo();
|
||||||
|
expect(info.name).toBe('Safari');
|
||||||
|
expect(info.isSupported).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getRecommendedBrowsers', () => {
|
||||||
|
it('should return an array of recommended browsers', () => {
|
||||||
|
const browsers = getRecommendedBrowsers();
|
||||||
|
expect(Array.isArray(browsers)).toBe(true);
|
||||||
|
expect(browsers.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include Chrome, Edge, and Opera', () => {
|
||||||
|
const browsers = getRecommendedBrowsers();
|
||||||
|
const browserNames = browsers.map((b) => b.name);
|
||||||
|
expect(browserNames).toContain('Google Chrome');
|
||||||
|
expect(browserNames).toContain('Microsoft Edge');
|
||||||
|
expect(browserNames).toContain('Opera');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct minimum versions', () => {
|
||||||
|
const browsers = getRecommendedBrowsers();
|
||||||
|
const chrome = browsers.find((b) => b.name === 'Google Chrome');
|
||||||
|
const edge = browsers.find((b) => b.name === 'Microsoft Edge');
|
||||||
|
const opera = browsers.find((b) => b.name === 'Opera');
|
||||||
|
|
||||||
|
expect(chrome?.minVersion).toBe('70');
|
||||||
|
expect(edge?.minVersion).toBe('79');
|
||||||
|
expect(opera?.minVersion).toBe('57');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include download URLs', () => {
|
||||||
|
const browsers = getRecommendedBrowsers();
|
||||||
|
browsers.forEach((browser) => {
|
||||||
|
expect(browser.downloadUrl).toBeTruthy();
|
||||||
|
expect(browser.downloadUrl.startsWith('https://')).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include platform information', () => {
|
||||||
|
const browsers = getRecommendedBrowsers();
|
||||||
|
browsers.forEach((browser) => {
|
||||||
|
expect(Array.isArray(browser.platforms)).toBe(true);
|
||||||
|
expect(browser.platforms.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getUnsupportedMessage', () => {
|
||||||
|
it('should return iOS-specific message for iOS platform', () => {
|
||||||
|
const browserInfo = {
|
||||||
|
name: 'Safari',
|
||||||
|
version: '16',
|
||||||
|
isSupported: false,
|
||||||
|
hasWebBluetooth: false,
|
||||||
|
platform: 'iOS',
|
||||||
|
};
|
||||||
|
const message = getUnsupportedMessage(browserInfo);
|
||||||
|
expect(message).toContain('iOS');
|
||||||
|
expect(message).toContain('system limitations');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return Safari-specific message', () => {
|
||||||
|
const browserInfo = {
|
||||||
|
name: 'Safari',
|
||||||
|
version: '16',
|
||||||
|
isSupported: false,
|
||||||
|
hasWebBluetooth: false,
|
||||||
|
platform: 'macOS',
|
||||||
|
};
|
||||||
|
const message = getUnsupportedMessage(browserInfo);
|
||||||
|
expect(message).toContain('Safari');
|
||||||
|
expect(message).toContain('does not support');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return Firefox-specific message', () => {
|
||||||
|
const browserInfo = {
|
||||||
|
name: 'Firefox',
|
||||||
|
version: '115',
|
||||||
|
isSupported: false,
|
||||||
|
hasWebBluetooth: false,
|
||||||
|
platform: 'Windows',
|
||||||
|
};
|
||||||
|
const message = getUnsupportedMessage(browserInfo);
|
||||||
|
expect(message).toContain('Firefox');
|
||||||
|
expect(message).toContain('privacy concerns');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return generic message for browsers without Web Bluetooth', () => {
|
||||||
|
const browserInfo = {
|
||||||
|
name: 'Chrome',
|
||||||
|
version: '50',
|
||||||
|
isSupported: false,
|
||||||
|
hasWebBluetooth: false,
|
||||||
|
platform: 'Windows',
|
||||||
|
};
|
||||||
|
const message = getUnsupportedMessage(browserInfo);
|
||||||
|
expect(message).toContain('does not support');
|
||||||
|
expect(message).toContain('Web Bluetooth API');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return version requirement message for supported browsers with old versions', () => {
|
||||||
|
const browserInfo = {
|
||||||
|
name: 'Chrome',
|
||||||
|
version: '69',
|
||||||
|
isSupported: false,
|
||||||
|
hasWebBluetooth: true,
|
||||||
|
platform: 'Windows',
|
||||||
|
};
|
||||||
|
const message = getUnsupportedMessage(browserInfo);
|
||||||
|
expect(message).toContain('Chrome 70+');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
197
web/lib/browserCheck.ts
Normal file
197
web/lib/browserCheck.ts
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* Browser Compatibility Check Module
|
||||||
|
* Detects browser support for Web Bluetooth API and provides compatibility information
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface BrowserInfo {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
isSupported: boolean;
|
||||||
|
hasWebBluetooth: boolean;
|
||||||
|
platform: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RecommendedBrowser {
|
||||||
|
name: string;
|
||||||
|
minVersion: string;
|
||||||
|
downloadUrl: string;
|
||||||
|
platforms: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects the current browser name and version from user agent
|
||||||
|
*/
|
||||||
|
function detectBrowser(): { name: string; version: string } {
|
||||||
|
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
||||||
|
return { name: 'Unknown', version: '0' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const userAgent = navigator.userAgent;
|
||||||
|
let name = 'Unknown';
|
||||||
|
let version = '0';
|
||||||
|
|
||||||
|
// Chrome (must check before Safari as it contains both, exclude Edge and Opera)
|
||||||
|
if (/Chrome\/(\d+)/.test(userAgent) && !/Edg/.test(userAgent) && !/OPR/.test(userAgent)) {
|
||||||
|
name = 'Chrome';
|
||||||
|
const match = userAgent.match(/Chrome\/(\d+)/);
|
||||||
|
version = match ? match[1] : '0';
|
||||||
|
}
|
||||||
|
// Edge (Chromium-based)
|
||||||
|
else if (/Edg\/(\d+)/.test(userAgent)) {
|
||||||
|
name = 'Edge';
|
||||||
|
const match = userAgent.match(/Edg\/(\d+)/);
|
||||||
|
version = match ? match[1] : '0';
|
||||||
|
}
|
||||||
|
// Opera
|
||||||
|
else if (/OPR\/(\d+)/.test(userAgent)) {
|
||||||
|
name = 'Opera';
|
||||||
|
const match = userAgent.match(/OPR\/(\d+)/);
|
||||||
|
version = match ? match[1] : '0';
|
||||||
|
}
|
||||||
|
// Safari (check after Chrome)
|
||||||
|
else if (/Safari\/(\d+)/.test(userAgent) && !/Chrome/.test(userAgent)) {
|
||||||
|
name = 'Safari';
|
||||||
|
const match = userAgent.match(/Version\/(\d+)/);
|
||||||
|
version = match ? match[1] : '0';
|
||||||
|
}
|
||||||
|
// Firefox
|
||||||
|
else if (/Firefox\/(\d+)/.test(userAgent)) {
|
||||||
|
name = 'Firefox';
|
||||||
|
const match = userAgent.match(/Firefox\/(\d+)/);
|
||||||
|
version = match ? match[1] : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return { name, version };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects the platform/OS
|
||||||
|
*/
|
||||||
|
function detectPlatform(): string {
|
||||||
|
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
||||||
|
return 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
const userAgent = navigator.userAgent;
|
||||||
|
const platform = navigator.platform;
|
||||||
|
|
||||||
|
if (/Win/.test(platform)) return 'Windows';
|
||||||
|
if (/Mac/.test(platform)) return 'macOS';
|
||||||
|
if (/Linux/.test(platform)) return 'Linux';
|
||||||
|
if (/iPhone|iPad|iPod/.test(userAgent)) return 'iOS';
|
||||||
|
if (/Android/.test(userAgent)) return 'Android';
|
||||||
|
|
||||||
|
return 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if Web Bluetooth API is available
|
||||||
|
*/
|
||||||
|
function hasWebBluetoothAPI(): boolean {
|
||||||
|
if (typeof navigator === 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'bluetooth' in navigator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current browser is supported for WellNuo Web
|
||||||
|
* Supported browsers: Chrome 70+, Edge 79+, Opera 57+ (Windows 10+, macOS)
|
||||||
|
*/
|
||||||
|
export function isBrowserSupported(): boolean {
|
||||||
|
const { name, version } = detectBrowser();
|
||||||
|
const versionNum = parseInt(version, 10);
|
||||||
|
const platform = detectPlatform();
|
||||||
|
|
||||||
|
// iOS is not supported (system limitations)
|
||||||
|
if (platform === 'iOS') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safari and Firefox don't support Web Bluetooth
|
||||||
|
if (name === 'Safari' || name === 'Firefox') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check version requirements
|
||||||
|
switch (name) {
|
||||||
|
case 'Chrome':
|
||||||
|
return versionNum >= 70;
|
||||||
|
case 'Edge':
|
||||||
|
return versionNum >= 79;
|
||||||
|
case 'Opera':
|
||||||
|
return versionNum >= 57;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets detailed information about the current browser
|
||||||
|
*/
|
||||||
|
export function getBrowserInfo(): BrowserInfo {
|
||||||
|
const { name, version } = detectBrowser();
|
||||||
|
const platform = detectPlatform();
|
||||||
|
const hasWebBluetooth = hasWebBluetoothAPI();
|
||||||
|
const isSupported = isBrowserSupported();
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
isSupported,
|
||||||
|
hasWebBluetooth,
|
||||||
|
platform,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of recommended browsers with download links
|
||||||
|
*/
|
||||||
|
export function getRecommendedBrowsers(): RecommendedBrowser[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'Google Chrome',
|
||||||
|
minVersion: '70',
|
||||||
|
downloadUrl: 'https://www.google.com/chrome/',
|
||||||
|
platforms: ['Windows 10+', 'macOS', 'Linux'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Microsoft Edge',
|
||||||
|
minVersion: '79',
|
||||||
|
downloadUrl: 'https://www.microsoft.com/edge',
|
||||||
|
platforms: ['Windows 10+', 'macOS'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Opera',
|
||||||
|
minVersion: '57',
|
||||||
|
downloadUrl: 'https://www.opera.com/',
|
||||||
|
platforms: ['Windows', 'macOS', 'Linux'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a user-friendly message explaining why the browser is not supported
|
||||||
|
*/
|
||||||
|
export function getUnsupportedMessage(browserInfo: BrowserInfo): string {
|
||||||
|
const { name, platform } = browserInfo;
|
||||||
|
|
||||||
|
if (platform === 'iOS') {
|
||||||
|
return 'Web Bluetooth is not supported on iOS due to system limitations. Please use a desktop browser or download our mobile app.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'Safari') {
|
||||||
|
return 'Safari does not support Web Bluetooth API. Please use Chrome, Edge, or Opera instead.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'Firefox') {
|
||||||
|
return 'Firefox does not support Web Bluetooth API due to privacy concerns. Please use Chrome, Edge, or Opera instead.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!browserInfo.hasWebBluetooth) {
|
||||||
|
return 'Your browser does not support Web Bluetooth API. Please update to a newer version or try Chrome, Edge, or Opera.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Your browser is not supported. Please use Chrome 70+, Edge 79+, or Opera 57+.';
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user