Skip to content

Commit 29eb2c7

Browse files
committed
more improvements
1 parent 1d5b084 commit 29eb2c7

3 files changed

Lines changed: 39 additions & 86 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@
8080
},
8181
{
8282
"path": "./build/releases/OneSignalSDK.page.es6.js",
83-
"limit": "60.5 kB",
83+
"limit": "60.55 kB",
8484
"gzip": true
8585
},
8686
{
8787
"path": "./build/releases/OneSignalSDK.sw.js",
88-
"limit": "25.1 kB",
88+
"limit": "25.25 kB",
8989
"gzip": true
9090
},
9191
{

src/shared/useragent/detect.ts

Lines changed: 34 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,152 +1,106 @@
11
interface BrowserConfig {
22
name: string;
33
pattern: RegExp;
4-
versionPattern?: RegExp;
4+
versionPattern: RegExp;
55
}
66

77
interface IBrowserResult {
88
name: string;
99
version: string;
1010
}
1111

12-
const PATTERNS = {
13-
LIKE_ANDROID: /like android/i,
14-
ANDROID: /android/i,
15-
IOS_DEVICES: /(iphone|ipod|ipad)/i,
16-
TABLET: /tablet/i,
17-
TABLET_PC: /tablet pc/i,
18-
MOBILE: /[^-]mobi/i,
19-
NEXUS_MOBILE: /nexus\s*[0-6]\s*/i,
20-
NEXUS_TABLET: /nexus\s*[0-9]+/i,
21-
GENERIC_VERSION: /version\/(\d+(?:\.\d+)?)/i,
22-
} as const;
23-
2412
const BROWSER_CONFIGS: BrowserConfig[] = [
2513
{
2614
name: 'Opera',
2715
pattern: /(?:opera|opr|opios)/i,
28-
versionPattern: /(?:opera|opr|opios)[\s\/](\d+(?:\.\d+)?)/i,
16+
versionPattern: /(?:opera|opr|opios)[ /](\d+(?:\.\d+)?)/i,
2917
},
3018
{
3119
name: 'Facebook',
3220
pattern: /FBAN\//i,
3321
versionPattern: /FBAV\/(\d+(?:\.\d+)?)/i,
3422
},
3523
{
36-
name: 'Samsung Internet for Android',
24+
name: 'Samsung Browser',
3725
pattern: /samsungbrowser/i,
38-
versionPattern: /samsungbrowser[\s\/](\d+(?:\.\d+)?)/i,
26+
versionPattern: /samsungbrowser[ /](\d+(?:\.\d+)?)/i,
3927
},
4028
{
4129
name: 'Yandex Browser',
4230
pattern: /yabrowser/i,
43-
versionPattern: /yabrowser[\s\/](\d+(?:\.\d+)?)/i,
31+
versionPattern: /yabrowser[ /](\d+(?:\.\d+)?)/i,
4432
},
4533
{
4634
name: 'Vivaldi',
4735
pattern: /vivaldi/i,
48-
versionPattern: /vivaldi[\s\/](\d+(?:\.\d+)?)/i,
36+
versionPattern: /vivaldi[ /](\d+(?:\.\d+)?)/i,
4937
},
5038
{
5139
name: 'UC Browser',
5240
pattern: /ucbrowser/i,
53-
versionPattern: /ucbrowser[\s\/](\d+(?:\.\d+)?)/i,
41+
versionPattern: /ucbrowser[ /](\d+(?:\.\d+)?)/i,
5442
},
5543
{
5644
name: 'Microsoft Edge',
57-
pattern: /(?:edge|edgios|edga|edg)/i,
58-
versionPattern: /(?:edge|edgios|edga|edg)[\s\/](\d+(?:\.\d+)?)/i,
45+
pattern: /edg/i,
46+
versionPattern: /edg[ /](\d+(?:\.\d+)?)/i,
5947
},
6048
{
6149
name: 'Firefox',
6250
pattern: /firefox|iceweasel|fxios/i,
63-
versionPattern: /(?:firefox|iceweasel|fxios)[\s\/](\d+(?:\.\d+)?)/i,
51+
versionPattern: /(?:firefox|iceweasel|fxios)[ /](\d+(?:\.\d+)?)/i,
6452
},
6553
{
6654
name: 'Chromium',
6755
pattern: /chromium/i,
68-
versionPattern: /chromium[\s\/](\d+(?:\.\d+)?)/i,
56+
versionPattern: /chromium[ /](\d+(?:\.\d+)?)/i,
6957
},
7058
{
7159
name: 'Chrome',
7260
pattern: /chrome|crios|crmo/i,
73-
versionPattern: /(?:chrome|crios|crmo)[\s\/](\d+(?:\.\d+)?)/i,
61+
versionPattern: /(?:chrome|crios|crmo)[ /](\d+(?:\.\d+)?)/i,
7462
},
7563
{
7664
name: 'Safari',
7765
pattern: /safari|applewebkit/i,
78-
versionPattern: /version[\s\/](\d+(?:\.\d+)?)/i,
66+
versionPattern: /version[ /](\d+(?:\.\d+)?)/i,
7967
},
8068
];
8169

82-
const matchUserAgent = (
83-
userAgent: string,
84-
position: number,
85-
pattern: RegExp,
86-
): string => userAgent.match(pattern)?.[position] || '';
87-
88-
function extractVersion(userAgent: string, config: BrowserConfig): string {
89-
if (!config.versionPattern)
90-
return matchUserAgent(userAgent, 1, PATTERNS.GENERIC_VERSION);
91-
const match = userAgent.match(config.versionPattern);
92-
return match?.[1] || '';
93-
}
94-
9570
export function getBrowser(userAgent: string): IBrowserResult {
9671
for (const config of BROWSER_CONFIGS) {
9772
if (config.pattern.test(userAgent)) {
98-
return { name: config.name, version: extractVersion(userAgent, config) };
73+
const version = userAgent.match(config.versionPattern)?.[1] ?? '';
74+
return { name: config.name, version };
9975
}
10076
}
101-
return {
102-
name: matchUserAgent(userAgent, 1, /^(.*?)[\s\/]/) || 'Unknown',
103-
version: matchUserAgent(userAgent, 2, /^(.*?)[\s\/](.+?)[\s]/) || '',
104-
};
77+
return { name: 'Unknown', version: '' };
10578
}
79+
const isAndroid = (userAgent: string): boolean =>
80+
!/like android/i.test(userAgent) && /android/i.test(userAgent);
10681

107-
const isAndroidDevice = (userAgent: string): boolean =>
108-
!PATTERNS.LIKE_ANDROID.test(userAgent) && PATTERNS.ANDROID.test(userAgent);
82+
const getIOSDeviceType = (userAgent: string): string =>
83+
userAgent.match(/(iphone|ipod|ipad)/i)?.[1]?.toLowerCase() || '';
10984

110-
export function getIOSDeviceType(userAgent: string): string {
111-
let deviceType = matchUserAgent(
112-
userAgent,
113-
1,
114-
PATTERNS.IOS_DEVICES,
115-
).toLowerCase();
85+
export function isTabletBrowser(userAgent = navigator.userAgent): boolean {
86+
const ios = getIOSDeviceType(userAgent);
11687

117-
if (
118-
!deviceType &&
119-
navigator.platform === 'MacIntel' &&
120-
navigator.maxTouchPoints > 2 &&
121-
!(window as { MSStream?: unknown })?.MSStream
122-
) {
123-
deviceType = 'ipad';
124-
}
125-
return deviceType;
126-
}
127-
128-
export function isTablet(userAgent: string): boolean {
129-
const isAndroid = isAndroidDevice(userAgent);
130-
const iOSDevice = getIOSDeviceType(userAgent);
13188
return (
132-
(PATTERNS.TABLET.test(userAgent) && !PATTERNS.TABLET_PC.test(userAgent)) ||
133-
iOSDevice === 'ipad' ||
134-
(isAndroid && !PATTERNS.MOBILE.test(userAgent)) ||
135-
(!PATTERNS.NEXUS_MOBILE.test(userAgent) &&
136-
PATTERNS.NEXUS_TABLET.test(userAgent))
89+
(/tablet/i.test(userAgent) && !/tablet pc/i.test(userAgent)) ||
90+
ios === 'ipad' ||
91+
(isAndroid(userAgent) && !/[^-]mobi/i.test(userAgent)) ||
92+
(!/nexus\s*[0-6]\s*/i.test(userAgent) && /nexus\s*\d+/i.test(userAgent))
13793
);
13894
}
13995

140-
export function isMobile(userAgent: string): boolean {
141-
const isTabletDevice = isTablet(userAgent);
142-
const isAndroid = isAndroidDevice(userAgent);
143-
const iOSDevice = getIOSDeviceType(userAgent);
96+
export function isMobileBrowser(userAgent = navigator.userAgent): boolean {
97+
if (isTabletBrowser(userAgent)) return false;
98+
99+
const ios = getIOSDeviceType(userAgent);
144100
return (
145-
!isTabletDevice &&
146-
(PATTERNS.MOBILE.test(userAgent) ||
147-
iOSDevice === 'iphone' ||
148-
iOSDevice === 'ipod' ||
149-
isAndroid ||
150-
PATTERNS.NEXUS_MOBILE.test(userAgent))
101+
/[^-]mobi/i.test(userAgent) ||
102+
ios === 'iphone' ||
103+
ios === 'ipod' ||
104+
isAndroid(userAgent)
151105
);
152106
}

src/shared/useragent/useragent.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { Browser } from './constants';
2-
import { getBrowser, isMobile, isTablet } from './detect';
2+
import { getBrowser } from './detect';
33
import type { BrowserValue } from './types';
44

5+
export { isMobileBrowser, isTabletBrowser } from './detect';
6+
57
const BROWSER_MAP: Record<string, BrowserValue> = {
68
Chrome: Browser.Chrome,
79
Chromium: Browser.Chrome,
@@ -21,9 +23,6 @@ export const getBrowserVersion = (): number => {
2123
return +`${major}.${minor}`;
2224
};
2325

24-
export const isMobileBrowser = (): boolean => isMobile(navigator.userAgent);
25-
export const isTabletBrowser = (): boolean => isTablet(navigator.userAgent);
26-
2726
export function requiresUserInteraction(): boolean {
2827
const browserName = getBrowserName();
2928
const version = getBrowserVersion();

0 commit comments

Comments
 (0)