@capgo/capacitor-webview-version-checker 8.0.0

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.
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ const WebviewVersionChecker = core.registerPlugin('WebviewVersionChecker', {
6
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.WebviewVersionCheckerWeb()),
7
+ });
8
+
9
+ const UNKNOWN_REASON = 'Web implementation is a compatibility shim. Native Android/iOS implementations provide full WebView checks.';
10
+ class WebviewVersionCheckerWeb extends core.WebPlugin {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.monitoring = false;
14
+ this.checkOnResume = true;
15
+ this.autoPromptOnOutdated = false;
16
+ this.lastStatus = null;
17
+ }
18
+ async check(options = {}) {
19
+ var _a;
20
+ const currentVersion = this.detectCurrentVersion();
21
+ const currentMajorVersion = this.parseMajorVersion(currentVersion);
22
+ const latestVersion = options.latestVersion;
23
+ const latestMajorVersion = this.parseMajorVersion(latestVersion);
24
+ let state = 'unknown';
25
+ let reason = UNKNOWN_REASON;
26
+ if (latestVersion && currentVersion) {
27
+ const cmp = this.compareVersions(currentVersion, latestVersion);
28
+ state = cmp >= 0 ? 'latest' : 'outdated';
29
+ reason = cmp >= 0 ? 'Current browser engine is at or above the requested latest version.' : 'Current browser engine is below the requested latest version.';
30
+ }
31
+ else if (typeof options.minimumMajorVersion === 'number' && typeof currentMajorVersion === 'number') {
32
+ state = currentMajorVersion >= options.minimumMajorVersion ? 'latest' : 'outdated';
33
+ reason = state === 'latest' ? 'Current browser engine major version meets the minimum requirement.' : 'Current browser engine major version is below the minimum requirement.';
34
+ }
35
+ const status = {
36
+ platform: 'web',
37
+ state,
38
+ isLatest: state === 'latest',
39
+ checkedAt: new Date().toISOString(),
40
+ reason,
41
+ currentVersion,
42
+ currentMajorVersion,
43
+ latestVersion,
44
+ latestMajorVersion,
45
+ updateUrl: options.updateUrl,
46
+ source: (_a = options.source) !== null && _a !== void 0 ? _a : 'web-shim',
47
+ };
48
+ this.lastStatus = status;
49
+ this.notifyListeners('statusChanged', status);
50
+ if (state === 'latest') {
51
+ this.notifyListeners('webViewLatest', status);
52
+ }
53
+ else if (state === 'outdated') {
54
+ this.notifyListeners('webViewOutdated', status);
55
+ if (options.showPromptOnOutdated || this.autoPromptOnOutdated) {
56
+ await this.showUpdatePrompt({ updateUrl: status.updateUrl });
57
+ }
58
+ }
59
+ return status;
60
+ }
61
+ async startMonitoring(options = {}) {
62
+ var _a, _b, _c, _d;
63
+ this.monitoring = true;
64
+ this.checkOnResume = (_a = options.checkOnResume) !== null && _a !== void 0 ? _a : true;
65
+ this.autoPromptOnOutdated = (_b = options.autoPromptOnOutdated) !== null && _b !== void 0 ? _b : false;
66
+ if ((_c = options.checkOnStart) !== null && _c !== void 0 ? _c : true) {
67
+ await this.check(Object.assign(Object.assign({}, options), { source: (_d = options.source) !== null && _d !== void 0 ? _d : 'startMonitoring' }));
68
+ }
69
+ return {
70
+ monitoring: this.monitoring,
71
+ checkOnResume: this.checkOnResume,
72
+ autoPromptOnOutdated: this.autoPromptOnOutdated,
73
+ };
74
+ }
75
+ async stopMonitoring() {
76
+ this.monitoring = false;
77
+ return {
78
+ monitoring: this.monitoring,
79
+ checkOnResume: this.checkOnResume,
80
+ autoPromptOnOutdated: this.autoPromptOnOutdated,
81
+ };
82
+ }
83
+ async getLastStatus() {
84
+ return {
85
+ status: this.lastStatus,
86
+ };
87
+ }
88
+ async showUpdatePrompt(options = {}) {
89
+ var _a, _b;
90
+ const url = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl;
91
+ if (!url) {
92
+ return {
93
+ shown: false,
94
+ openedUpdatePage: false,
95
+ };
96
+ }
97
+ const opened = this.openUrl(url);
98
+ return {
99
+ shown: true,
100
+ openedUpdatePage: opened,
101
+ };
102
+ }
103
+ async openUpdatePage(options = {}) {
104
+ var _a, _b, _c;
105
+ const url = (_c = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl) !== null && _c !== void 0 ? _c : '';
106
+ if (!url) {
107
+ return {
108
+ opened: false,
109
+ url,
110
+ };
111
+ }
112
+ return {
113
+ opened: this.openUrl(url),
114
+ url,
115
+ };
116
+ }
117
+ detectCurrentVersion() {
118
+ const chromiumMatch = navigator.userAgent.match(/Chrome\/([\d.]+)/i);
119
+ if (chromiumMatch && chromiumMatch[1]) {
120
+ return chromiumMatch[1];
121
+ }
122
+ const appleWebKitMatch = navigator.userAgent.match(/AppleWebKit\/([\d.]+)/i);
123
+ if (appleWebKitMatch && appleWebKitMatch[1]) {
124
+ return appleWebKitMatch[1];
125
+ }
126
+ return navigator.userAgent;
127
+ }
128
+ openUrl(url) {
129
+ try {
130
+ window.open(url, '_blank', 'noopener,noreferrer');
131
+ return true;
132
+ }
133
+ catch (_a) {
134
+ return false;
135
+ }
136
+ }
137
+ parseMajorVersion(version) {
138
+ if (!version) {
139
+ return undefined;
140
+ }
141
+ const match = version.match(/(\d+)/);
142
+ if (!match) {
143
+ return undefined;
144
+ }
145
+ const major = Number.parseInt(match[1], 10);
146
+ return Number.isFinite(major) ? major : undefined;
147
+ }
148
+ compareVersions(left, right) {
149
+ var _a, _b;
150
+ const leftParts = left.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));
151
+ const rightParts = right.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));
152
+ const maxLength = Math.max(leftParts.length, rightParts.length);
153
+ for (let i = 0; i < maxLength; i += 1) {
154
+ const a = (_a = leftParts[i]) !== null && _a !== void 0 ? _a : 0;
155
+ const b = (_b = rightParts[i]) !== null && _b !== void 0 ? _b : 0;
156
+ if (a > b) {
157
+ return 1;
158
+ }
159
+ if (a < b) {
160
+ return -1;
161
+ }
162
+ }
163
+ return 0;
164
+ }
165
+ }
166
+
167
+ var web = /*#__PURE__*/Object.freeze({
168
+ __proto__: null,
169
+ WebviewVersionCheckerWeb: WebviewVersionCheckerWeb
170
+ });
171
+
172
+ exports.WebviewVersionChecker = WebviewVersionChecker;
173
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst WebviewVersionChecker = registerPlugin('WebviewVersionChecker', {\n web: () => import('./web').then((m) => new m.WebviewVersionCheckerWeb()),\n});\nexport * from './definitions';\nexport { WebviewVersionChecker };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst UNKNOWN_REASON = 'Web implementation is a compatibility shim. Native Android/iOS implementations provide full WebView checks.';\nexport class WebviewVersionCheckerWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.monitoring = false;\n this.checkOnResume = true;\n this.autoPromptOnOutdated = false;\n this.lastStatus = null;\n }\n async check(options = {}) {\n var _a;\n const currentVersion = this.detectCurrentVersion();\n const currentMajorVersion = this.parseMajorVersion(currentVersion);\n const latestVersion = options.latestVersion;\n const latestMajorVersion = this.parseMajorVersion(latestVersion);\n let state = 'unknown';\n let reason = UNKNOWN_REASON;\n if (latestVersion && currentVersion) {\n const cmp = this.compareVersions(currentVersion, latestVersion);\n state = cmp >= 0 ? 'latest' : 'outdated';\n reason = cmp >= 0 ? 'Current browser engine is at or above the requested latest version.' : 'Current browser engine is below the requested latest version.';\n }\n else if (typeof options.minimumMajorVersion === 'number' && typeof currentMajorVersion === 'number') {\n state = currentMajorVersion >= options.minimumMajorVersion ? 'latest' : 'outdated';\n reason = state === 'latest' ? 'Current browser engine major version meets the minimum requirement.' : 'Current browser engine major version is below the minimum requirement.';\n }\n const status = {\n platform: 'web',\n state,\n isLatest: state === 'latest',\n checkedAt: new Date().toISOString(),\n reason,\n currentVersion,\n currentMajorVersion,\n latestVersion,\n latestMajorVersion,\n updateUrl: options.updateUrl,\n source: (_a = options.source) !== null && _a !== void 0 ? _a : 'web-shim',\n };\n this.lastStatus = status;\n this.notifyListeners('statusChanged', status);\n if (state === 'latest') {\n this.notifyListeners('webViewLatest', status);\n }\n else if (state === 'outdated') {\n this.notifyListeners('webViewOutdated', status);\n if (options.showPromptOnOutdated || this.autoPromptOnOutdated) {\n await this.showUpdatePrompt({ updateUrl: status.updateUrl });\n }\n }\n return status;\n }\n async startMonitoring(options = {}) {\n var _a, _b, _c, _d;\n this.monitoring = true;\n this.checkOnResume = (_a = options.checkOnResume) !== null && _a !== void 0 ? _a : true;\n this.autoPromptOnOutdated = (_b = options.autoPromptOnOutdated) !== null && _b !== void 0 ? _b : false;\n if ((_c = options.checkOnStart) !== null && _c !== void 0 ? _c : true) {\n await this.check(Object.assign(Object.assign({}, options), { source: (_d = options.source) !== null && _d !== void 0 ? _d : 'startMonitoring' }));\n }\n return {\n monitoring: this.monitoring,\n checkOnResume: this.checkOnResume,\n autoPromptOnOutdated: this.autoPromptOnOutdated,\n };\n }\n async stopMonitoring() {\n this.monitoring = false;\n return {\n monitoring: this.monitoring,\n checkOnResume: this.checkOnResume,\n autoPromptOnOutdated: this.autoPromptOnOutdated,\n };\n }\n async getLastStatus() {\n return {\n status: this.lastStatus,\n };\n }\n async showUpdatePrompt(options = {}) {\n var _a, _b;\n const url = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl;\n if (!url) {\n return {\n shown: false,\n openedUpdatePage: false,\n };\n }\n const opened = this.openUrl(url);\n return {\n shown: true,\n openedUpdatePage: opened,\n };\n }\n async openUpdatePage(options = {}) {\n var _a, _b, _c;\n const url = (_c = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl) !== null && _c !== void 0 ? _c : '';\n if (!url) {\n return {\n opened: false,\n url,\n };\n }\n return {\n opened: this.openUrl(url),\n url,\n };\n }\n detectCurrentVersion() {\n const chromiumMatch = navigator.userAgent.match(/Chrome\\/([\\d.]+)/i);\n if (chromiumMatch && chromiumMatch[1]) {\n return chromiumMatch[1];\n }\n const appleWebKitMatch = navigator.userAgent.match(/AppleWebKit\\/([\\d.]+)/i);\n if (appleWebKitMatch && appleWebKitMatch[1]) {\n return appleWebKitMatch[1];\n }\n return navigator.userAgent;\n }\n openUrl(url) {\n try {\n window.open(url, '_blank', 'noopener,noreferrer');\n return true;\n }\n catch (_a) {\n return false;\n }\n }\n parseMajorVersion(version) {\n if (!version) {\n return undefined;\n }\n const match = version.match(/(\\d+)/);\n if (!match) {\n return undefined;\n }\n const major = Number.parseInt(match[1], 10);\n return Number.isFinite(major) ? major : undefined;\n }\n compareVersions(left, right) {\n var _a, _b;\n const leftParts = left.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));\n const rightParts = right.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));\n const maxLength = Math.max(leftParts.length, rightParts.length);\n for (let i = 0; i < maxLength; i += 1) {\n const a = (_a = leftParts[i]) !== null && _a !== void 0 ? _a : 0;\n const b = (_b = rightParts[i]) !== null && _b !== void 0 ? _b : 0;\n if (a > b) {\n return 1;\n }\n if (a < b) {\n return -1;\n }\n }\n return 0;\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,qBAAqB,GAAGA,mBAAc,CAAC,uBAAuB,EAAE;AACtE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,wBAAwB,EAAE,CAAC;AAC5E,CAAC;;ACFD,MAAM,cAAc,GAAG,6GAA6G;AAC7H,MAAM,wBAAwB,SAASC,cAAS,CAAC;AACxD,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;AAC3B,QAAQ,IAAI,CAAC,UAAU,GAAG,KAAK;AAC/B,QAAQ,IAAI,CAAC,aAAa,GAAG,IAAI;AACjC,QAAQ,IAAI,CAAC,oBAAoB,GAAG,KAAK;AACzC,QAAQ,IAAI,CAAC,UAAU,GAAG,IAAI;AAC9B,IAAI;AACJ,IAAI,MAAM,KAAK,CAAC,OAAO,GAAG,EAAE,EAAE;AAC9B,QAAQ,IAAI,EAAE;AACd,QAAQ,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,EAAE;AAC1D,QAAQ,MAAM,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC;AAC1E,QAAQ,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa;AACnD,QAAQ,MAAM,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC;AACxE,QAAQ,IAAI,KAAK,GAAG,SAAS;AAC7B,QAAQ,IAAI,MAAM,GAAG,cAAc;AACnC,QAAQ,IAAI,aAAa,IAAI,cAAc,EAAE;AAC7C,YAAY,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,aAAa,CAAC;AAC3E,YAAY,KAAK,GAAG,GAAG,IAAI,CAAC,GAAG,QAAQ,GAAG,UAAU;AACpD,YAAY,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,qEAAqE,GAAG,+DAA+D;AACvK,QAAQ;AACR,aAAa,IAAI,OAAO,OAAO,CAAC,mBAAmB,KAAK,QAAQ,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE;AAC7G,YAAY,KAAK,GAAG,mBAAmB,IAAI,OAAO,CAAC,mBAAmB,GAAG,QAAQ,GAAG,UAAU;AAC9F,YAAY,MAAM,GAAG,KAAK,KAAK,QAAQ,GAAG,qEAAqE,GAAG,wEAAwE;AAC1L,QAAQ;AACR,QAAQ,MAAM,MAAM,GAAG;AACvB,YAAY,QAAQ,EAAE,KAAK;AAC3B,YAAY,KAAK;AACjB,YAAY,QAAQ,EAAE,KAAK,KAAK,QAAQ;AACxC,YAAY,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC/C,YAAY,MAAM;AAClB,YAAY,cAAc;AAC1B,YAAY,mBAAmB;AAC/B,YAAY,aAAa;AACzB,YAAY,kBAAkB;AAC9B,YAAY,SAAS,EAAE,OAAO,CAAC,SAAS;AACxC,YAAY,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,UAAU;AACrF,SAAS;AACT,QAAQ,IAAI,CAAC,UAAU,GAAG,MAAM;AAChC,QAAQ,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,MAAM,CAAC;AACrD,QAAQ,IAAI,KAAK,KAAK,QAAQ,EAAE;AAChC,YAAY,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,MAAM,CAAC;AACzD,QAAQ;AACR,aAAa,IAAI,KAAK,KAAK,UAAU,EAAE;AACvC,YAAY,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,MAAM,CAAC;AAC3D,YAAY,IAAI,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC,oBAAoB,EAAE;AAC3E,gBAAgB,MAAM,IAAI,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;AAC5E,YAAY;AACZ,QAAQ;AACR,QAAQ,OAAO,MAAM;AACrB,IAAI;AACJ,IAAI,MAAM,eAAe,CAAC,OAAO,GAAG,EAAE,EAAE;AACxC,QAAQ,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;AAC1B,QAAQ,IAAI,CAAC,UAAU,GAAG,IAAI;AAC9B,QAAQ,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,aAAa,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI;AAC/F,QAAQ,IAAI,CAAC,oBAAoB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,oBAAoB,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,KAAK;AAC9G,QAAQ,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE;AAC/E,YAAY,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,iBAAiB,EAAE,CAAC,CAAC;AAC7J,QAAQ;AACR,QAAQ,OAAO;AACf,YAAY,UAAU,EAAE,IAAI,CAAC,UAAU;AACvC,YAAY,aAAa,EAAE,IAAI,CAAC,aAAa;AAC7C,YAAY,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;AAC3D,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,cAAc,GAAG;AAC3B,QAAQ,IAAI,CAAC,UAAU,GAAG,KAAK;AAC/B,QAAQ,OAAO;AACf,YAAY,UAAU,EAAE,IAAI,CAAC,UAAU;AACvC,YAAY,aAAa,EAAE,IAAI,CAAC,aAAa;AAC7C,YAAY,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;AAC3D,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,aAAa,GAAG;AAC1B,QAAQ,OAAO;AACf,YAAY,MAAM,EAAE,IAAI,CAAC,UAAU;AACnC,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,gBAAgB,CAAC,OAAO,GAAG,EAAE,EAAE;AACzC,QAAQ,IAAI,EAAE,EAAE,EAAE;AAClB,QAAQ,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,SAAS;AACtJ,QAAQ,IAAI,CAAC,GAAG,EAAE;AAClB,YAAY,OAAO;AACnB,gBAAgB,KAAK,EAAE,KAAK;AAC5B,gBAAgB,gBAAgB,EAAE,KAAK;AACvC,aAAa;AACb,QAAQ;AACR,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;AACxC,QAAQ,OAAO;AACf,YAAY,KAAK,EAAE,IAAI;AACvB,YAAY,gBAAgB,EAAE,MAAM;AACpC,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,cAAc,CAAC,OAAO,GAAG,EAAE,EAAE;AACvC,QAAQ,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;AACtB,QAAQ,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,EAAE;AACjM,QAAQ,IAAI,CAAC,GAAG,EAAE;AAClB,YAAY,OAAO;AACnB,gBAAgB,MAAM,EAAE,KAAK;AAC7B,gBAAgB,GAAG;AACnB,aAAa;AACb,QAAQ;AACR,QAAQ,OAAO;AACf,YAAY,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;AACrC,YAAY,GAAG;AACf,SAAS;AACT,IAAI;AACJ,IAAI,oBAAoB,GAAG;AAC3B,QAAQ,MAAM,aAAa,GAAG,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,mBAAmB,CAAC;AAC5E,QAAQ,IAAI,aAAa,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE;AAC/C,YAAY,OAAO,aAAa,CAAC,CAAC,CAAC;AACnC,QAAQ;AACR,QAAQ,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,wBAAwB,CAAC;AACpF,QAAQ,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE;AACrD,YAAY,OAAO,gBAAgB,CAAC,CAAC,CAAC;AACtC,QAAQ;AACR,QAAQ,OAAO,SAAS,CAAC,SAAS;AAClC,IAAI;AACJ,IAAI,OAAO,CAAC,GAAG,EAAE;AACjB,QAAQ,IAAI;AACZ,YAAY,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,qBAAqB,CAAC;AAC7D,YAAY,OAAO,IAAI;AACvB,QAAQ;AACR,QAAQ,OAAO,EAAE,EAAE;AACnB,YAAY,OAAO,KAAK;AACxB,QAAQ;AACR,IAAI;AACJ,IAAI,iBAAiB,CAAC,OAAO,EAAE;AAC/B,QAAQ,IAAI,CAAC,OAAO,EAAE;AACtB,YAAY,OAAO,SAAS;AAC5B,QAAQ;AACR,QAAQ,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;AAC5C,QAAQ,IAAI,CAAC,KAAK,EAAE;AACpB,YAAY,OAAO,SAAS;AAC5B,QAAQ;AACR,QAAQ,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACnD,QAAQ,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,SAAS;AACzD,IAAI;AACJ,IAAI,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE;AACjC,QAAQ,IAAI,EAAE,EAAE,EAAE;AAClB,QAAQ,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACxG,QAAQ,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC1G,QAAQ,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC;AACvE,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE;AAC/C,YAAY,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC;AAC5E,YAAY,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC;AAC7E,YAAY,IAAI,CAAC,GAAG,CAAC,EAAE;AACvB,gBAAgB,OAAO,CAAC;AACxB,YAAY;AACZ,YAAY,IAAI,CAAC,GAAG,CAAC,EAAE;AACvB,gBAAgB,OAAO,EAAE;AACzB,YAAY;AACZ,QAAQ;AACR,QAAQ,OAAO,CAAC;AAChB,IAAI;AACJ;;;;;;;;;"}
package/dist/plugin.js ADDED
@@ -0,0 +1,176 @@
1
+ var capacitorWebviewVersionChecker = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ const WebviewVersionChecker = core.registerPlugin('WebviewVersionChecker', {
5
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.WebviewVersionCheckerWeb()),
6
+ });
7
+
8
+ const UNKNOWN_REASON = 'Web implementation is a compatibility shim. Native Android/iOS implementations provide full WebView checks.';
9
+ class WebviewVersionCheckerWeb extends core.WebPlugin {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.monitoring = false;
13
+ this.checkOnResume = true;
14
+ this.autoPromptOnOutdated = false;
15
+ this.lastStatus = null;
16
+ }
17
+ async check(options = {}) {
18
+ var _a;
19
+ const currentVersion = this.detectCurrentVersion();
20
+ const currentMajorVersion = this.parseMajorVersion(currentVersion);
21
+ const latestVersion = options.latestVersion;
22
+ const latestMajorVersion = this.parseMajorVersion(latestVersion);
23
+ let state = 'unknown';
24
+ let reason = UNKNOWN_REASON;
25
+ if (latestVersion && currentVersion) {
26
+ const cmp = this.compareVersions(currentVersion, latestVersion);
27
+ state = cmp >= 0 ? 'latest' : 'outdated';
28
+ reason = cmp >= 0 ? 'Current browser engine is at or above the requested latest version.' : 'Current browser engine is below the requested latest version.';
29
+ }
30
+ else if (typeof options.minimumMajorVersion === 'number' && typeof currentMajorVersion === 'number') {
31
+ state = currentMajorVersion >= options.minimumMajorVersion ? 'latest' : 'outdated';
32
+ reason = state === 'latest' ? 'Current browser engine major version meets the minimum requirement.' : 'Current browser engine major version is below the minimum requirement.';
33
+ }
34
+ const status = {
35
+ platform: 'web',
36
+ state,
37
+ isLatest: state === 'latest',
38
+ checkedAt: new Date().toISOString(),
39
+ reason,
40
+ currentVersion,
41
+ currentMajorVersion,
42
+ latestVersion,
43
+ latestMajorVersion,
44
+ updateUrl: options.updateUrl,
45
+ source: (_a = options.source) !== null && _a !== void 0 ? _a : 'web-shim',
46
+ };
47
+ this.lastStatus = status;
48
+ this.notifyListeners('statusChanged', status);
49
+ if (state === 'latest') {
50
+ this.notifyListeners('webViewLatest', status);
51
+ }
52
+ else if (state === 'outdated') {
53
+ this.notifyListeners('webViewOutdated', status);
54
+ if (options.showPromptOnOutdated || this.autoPromptOnOutdated) {
55
+ await this.showUpdatePrompt({ updateUrl: status.updateUrl });
56
+ }
57
+ }
58
+ return status;
59
+ }
60
+ async startMonitoring(options = {}) {
61
+ var _a, _b, _c, _d;
62
+ this.monitoring = true;
63
+ this.checkOnResume = (_a = options.checkOnResume) !== null && _a !== void 0 ? _a : true;
64
+ this.autoPromptOnOutdated = (_b = options.autoPromptOnOutdated) !== null && _b !== void 0 ? _b : false;
65
+ if ((_c = options.checkOnStart) !== null && _c !== void 0 ? _c : true) {
66
+ await this.check(Object.assign(Object.assign({}, options), { source: (_d = options.source) !== null && _d !== void 0 ? _d : 'startMonitoring' }));
67
+ }
68
+ return {
69
+ monitoring: this.monitoring,
70
+ checkOnResume: this.checkOnResume,
71
+ autoPromptOnOutdated: this.autoPromptOnOutdated,
72
+ };
73
+ }
74
+ async stopMonitoring() {
75
+ this.monitoring = false;
76
+ return {
77
+ monitoring: this.monitoring,
78
+ checkOnResume: this.checkOnResume,
79
+ autoPromptOnOutdated: this.autoPromptOnOutdated,
80
+ };
81
+ }
82
+ async getLastStatus() {
83
+ return {
84
+ status: this.lastStatus,
85
+ };
86
+ }
87
+ async showUpdatePrompt(options = {}) {
88
+ var _a, _b;
89
+ const url = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl;
90
+ if (!url) {
91
+ return {
92
+ shown: false,
93
+ openedUpdatePage: false,
94
+ };
95
+ }
96
+ const opened = this.openUrl(url);
97
+ return {
98
+ shown: true,
99
+ openedUpdatePage: opened,
100
+ };
101
+ }
102
+ async openUpdatePage(options = {}) {
103
+ var _a, _b, _c;
104
+ const url = (_c = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl) !== null && _c !== void 0 ? _c : '';
105
+ if (!url) {
106
+ return {
107
+ opened: false,
108
+ url,
109
+ };
110
+ }
111
+ return {
112
+ opened: this.openUrl(url),
113
+ url,
114
+ };
115
+ }
116
+ detectCurrentVersion() {
117
+ const chromiumMatch = navigator.userAgent.match(/Chrome\/([\d.]+)/i);
118
+ if (chromiumMatch && chromiumMatch[1]) {
119
+ return chromiumMatch[1];
120
+ }
121
+ const appleWebKitMatch = navigator.userAgent.match(/AppleWebKit\/([\d.]+)/i);
122
+ if (appleWebKitMatch && appleWebKitMatch[1]) {
123
+ return appleWebKitMatch[1];
124
+ }
125
+ return navigator.userAgent;
126
+ }
127
+ openUrl(url) {
128
+ try {
129
+ window.open(url, '_blank', 'noopener,noreferrer');
130
+ return true;
131
+ }
132
+ catch (_a) {
133
+ return false;
134
+ }
135
+ }
136
+ parseMajorVersion(version) {
137
+ if (!version) {
138
+ return undefined;
139
+ }
140
+ const match = version.match(/(\d+)/);
141
+ if (!match) {
142
+ return undefined;
143
+ }
144
+ const major = Number.parseInt(match[1], 10);
145
+ return Number.isFinite(major) ? major : undefined;
146
+ }
147
+ compareVersions(left, right) {
148
+ var _a, _b;
149
+ const leftParts = left.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));
150
+ const rightParts = right.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));
151
+ const maxLength = Math.max(leftParts.length, rightParts.length);
152
+ for (let i = 0; i < maxLength; i += 1) {
153
+ const a = (_a = leftParts[i]) !== null && _a !== void 0 ? _a : 0;
154
+ const b = (_b = rightParts[i]) !== null && _b !== void 0 ? _b : 0;
155
+ if (a > b) {
156
+ return 1;
157
+ }
158
+ if (a < b) {
159
+ return -1;
160
+ }
161
+ }
162
+ return 0;
163
+ }
164
+ }
165
+
166
+ var web = /*#__PURE__*/Object.freeze({
167
+ __proto__: null,
168
+ WebviewVersionCheckerWeb: WebviewVersionCheckerWeb
169
+ });
170
+
171
+ exports.WebviewVersionChecker = WebviewVersionChecker;
172
+
173
+ return exports;
174
+
175
+ })({}, capacitorExports);
176
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst WebviewVersionChecker = registerPlugin('WebviewVersionChecker', {\n web: () => import('./web').then((m) => new m.WebviewVersionCheckerWeb()),\n});\nexport * from './definitions';\nexport { WebviewVersionChecker };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst UNKNOWN_REASON = 'Web implementation is a compatibility shim. Native Android/iOS implementations provide full WebView checks.';\nexport class WebviewVersionCheckerWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.monitoring = false;\n this.checkOnResume = true;\n this.autoPromptOnOutdated = false;\n this.lastStatus = null;\n }\n async check(options = {}) {\n var _a;\n const currentVersion = this.detectCurrentVersion();\n const currentMajorVersion = this.parseMajorVersion(currentVersion);\n const latestVersion = options.latestVersion;\n const latestMajorVersion = this.parseMajorVersion(latestVersion);\n let state = 'unknown';\n let reason = UNKNOWN_REASON;\n if (latestVersion && currentVersion) {\n const cmp = this.compareVersions(currentVersion, latestVersion);\n state = cmp >= 0 ? 'latest' : 'outdated';\n reason = cmp >= 0 ? 'Current browser engine is at or above the requested latest version.' : 'Current browser engine is below the requested latest version.';\n }\n else if (typeof options.minimumMajorVersion === 'number' && typeof currentMajorVersion === 'number') {\n state = currentMajorVersion >= options.minimumMajorVersion ? 'latest' : 'outdated';\n reason = state === 'latest' ? 'Current browser engine major version meets the minimum requirement.' : 'Current browser engine major version is below the minimum requirement.';\n }\n const status = {\n platform: 'web',\n state,\n isLatest: state === 'latest',\n checkedAt: new Date().toISOString(),\n reason,\n currentVersion,\n currentMajorVersion,\n latestVersion,\n latestMajorVersion,\n updateUrl: options.updateUrl,\n source: (_a = options.source) !== null && _a !== void 0 ? _a : 'web-shim',\n };\n this.lastStatus = status;\n this.notifyListeners('statusChanged', status);\n if (state === 'latest') {\n this.notifyListeners('webViewLatest', status);\n }\n else if (state === 'outdated') {\n this.notifyListeners('webViewOutdated', status);\n if (options.showPromptOnOutdated || this.autoPromptOnOutdated) {\n await this.showUpdatePrompt({ updateUrl: status.updateUrl });\n }\n }\n return status;\n }\n async startMonitoring(options = {}) {\n var _a, _b, _c, _d;\n this.monitoring = true;\n this.checkOnResume = (_a = options.checkOnResume) !== null && _a !== void 0 ? _a : true;\n this.autoPromptOnOutdated = (_b = options.autoPromptOnOutdated) !== null && _b !== void 0 ? _b : false;\n if ((_c = options.checkOnStart) !== null && _c !== void 0 ? _c : true) {\n await this.check(Object.assign(Object.assign({}, options), { source: (_d = options.source) !== null && _d !== void 0 ? _d : 'startMonitoring' }));\n }\n return {\n monitoring: this.monitoring,\n checkOnResume: this.checkOnResume,\n autoPromptOnOutdated: this.autoPromptOnOutdated,\n };\n }\n async stopMonitoring() {\n this.monitoring = false;\n return {\n monitoring: this.monitoring,\n checkOnResume: this.checkOnResume,\n autoPromptOnOutdated: this.autoPromptOnOutdated,\n };\n }\n async getLastStatus() {\n return {\n status: this.lastStatus,\n };\n }\n async showUpdatePrompt(options = {}) {\n var _a, _b;\n const url = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl;\n if (!url) {\n return {\n shown: false,\n openedUpdatePage: false,\n };\n }\n const opened = this.openUrl(url);\n return {\n shown: true,\n openedUpdatePage: opened,\n };\n }\n async openUpdatePage(options = {}) {\n var _a, _b, _c;\n const url = (_c = (_a = options.updateUrl) !== null && _a !== void 0 ? _a : (_b = this.lastStatus) === null || _b === void 0 ? void 0 : _b.updateUrl) !== null && _c !== void 0 ? _c : '';\n if (!url) {\n return {\n opened: false,\n url,\n };\n }\n return {\n opened: this.openUrl(url),\n url,\n };\n }\n detectCurrentVersion() {\n const chromiumMatch = navigator.userAgent.match(/Chrome\\/([\\d.]+)/i);\n if (chromiumMatch && chromiumMatch[1]) {\n return chromiumMatch[1];\n }\n const appleWebKitMatch = navigator.userAgent.match(/AppleWebKit\\/([\\d.]+)/i);\n if (appleWebKitMatch && appleWebKitMatch[1]) {\n return appleWebKitMatch[1];\n }\n return navigator.userAgent;\n }\n openUrl(url) {\n try {\n window.open(url, '_blank', 'noopener,noreferrer');\n return true;\n }\n catch (_a) {\n return false;\n }\n }\n parseMajorVersion(version) {\n if (!version) {\n return undefined;\n }\n const match = version.match(/(\\d+)/);\n if (!match) {\n return undefined;\n }\n const major = Number.parseInt(match[1], 10);\n return Number.isFinite(major) ? major : undefined;\n }\n compareVersions(left, right) {\n var _a, _b;\n const leftParts = left.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));\n const rightParts = right.split(/[^0-9]+/).filter(Boolean).map((part) => Number.parseInt(part, 10));\n const maxLength = Math.max(leftParts.length, rightParts.length);\n for (let i = 0; i < maxLength; i += 1) {\n const a = (_a = leftParts[i]) !== null && _a !== void 0 ? _a : 0;\n const b = (_b = rightParts[i]) !== null && _b !== void 0 ? _b : 0;\n if (a > b) {\n return 1;\n }\n if (a < b) {\n return -1;\n }\n }\n return 0;\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ private let defaultIOSUpdateUrl = "https://support.apple.com/guide/iphone/update-ios-iph3e504502/ios"
5
+
6
+ @objc public class WebviewVersionChecker: NSObject {
7
+ private let isoFormatter: ISO8601DateFormatter = {
8
+ let formatter = ISO8601DateFormatter()
9
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
10
+ return formatter
11
+ }()
12
+
13
+ func buildStatus(source: String, latestVersion: String?, minimumMajorVersion: Int?, updateUrl: String?) -> [String: Any] {
14
+ let currentVersion = UIDevice.current.systemVersion
15
+ let currentMajorVersion = parseMajorVersion(currentVersion)
16
+ let normalizedLatestVersion = normalizeVersion(latestVersion)
17
+ let latestMajorVersion = parseMajorVersion(normalizedLatestVersion)
18
+
19
+ var status: [String: Any] = [
20
+ "platform": "ios",
21
+ "source": source,
22
+ "checkedAt": isoFormatter.string(from: Date()),
23
+ "currentVersion": currentVersion,
24
+ "updateUrl": normalizedUpdateUrl(updateUrl)
25
+ ]
26
+
27
+ if let currentMajorVersion {
28
+ status["currentMajorVersion"] = currentMajorVersion
29
+ }
30
+
31
+ if let normalizedLatestVersion {
32
+ status["latestVersion"] = normalizedLatestVersion
33
+ }
34
+
35
+ if let latestMajorVersion {
36
+ status["latestMajorVersion"] = latestMajorVersion
37
+ }
38
+
39
+ if let normalizedLatestVersion {
40
+ let cmp = compareVersions(currentVersion, normalizedLatestVersion)
41
+ let isLatest = cmp >= 0
42
+ status["state"] = isLatest ? "latest" : "outdated"
43
+ status["isLatest"] = isLatest
44
+ status["reason"] = isLatest
45
+ ? "Installed iOS WebKit version is at or above the requested latest version."
46
+ : "Installed iOS WebKit version is behind the requested latest version."
47
+ return status
48
+ }
49
+
50
+ if let minimumMajorVersion, let currentMajorVersion {
51
+ let isLatest = currentMajorVersion >= minimumMajorVersion
52
+ status["state"] = isLatest ? "latest" : "outdated"
53
+ status["isLatest"] = isLatest
54
+ status["reason"] = isLatest
55
+ ? "Installed iOS major version satisfies the configured minimum major version."
56
+ : "Installed iOS major version is below the configured minimum major version."
57
+ return status
58
+ }
59
+
60
+ status["state"] = "unknown"
61
+ status["isLatest"] = false
62
+ status["reason"] = "iOS WebKit updates are tied to iOS updates. Configure latestVersion or minimumMajorVersion to enforce a policy."
63
+ return status
64
+ }
65
+
66
+ func defaultPromptMessage(status: [String: Any]?) -> String {
67
+ guard let status else {
68
+ return "A newer iOS WebKit version may be available. Please update iOS for best compatibility."
69
+ }
70
+
71
+ let current = (status["currentVersion"] as? String) ?? "current version"
72
+ let latest = (status["latestVersion"] as? String) ?? "the latest available version"
73
+
74
+ return "Your iOS WebKit version (\(current)) may be outdated. Please update toward \(latest)."
75
+ }
76
+
77
+ func normalizedUpdateUrl(_ value: String?) -> String {
78
+ let trimmed = normalizeVersion(value)
79
+ return trimmed ?? defaultIOSUpdateUrl
80
+ }
81
+
82
+ func promptFingerprint(status: [String: Any]?, updateUrl: String) -> String {
83
+ guard let status else {
84
+ return updateUrl
85
+ }
86
+
87
+ let current = (status["currentVersion"] as? String) ?? ""
88
+ let latest = (status["latestVersion"] as? String) ?? ""
89
+ return "\(current)|\(latest)|\(updateUrl)"
90
+ }
91
+
92
+ private func parseMajorVersion(_ value: String?) -> Int? {
93
+ guard let value, !value.isEmpty else {
94
+ return nil
95
+ }
96
+
97
+ var digits = ""
98
+ for character in value {
99
+ if character.isNumber {
100
+ digits.append(character)
101
+ } else if !digits.isEmpty {
102
+ break
103
+ }
104
+ }
105
+
106
+ return Int(digits)
107
+ }
108
+
109
+ private func normalizeVersion(_ value: String?) -> String? {
110
+ guard let value else {
111
+ return nil
112
+ }
113
+
114
+ let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
115
+ return trimmed.isEmpty ? nil : trimmed
116
+ }
117
+
118
+ private func compareVersions(_ left: String, _ right: String) -> Int {
119
+ let leftParts = tokenize(left)
120
+ let rightParts = tokenize(right)
121
+ let maxCount = max(leftParts.count, rightParts.count)
122
+
123
+ for index in 0..<maxCount {
124
+ let a = index < leftParts.count ? leftParts[index] : 0
125
+ let b = index < rightParts.count ? rightParts[index] : 0
126
+ if a > b {
127
+ return 1
128
+ }
129
+ if a < b {
130
+ return -1
131
+ }
132
+ }
133
+
134
+ return 0
135
+ }
136
+
137
+ private func tokenize(_ value: String) -> [Int] {
138
+ value
139
+ .split(whereSeparator: { !$0.isNumber })
140
+ .compactMap { Int($0) }
141
+ }
142
+ }