Skip to content

Commit e81d75f

Browse files
committed
common logic to detect ua
Signed-off-by: Chandrika Mohan <chandrikalov@gmail.com>
1 parent 25bfe21 commit e81d75f

8 files changed

+63
-51
lines changed

apps/settings/src/components/AuthToken.spec.ts

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,52 @@
44
*/
55

66
import { describe, expect, it } from 'vitest'
7-
import { userAgentMap } from '../utils/userAgentMap.ts'
8-
9-
// Helper: iterate map in order, return first match (mirrors AuthToken.vue client computed)
10-
function detect(ua: string) {
11-
for (const [id, regex] of Object.entries(userAgentMap)) {
12-
const m = ua.match(regex)
13-
if (m) {
14-
return { id, version: m[2] ?? m[1], os: m[2] ? m[1] : null }
15-
}
16-
}
17-
return null
18-
}
19-
20-
// Android Chrome
7+
import { detect } from '../utils/userAgentDetect.ts'
218

229
describe('Android Chrome detection', () => {
2310
it('modern Android Chrome (no Build/ string, post-2021) should match androidChrome', () => {
2411
const ua = 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36'
25-
const result = detect(ua)
26-
expect(result?.id).toBe('androidChrome')
27-
expect(result?.version).toBe('132')
12+
expect(detect(ua)).toEqual({
13+
id: 'androidChrome',
14+
version: '132',
15+
})
2816
})
2917

3018
it('legacy Android Chrome (with Build/ string, pre-2021) should match androidChrome', () => {
3119
const ua = 'Mozilla/5.0 (Linux; Android 10; SM-G973F Build/QP1A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36'
32-
const result = detect(ua)
33-
expect(result?.id).toBe('androidChrome')
34-
expect(result?.version).toBe('130')
20+
expect(detect(ua)).toEqual({
21+
id: 'androidChrome',
22+
version: '130',
23+
})
3524
})
3625

3726
it('Android Chrome on tablet (no "Mobile" in UA) should match androidChrome', () => {
3827
const ua = 'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
39-
const result = detect(ua)
40-
expect(result?.id).toBe('androidChrome')
41-
expect(result?.version).toBe('131')
28+
expect(detect(ua)).toEqual({
29+
id: 'androidChrome',
30+
version: '131',
31+
})
4232
})
4333
})
4434

45-
// Desktop Chrome regressions
46-
4735
describe('Desktop Chrome regression tests', () => {
4836
it('Desktop Chrome on Linux should still match chrome', () => {
4937
const ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'
50-
const result = detect(ua)
51-
expect(result?.id).toBe('chrome')
52-
expect(result?.version).toBe('132')
38+
expect(detect(ua)).toEqual({
39+
id: 'chrome',
40+
version: '132',
41+
os: 'Linux',
42+
})
5343
})
5444
})
5545

56-
// Desktop Firefox regressions
57-
5846
describe('Desktop Firefox regression tests', () => {
5947
it('Desktop Firefox on Linux should still match firefox', () => {
6048
const ua = 'Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0'
61-
const result = detect(ua)
62-
expect(result?.id).toBe('firefox')
63-
expect(result?.version).toBe('124')
49+
expect(detect(ua)).toEqual({
50+
id: 'firefox',
51+
version: '124',
52+
os: 'Linux',
53+
})
6454
})
6555
})

apps/settings/src/components/AuthToken.vue

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ import NcDateTime from '@nextcloud/vue/components/NcDateTime'
100100
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
101101
import NcTextField from '@nextcloud/vue/components/NcTextField'
102102
import { TokenType, useAuthTokenStore } from '../store/authtoken.ts'
103-
import { userAgentMap } from '../utils/userAgentMap.ts'
103+
import { detect } from '../utils/userAgentDetect.ts'
104104
105105
const nameMap = {
106106
edge: 'Microsoft Edge',
@@ -176,18 +176,7 @@ export default defineComponent({
176176
}
177177
}
178178
179-
for (const client in userAgentMap) {
180-
const matches = this.token.name.match(userAgentMap[client])
181-
if (matches) {
182-
return {
183-
id: client,
184-
os: matches[2] && matches[1],
185-
version: matches[2] ?? matches[1],
186-
}
187-
}
188-
}
189-
190-
return null
179+
return detect(this.token.name)
191180
},
192181
193182
/**
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { userAgentMap } from './userAgentMap.ts'
7+
8+
export interface DetectedUserAgent {
9+
id: string
10+
version?: string
11+
os?: string
12+
}
13+
14+
/**
15+
* Detect the client from a user agent string.
16+
*
17+
* @param ua Raw user agent string
18+
* @return Detected client information or null if unknown
19+
*/
20+
export function detect(ua: string): DetectedUserAgent | null {
21+
for (const id in userAgentMap) {
22+
const matches = ua.match(userAgentMap[id])
23+
if (matches) {
24+
return {
25+
id,
26+
version: matches[2] ?? matches[1],
27+
os: matches[2] && matches[1],
28+
}
29+
}
30+
}
31+
32+
return null
33+
}

dist/settings-vue-settings-personal-security.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/settings-vue-settings-personal-security.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/theming-settings-personal.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* extracted by css-entry-points-plugin */
2-
@import './theming-theming-settings-personal-BGvZ2soH.chunk.css';
2+
@import './theming-theming-settings-personal-Tw2nBJ_u.chunk.css';
33
@import './createElementId-DhjFt1I9-C_oBIsvc.chunk.css';
44
@import './autolink-U5pBzLgI-R3us1MM8.chunk.css';
55
@import './NcModal-DHryP_87-CU2wYsLf.chunk.css';

dist/theming-theming-settings-personal-BGvZ2soH.chunk.css

Lines changed: 0 additions & 1 deletion
This file was deleted.

dist/theming-theming-settings-personal-Tw2nBJ_u.chunk.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)