@hkdigital/lib-core 0.5.16 → 0.5.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/info.d.ts +26 -0
- package/dist/app/info.js +33 -0
- package/dist/app/typedef.d.ts +4 -0
- package/dist/app/typedef.js +8 -0
- package/dist/browser/info/device.d.ts +67 -0
- package/dist/browser/info/device.js +183 -0
- package/dist/browser/info/display.d.ts +73 -0
- package/dist/browser/info/display.js +109 -0
- package/dist/browser/info/engine.d.ts +39 -0
- package/dist/browser/info/engine.js +64 -0
- package/dist/browser/info/language.d.ts +18 -0
- package/dist/browser/info/language.js +23 -0
- package/dist/browser/info/system.d.ts +47 -0
- package/dist/browser/info/system.js +102 -0
- package/dist/browser/info/timezone.d.ts +20 -0
- package/dist/browser/info/timezone.js +25 -0
- package/dist/browser/info.d.ts +81 -0
- package/dist/browser/info.js +185 -0
- package/dist/browser/typedef.d.ts +31 -0
- package/dist/browser/typedef.js +38 -0
- package/dist/ui/components/game-box/GameBox.svelte +37 -90
- package/dist/ui/components/game-box/GameBox.svelte.d.ts +4 -70
- package/dist/ui/components/game-box/gamebox.util.d.ts +0 -24
- package/dist/ui/components/game-box/gamebox.util.js +0 -61
- package/dist/ui/components/game-box/typedef.d.ts +16 -0
- package/dist/ui/components/game-box/typedef.js +23 -0
- package/dist/ui/components/typedef.d.ts +1 -0
- package/dist/ui/components/typedef.js +1 -0
- package/dist/util/expect/values.d.ts +1 -1
- package/dist/util/expect/values.js +5 -2
- package/dist/util/random/bytes.js +6 -3
- package/dist/util/random/uuid.d.ts +22 -0
- package/dist/util/random/uuid.js +59 -0
- package/dist/util/random.d.ts +1 -0
- package/dist/util/random.js +2 -1
- package/dist/util/unique/index.d.ts +41 -6
- package/dist/util/unique/index.js +62 -12
- package/package.json +1 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get simplified platform identifier
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* // 'macos', 'windows', 'linux', 'ios', 'android', 'unknown'
|
|
6
|
+
*
|
|
7
|
+
* @returns {string} platform identifier
|
|
8
|
+
*/
|
|
9
|
+
export function getPlatform() {
|
|
10
|
+
const platform = navigator.platform.toLowerCase();
|
|
11
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
12
|
+
|
|
13
|
+
// iOS devices
|
|
14
|
+
if (/iphone|ipod|ipad/.test(platform)) {
|
|
15
|
+
return 'ios';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// iPadOS (reports as MacIntel but has touch)
|
|
19
|
+
if (platform === 'macintel' && navigator.maxTouchPoints > 2) {
|
|
20
|
+
return 'ios';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Android
|
|
24
|
+
if (/android/.test(ua)) {
|
|
25
|
+
return 'android';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// macOS
|
|
29
|
+
if (/mac/.test(platform)) {
|
|
30
|
+
return 'macos';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Windows
|
|
34
|
+
if (/win/.test(platform)) {
|
|
35
|
+
return 'windows';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Linux
|
|
39
|
+
if (/linux/.test(platform)) {
|
|
40
|
+
return 'linux';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return 'unknown';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get raw platform string from navigator
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // 'MacIntel', 'Win32', 'Linux x86_64', 'iPhone', 'iPad'
|
|
51
|
+
*
|
|
52
|
+
* @returns {string} raw platform identifier
|
|
53
|
+
*/
|
|
54
|
+
export function getPlatformRaw() {
|
|
55
|
+
return navigator.platform;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get number of CPU cores (logical processors)
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Desktop: 8, 16, 24
|
|
63
|
+
* // Mobile: 4, 6, 8
|
|
64
|
+
* // Older devices: 2
|
|
65
|
+
*
|
|
66
|
+
* @returns {number} number of logical processors
|
|
67
|
+
*/
|
|
68
|
+
export function getCpuCores() {
|
|
69
|
+
return navigator.hardwareConcurrency || 1;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if device is online
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // true (connected), false (offline)
|
|
77
|
+
*
|
|
78
|
+
* @returns {boolean} true if online
|
|
79
|
+
*/
|
|
80
|
+
export function isOnline() {
|
|
81
|
+
return navigator.onLine;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get connection type if available (experimental API)
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // '4g', '3g', 'slow-2g', 'wifi', null
|
|
89
|
+
*
|
|
90
|
+
* @returns {string|null} connection type or null
|
|
91
|
+
*/
|
|
92
|
+
export function getConnectionType() {
|
|
93
|
+
// @ts-ignore
|
|
94
|
+
const connection =
|
|
95
|
+
navigator.connection ||
|
|
96
|
+
// @ts-ignore
|
|
97
|
+
navigator.mozConnection ||
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
navigator.webkitConnection;
|
|
100
|
+
|
|
101
|
+
return connection?.effectiveType || null;
|
|
102
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get timezone offset in minutes
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* // UTC: 0
|
|
6
|
+
* // PST (UTC-8): 480
|
|
7
|
+
* // CET (UTC+1): -60
|
|
8
|
+
*
|
|
9
|
+
* @returns {number} timezone offset
|
|
10
|
+
*/
|
|
11
|
+
export function getTimezoneOffset(): number;
|
|
12
|
+
/**
|
|
13
|
+
* Get timezone name
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // 'America/New_York', 'Europe/Amsterdam', 'Asia/Tokyo'
|
|
17
|
+
*
|
|
18
|
+
* @returns {string} timezone identifier
|
|
19
|
+
*/
|
|
20
|
+
export function getTimezone(): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get timezone offset in minutes
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* // UTC: 0
|
|
6
|
+
* // PST (UTC-8): 480
|
|
7
|
+
* // CET (UTC+1): -60
|
|
8
|
+
*
|
|
9
|
+
* @returns {number} timezone offset
|
|
10
|
+
*/
|
|
11
|
+
export function getTimezoneOffset() {
|
|
12
|
+
return new Date().getTimezoneOffset();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get timezone name
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // 'America/New_York', 'Europe/Amsterdam', 'Asia/Tokyo'
|
|
20
|
+
*
|
|
21
|
+
* @returns {string} timezone identifier
|
|
22
|
+
*/
|
|
23
|
+
export function getTimezone() {
|
|
24
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
25
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{
|
|
3
|
+
* deviceType?: boolean,
|
|
4
|
+
* isMobile?: boolean,
|
|
5
|
+
* platform?: boolean,
|
|
6
|
+
* browser?: boolean,
|
|
7
|
+
* browserEngine?: boolean,
|
|
8
|
+
* screenWidth?: boolean,
|
|
9
|
+
* screenHeight?: boolean,
|
|
10
|
+
* devicePixelRatio?: boolean,
|
|
11
|
+
* hasTouch?: boolean,
|
|
12
|
+
* language?: boolean,
|
|
13
|
+
* timezone?: boolean,
|
|
14
|
+
* isPwa?: boolean,
|
|
15
|
+
* viewportWidth?: boolean,
|
|
16
|
+
* viewportHeight?: boolean,
|
|
17
|
+
* orientation?: boolean,
|
|
18
|
+
* cpuCores?: boolean,
|
|
19
|
+
* connectionType?: boolean
|
|
20
|
+
* }} BrowserInfoOptions
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {import('./typedef.js').BrowserInfo} BrowserInfo
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Collect browser and device information for analytics/stats
|
|
27
|
+
*
|
|
28
|
+
* @param {BrowserInfoOptions} [options] - Enable/disable individual properties
|
|
29
|
+
*
|
|
30
|
+
* @returns {BrowserInfo} collected browser information
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Get all essential info (default)
|
|
34
|
+
* const info = getBrowserInfo();
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Get only specific properties
|
|
38
|
+
* const info = getBrowserInfo({
|
|
39
|
+
* deviceType: true,
|
|
40
|
+
* platform: true,
|
|
41
|
+
* browser: true
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // Get essential + extended properties
|
|
46
|
+
* const info = getBrowserInfo({
|
|
47
|
+
* deviceType: true,
|
|
48
|
+
* platform: true,
|
|
49
|
+
* viewportWidth: true,
|
|
50
|
+
* viewportHeight: true,
|
|
51
|
+
* orientation: true,
|
|
52
|
+
* cpuCores: true
|
|
53
|
+
* });
|
|
54
|
+
*/
|
|
55
|
+
export function getBrowserInfo(options?: BrowserInfoOptions): BrowserInfo;
|
|
56
|
+
export * from "./info/device.js";
|
|
57
|
+
export * from "./info/display.js";
|
|
58
|
+
export * from "./info/engine.js";
|
|
59
|
+
export * from "./info/language.js";
|
|
60
|
+
export * from "./info/system.js";
|
|
61
|
+
export * from "./info/timezone.js";
|
|
62
|
+
export type BrowserInfoOptions = {
|
|
63
|
+
deviceType?: boolean;
|
|
64
|
+
isMobile?: boolean;
|
|
65
|
+
platform?: boolean;
|
|
66
|
+
browser?: boolean;
|
|
67
|
+
browserEngine?: boolean;
|
|
68
|
+
screenWidth?: boolean;
|
|
69
|
+
screenHeight?: boolean;
|
|
70
|
+
devicePixelRatio?: boolean;
|
|
71
|
+
hasTouch?: boolean;
|
|
72
|
+
language?: boolean;
|
|
73
|
+
timezone?: boolean;
|
|
74
|
+
isPwa?: boolean;
|
|
75
|
+
viewportWidth?: boolean;
|
|
76
|
+
viewportHeight?: boolean;
|
|
77
|
+
orientation?: boolean;
|
|
78
|
+
cpuCores?: boolean;
|
|
79
|
+
connectionType?: boolean;
|
|
80
|
+
};
|
|
81
|
+
export type BrowserInfo = import("./typedef.js").BrowserInfo;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
export * from './info/device.js';
|
|
2
|
+
export * from './info/display.js';
|
|
3
|
+
export * from './info/engine.js';
|
|
4
|
+
export * from './info/language.js';
|
|
5
|
+
export * from './info/system.js';
|
|
6
|
+
export * from './info/timezone.js';
|
|
7
|
+
|
|
8
|
+
import { getDeviceType, getIsMobile } from './info/device.js';
|
|
9
|
+
import { getBrowserName, getBrowserEngine } from './info/engine.js';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
getScreenSize,
|
|
13
|
+
getViewportSize,
|
|
14
|
+
getDevicePixelRatio,
|
|
15
|
+
getOrientation,
|
|
16
|
+
hasTouchSupport,
|
|
17
|
+
getIsPwa
|
|
18
|
+
} from './info/display.js';
|
|
19
|
+
|
|
20
|
+
import { getLanguage } from './info/language.js';
|
|
21
|
+
import { getPlatform, getCpuCores, getConnectionType } from './info/system.js';
|
|
22
|
+
import { getTimezone } from './info/timezone.js';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {{
|
|
26
|
+
* deviceType?: boolean,
|
|
27
|
+
* isMobile?: boolean,
|
|
28
|
+
* platform?: boolean,
|
|
29
|
+
* browser?: boolean,
|
|
30
|
+
* browserEngine?: boolean,
|
|
31
|
+
* screenWidth?: boolean,
|
|
32
|
+
* screenHeight?: boolean,
|
|
33
|
+
* devicePixelRatio?: boolean,
|
|
34
|
+
* hasTouch?: boolean,
|
|
35
|
+
* language?: boolean,
|
|
36
|
+
* timezone?: boolean,
|
|
37
|
+
* isPwa?: boolean,
|
|
38
|
+
* viewportWidth?: boolean,
|
|
39
|
+
* viewportHeight?: boolean,
|
|
40
|
+
* orientation?: boolean,
|
|
41
|
+
* cpuCores?: boolean,
|
|
42
|
+
* connectionType?: boolean
|
|
43
|
+
* }} BrowserInfoOptions
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {import('./typedef.js').BrowserInfo} BrowserInfo
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Collect browser and device information for analytics/stats
|
|
52
|
+
*
|
|
53
|
+
* @param {BrowserInfoOptions} [options] - Enable/disable individual properties
|
|
54
|
+
*
|
|
55
|
+
* @returns {BrowserInfo} collected browser information
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Get all essential info (default)
|
|
59
|
+
* const info = getBrowserInfo();
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Get only specific properties
|
|
63
|
+
* const info = getBrowserInfo({
|
|
64
|
+
* deviceType: true,
|
|
65
|
+
* platform: true,
|
|
66
|
+
* browser: true
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Get essential + extended properties
|
|
71
|
+
* const info = getBrowserInfo({
|
|
72
|
+
* deviceType: true,
|
|
73
|
+
* platform: true,
|
|
74
|
+
* viewportWidth: true,
|
|
75
|
+
* viewportHeight: true,
|
|
76
|
+
* orientation: true,
|
|
77
|
+
* cpuCores: true
|
|
78
|
+
* });
|
|
79
|
+
*/
|
|
80
|
+
export function getBrowserInfo(options = {}) {
|
|
81
|
+
// Default to BrowserInfoEssential properties
|
|
82
|
+
const {
|
|
83
|
+
deviceType = true,
|
|
84
|
+
isMobile = true,
|
|
85
|
+
platform = true,
|
|
86
|
+
browser = true,
|
|
87
|
+
browserEngine = true,
|
|
88
|
+
screenWidth = true,
|
|
89
|
+
screenHeight = true,
|
|
90
|
+
devicePixelRatio = true,
|
|
91
|
+
hasTouch = true,
|
|
92
|
+
language = true,
|
|
93
|
+
timezone = true,
|
|
94
|
+
isPwa = true,
|
|
95
|
+
// Extended properties (default false)
|
|
96
|
+
viewportWidth = false,
|
|
97
|
+
viewportHeight = false,
|
|
98
|
+
orientation = false,
|
|
99
|
+
cpuCores = false,
|
|
100
|
+
connectionType = false
|
|
101
|
+
} = options;
|
|
102
|
+
|
|
103
|
+
const info = {};
|
|
104
|
+
|
|
105
|
+
// Device type
|
|
106
|
+
if (deviceType) {
|
|
107
|
+
info.deviceType = getDeviceType();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Mobile check
|
|
111
|
+
if (isMobile) {
|
|
112
|
+
info.isMobile = getIsMobile();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Platform
|
|
116
|
+
if (platform) {
|
|
117
|
+
info.platform = getPlatform();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Browser name
|
|
121
|
+
if (browser) {
|
|
122
|
+
info.browser = getBrowserName();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Browser engine
|
|
126
|
+
if (browserEngine) {
|
|
127
|
+
info.browserEngine = getBrowserEngine();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Screen dimensions
|
|
131
|
+
if (screenWidth || screenHeight) {
|
|
132
|
+
const screenSize = getScreenSize();
|
|
133
|
+
if (screenWidth) info.screenWidth = screenSize.width;
|
|
134
|
+
if (screenHeight) info.screenHeight = screenSize.height;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Device pixel ratio
|
|
138
|
+
if (devicePixelRatio) {
|
|
139
|
+
info.devicePixelRatio = getDevicePixelRatio();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Touch support
|
|
143
|
+
if (hasTouch) {
|
|
144
|
+
info.hasTouch = hasTouchSupport();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Language
|
|
148
|
+
if (language) {
|
|
149
|
+
info.language = getLanguage();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Timezone
|
|
153
|
+
if (timezone) {
|
|
154
|
+
info.timezone = getTimezone();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// PWA
|
|
158
|
+
if (isPwa) {
|
|
159
|
+
info.isPwa = getIsPwa();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Viewport dimensions (extended)
|
|
163
|
+
if (viewportWidth || viewportHeight) {
|
|
164
|
+
const viewportSize = getViewportSize();
|
|
165
|
+
if (viewportWidth) info.viewportWidth = viewportSize.width;
|
|
166
|
+
if (viewportHeight) info.viewportHeight = viewportSize.height;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Orientation (extended)
|
|
170
|
+
if (orientation) {
|
|
171
|
+
info.orientation = getOrientation();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// CPU cores (extended)
|
|
175
|
+
if (cpuCores) {
|
|
176
|
+
info.cpuCores = getCpuCores();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Connection type (extended)
|
|
180
|
+
if (connectionType) {
|
|
181
|
+
info.connectionType = getConnectionType();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return info;
|
|
185
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Essential browser info
|
|
3
|
+
*/
|
|
4
|
+
export type BrowserInfoEssential = {
|
|
5
|
+
deviceType?: "phone" | "tablet" | "tv" | "desktop";
|
|
6
|
+
isMobile?: boolean;
|
|
7
|
+
platform?: string;
|
|
8
|
+
browser?: string;
|
|
9
|
+
browserEngine?: "blink" | "gecko" | "webkit" | "unknown";
|
|
10
|
+
screenWidth?: number;
|
|
11
|
+
screenHeight?: number;
|
|
12
|
+
devicePixelRatio?: number;
|
|
13
|
+
hasTouch?: boolean;
|
|
14
|
+
language?: string;
|
|
15
|
+
timezone?: string;
|
|
16
|
+
isPwa?: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Extended browser info (opt-in)
|
|
20
|
+
*/
|
|
21
|
+
export type BrowserInfoExtended = {
|
|
22
|
+
viewportWidth?: number;
|
|
23
|
+
viewportHeight?: number;
|
|
24
|
+
orientation?: "portrait" | "landscape";
|
|
25
|
+
cpuCores?: number;
|
|
26
|
+
connectionType?: string | null;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Complete browser info (essential + extended)
|
|
30
|
+
*/
|
|
31
|
+
export type BrowserInfo = BrowserInfoEssential & BrowserInfoExtended;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Essential browser info
|
|
3
|
+
*
|
|
4
|
+
* @typedef {{
|
|
5
|
+
* deviceType?: 'phone'|'tablet'|'tv'|'desktop',
|
|
6
|
+
* isMobile?: boolean,
|
|
7
|
+
* platform?: string,
|
|
8
|
+
* browser?: string,
|
|
9
|
+
* browserEngine?: 'blink'|'gecko'|'webkit'|'unknown',
|
|
10
|
+
* screenWidth?: number,
|
|
11
|
+
* screenHeight?: number,
|
|
12
|
+
* devicePixelRatio?: number,
|
|
13
|
+
* hasTouch?: boolean,
|
|
14
|
+
* language?: string,
|
|
15
|
+
* timezone?: string,
|
|
16
|
+
* isPwa?: boolean
|
|
17
|
+
* }} BrowserInfoEssential
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Extended browser info (opt-in)
|
|
22
|
+
*
|
|
23
|
+
* @typedef {{
|
|
24
|
+
* viewportWidth?: number,
|
|
25
|
+
* viewportHeight?: number,
|
|
26
|
+
* orientation?: 'portrait'|'landscape',
|
|
27
|
+
* cpuCores?: number,
|
|
28
|
+
* connectionType?: string|null
|
|
29
|
+
* }} BrowserInfoExtended
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Complete browser info (essential + extended)
|
|
34
|
+
*
|
|
35
|
+
* @typedef {BrowserInfoEssential & BrowserInfoExtended} BrowserInfo
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export {};
|
|
@@ -3,34 +3,28 @@
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
getGameWidthOnLandscape,
|
|
6
|
-
getGameWidthOnPortrait
|
|
7
|
-
isIOS,
|
|
8
|
-
isIpadOS,
|
|
9
|
-
getOS,
|
|
10
|
-
getIsMobile
|
|
6
|
+
getGameWidthOnPortrait
|
|
11
7
|
} from './gamebox.util.js';
|
|
12
8
|
|
|
9
|
+
import {
|
|
10
|
+
getIsAppleMobile,
|
|
11
|
+
getIsIpadOS,
|
|
12
|
+
getIsMobile
|
|
13
|
+
} from '../../../browser/info/device.js';
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
getIsPwa,
|
|
17
|
+
getIsFullscreen
|
|
18
|
+
} from '../../../browser/info/display.js';
|
|
19
|
+
|
|
13
20
|
import ScaledContainer from './ScaledContainer.svelte';
|
|
14
21
|
|
|
15
22
|
/**
|
|
16
|
-
* @typedef {
|
|
17
|
-
* isLandscape: boolean,
|
|
18
|
-
* isPortrait: boolean,
|
|
19
|
-
* isMobile:boolean,
|
|
20
|
-
* isIos:boolean,
|
|
21
|
-
* isAndroid:boolean,
|
|
22
|
-
* os:'Android'|'iOS',
|
|
23
|
-
* isFullscreen:boolean,
|
|
24
|
-
* isDevMode:boolean,
|
|
25
|
-
* requestDevmode:function,
|
|
26
|
-
* requestFullscreen:function,
|
|
27
|
-
* gameWidth: number,
|
|
28
|
-
* gameHeight: number
|
|
29
|
-
* }} SnippetParams
|
|
23
|
+
* @typedef {import('./typedef.js').SnippetParams} SnippetParams
|
|
30
24
|
*/
|
|
31
25
|
|
|
32
26
|
/**
|
|
33
|
-
* @typedef {import('
|
|
27
|
+
* @typedef {import('./typedef.js').GameBoxSnippet} GameBoxSnippet
|
|
34
28
|
*/
|
|
35
29
|
|
|
36
30
|
/**
|
|
@@ -97,11 +91,6 @@
|
|
|
97
91
|
let windowWidth = $state();
|
|
98
92
|
let windowHeight = $state();
|
|
99
93
|
|
|
100
|
-
let debouncedWindowWidth = $state();
|
|
101
|
-
let debouncedWindowHeight = $state();
|
|
102
|
-
|
|
103
|
-
let debounceTimer;
|
|
104
|
-
|
|
105
94
|
let gameWidthOnPortrait = $state();
|
|
106
95
|
let gameHeightOnPortrait = $state();
|
|
107
96
|
|
|
@@ -132,47 +121,19 @@
|
|
|
132
121
|
} );
|
|
133
122
|
|
|
134
123
|
// iPad is also considered Apple mobile
|
|
135
|
-
const isAppleMobile =
|
|
136
|
-
|
|
137
|
-
let os = $state();
|
|
138
|
-
let isIos = $derived(os === 'iOS');
|
|
139
|
-
let isAndroid = $derived(os === 'Android');
|
|
140
|
-
|
|
141
|
-
// Debounce window dimensions on iOS to skip intermediate resize events
|
|
142
|
-
let skipNextResize = false;
|
|
143
|
-
let resetTimer;
|
|
144
|
-
|
|
145
|
-
$effect(() => {
|
|
146
|
-
if (isAppleMobile && windowWidth && windowHeight) {
|
|
147
|
-
if (skipNextResize) {
|
|
148
|
-
skipNextResize = false;
|
|
149
|
-
return; // Skip first of the two resize events
|
|
150
|
-
}
|
|
124
|
+
const isAppleMobile = getIsAppleMobile();
|
|
151
125
|
|
|
152
|
-
|
|
126
|
+
let isIos = $state(false);
|
|
127
|
+
let isAndroid = $state(false);
|
|
128
|
+
let isIpadOS = $state(false);
|
|
153
129
|
|
|
154
|
-
|
|
155
|
-
debouncedWindowHeight = windowHeight;
|
|
156
|
-
|
|
157
|
-
// Reset flag after resize events settle
|
|
158
|
-
clearTimeout(resetTimer);
|
|
159
|
-
resetTimer = setTimeout(() => {
|
|
160
|
-
skipNextResize = false;
|
|
161
|
-
}, 500);
|
|
162
|
-
} else {
|
|
163
|
-
// Non-iOS: use dimensions immediately
|
|
164
|
-
debouncedWindowWidth = windowWidth;
|
|
165
|
-
debouncedWindowHeight = windowHeight;
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Update iOS dimensions when debounced window size changes
|
|
130
|
+
// Update iOS dimensions when window size changes
|
|
170
131
|
$effect(() => {
|
|
171
132
|
if (
|
|
172
133
|
isPwa &&
|
|
173
134
|
isAppleMobile &&
|
|
174
|
-
|
|
175
|
-
|
|
135
|
+
windowWidth &&
|
|
136
|
+
windowHeight
|
|
176
137
|
) {
|
|
177
138
|
updateIosWidthHeight();
|
|
178
139
|
}
|
|
@@ -285,13 +246,13 @@
|
|
|
285
246
|
|
|
286
247
|
isMobile = getIsMobile();
|
|
287
248
|
|
|
288
|
-
|
|
249
|
+
isIos = isAppleMobile;
|
|
250
|
+
isAndroid = !isAppleMobile && /Android/.test(navigator.userAgent);
|
|
251
|
+
isIpadOS = getIsIpadOS();
|
|
289
252
|
|
|
290
253
|
isFullscreen = getIsFullscreen();
|
|
291
254
|
|
|
292
|
-
isPwa =
|
|
293
|
-
'(display-mode: fullscreen) or (display-mode: standalone)'
|
|
294
|
-
).matches;
|
|
255
|
+
isPwa = getIsPwa();
|
|
295
256
|
|
|
296
257
|
updateIosWidthHeight();
|
|
297
258
|
|
|
@@ -364,26 +325,6 @@
|
|
|
364
325
|
}
|
|
365
326
|
});
|
|
366
327
|
|
|
367
|
-
/**
|
|
368
|
-
* Returns true if the window is in full screen
|
|
369
|
-
* - Checks if CSS thinks we're in fullscreen mode
|
|
370
|
-
* - Checks if there is a fullscreen element (for safari)
|
|
371
|
-
*/
|
|
372
|
-
function getIsFullscreen() {
|
|
373
|
-
if (
|
|
374
|
-
window.matchMedia(
|
|
375
|
-
'(display-mode: fullscreen) or (display-mode: standalone)'
|
|
376
|
-
).matches
|
|
377
|
-
) {
|
|
378
|
-
return true;
|
|
379
|
-
} else if (document.fullscreenElement) {
|
|
380
|
-
// Safari
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
328
|
async function requestFullscreen() {
|
|
388
329
|
// console.debug('Request full screen');
|
|
389
330
|
show = false;
|
|
@@ -484,7 +425,8 @@
|
|
|
484
425
|
isMobile,
|
|
485
426
|
isIos,
|
|
486
427
|
isAndroid,
|
|
487
|
-
|
|
428
|
+
isIpadOS,
|
|
429
|
+
isPwa,
|
|
488
430
|
isFullscreen,
|
|
489
431
|
isDevMode,
|
|
490
432
|
requestDevmode,
|
|
@@ -508,7 +450,8 @@
|
|
|
508
450
|
isMobile,
|
|
509
451
|
isIos,
|
|
510
452
|
isAndroid,
|
|
511
|
-
|
|
453
|
+
isIpadOS,
|
|
454
|
+
isPwa,
|
|
512
455
|
isFullscreen,
|
|
513
456
|
isDevMode,
|
|
514
457
|
requestDevmode,
|
|
@@ -532,7 +475,8 @@
|
|
|
532
475
|
isMobile,
|
|
533
476
|
isIos,
|
|
534
477
|
isAndroid,
|
|
535
|
-
|
|
478
|
+
isIpadOS,
|
|
479
|
+
isPwa,
|
|
536
480
|
isFullscreen,
|
|
537
481
|
isDevMode,
|
|
538
482
|
requestDevmode,
|
|
@@ -556,7 +500,8 @@
|
|
|
556
500
|
isMobile,
|
|
557
501
|
isIos,
|
|
558
502
|
isAndroid,
|
|
559
|
-
|
|
503
|
+
isIpadOS,
|
|
504
|
+
isPwa,
|
|
560
505
|
isFullscreen,
|
|
561
506
|
isDevMode,
|
|
562
507
|
requestDevmode,
|
|
@@ -581,7 +526,8 @@
|
|
|
581
526
|
isMobile,
|
|
582
527
|
isIos,
|
|
583
528
|
isAndroid,
|
|
584
|
-
|
|
529
|
+
isIpadOS,
|
|
530
|
+
isPwa,
|
|
585
531
|
isFullscreen,
|
|
586
532
|
isDevMode,
|
|
587
533
|
requestDevmode,
|
|
@@ -605,7 +551,8 @@
|
|
|
605
551
|
isMobile,
|
|
606
552
|
isIos,
|
|
607
553
|
isAndroid,
|
|
608
|
-
|
|
554
|
+
isIpadOS,
|
|
555
|
+
isPwa,
|
|
609
556
|
isFullscreen,
|
|
610
557
|
isDevMode,
|
|
611
558
|
requestDevmode,
|