@saltcorn/mobile-app 1.1.0-beta.2 → 1.1.0-beta.21
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/.babelrc +3 -0
- package/build_scripts/modify_android_manifest.js +47 -0
- package/build_scripts/modify_gradle_cfg.js +34 -0
- package/package.json +20 -11
- package/src/.eslintrc +21 -0
- package/src/helpers/api.js +43 -0
- package/src/helpers/auth.js +191 -0
- package/src/helpers/common.js +175 -0
- package/{www/js/utils/table_utils.js → src/helpers/db_schema.js} +18 -40
- package/src/helpers/file_system.js +102 -0
- package/{www/js/utils/global_utils.js → src/helpers/navigation.js} +175 -335
- package/src/helpers/offline_mode.js +645 -0
- package/src/index.js +20 -0
- package/src/init.js +424 -0
- package/src/routing/index.js +98 -0
- package/{www/js → src/routing}/mocks/request.js +5 -5
- package/{www/js → src/routing}/mocks/response.js +1 -1
- package/{www/js → src/routing}/routes/api.js +10 -15
- package/{www/js → src/routing}/routes/auth.js +12 -6
- package/{www/js → src/routing}/routes/delete.js +9 -6
- package/{www/js → src/routing}/routes/edit.js +9 -6
- package/src/routing/routes/error.js +6 -0
- package/{www/js → src/routing}/routes/fields.js +7 -2
- package/{www/js → src/routing}/routes/page.js +14 -9
- package/{www/js → src/routing}/routes/sync.js +9 -5
- package/{www/js → src/routing}/routes/view.js +16 -11
- package/{www/js/routes/common.js → src/routing/utils.js} +15 -13
- package/webpack.config.js +31 -0
- package/www/data/encoded_site_logo.js +1 -0
- package/www/index.html +23 -493
- package/www/js/{utils/iframe_view_utils.js → iframe_view_utils.js} +187 -273
- package/config.xml +0 -27
- package/res/icon/android/icon.png +0 -0
- package/res/screen/android/splash-icon.png +0 -0
- package/res/screen/ios/Default@2x~universal~anyany.png +0 -0
- package/www/js/routes/error.js +0 -5
- package/www/js/routes/init.js +0 -76
- package/www/js/utils/file_helpers.js +0 -108
- package/www/js/utils/offline_mode_helper.js +0 -625
package/www/index.html
CHANGED
|
@@ -5,500 +5,30 @@
|
|
|
5
5
|
name="viewport"
|
|
6
6
|
content="width=device-width, initial-scale=1, maximum-scale=1"
|
|
7
7
|
/>
|
|
8
|
-
<script src="
|
|
9
|
-
<script src="
|
|
10
|
-
<script src="
|
|
11
|
-
<script src="
|
|
12
|
-
<script src="
|
|
13
|
-
<script src="
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<script
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<script src="js/mocks/request.js"></script>
|
|
31
|
-
<script src="npm_packages/jwt-decode.js"></script>
|
|
32
|
-
<script src="npm_packages/universal-router.min.js"></script>
|
|
33
|
-
<script src="npm_packages/axios.min.js"></script>
|
|
34
|
-
<script src="npm_packages/i18next.min.js"></script>
|
|
35
|
-
<script src="npm_packages/i18nextSprintfPostProcessor.min.js"></script>
|
|
36
|
-
<script>
|
|
37
|
-
const staticPlugins = ["base", "sbadmin2"];
|
|
38
|
-
|
|
39
|
-
async function addScript(scriptObj) {
|
|
40
|
-
let waited = 0;
|
|
41
|
-
const maxWait = 3000;
|
|
42
|
-
|
|
43
|
-
const moduleAvailable = () =>
|
|
44
|
-
window.saltcorn && window.saltcorn[scriptObj.name];
|
|
45
|
-
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
let script = document.createElement("script");
|
|
48
|
-
document.head.appendChild(script);
|
|
49
|
-
|
|
50
|
-
const waitForModule = () => {
|
|
51
|
-
waited += 100;
|
|
52
|
-
if (waited >= maxWait)
|
|
53
|
-
return reject(`unable to load '${scriptObj.name}'`);
|
|
54
|
-
console.log("waiting for " + scriptObj.name);
|
|
55
|
-
setTimeout(function () {
|
|
56
|
-
if (moduleAvailable()) return resolve();
|
|
57
|
-
else waitForModule();
|
|
58
|
-
}, 100);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
script.onload = () => {
|
|
62
|
-
if (!scriptObj.name || moduleAvailable()) return resolve();
|
|
63
|
-
waitForModule();
|
|
64
|
-
};
|
|
65
|
-
script.src = scriptObj.src;
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function loadPlugin(plugin) {
|
|
70
|
-
await addScript({
|
|
71
|
-
src: `js/bundle/${plugin.name}.bundle.js`,
|
|
72
|
-
name: plugin.name,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function loadPlugins(state) {
|
|
77
|
-
const plugins = (await saltcorn.data.models.Plugin.find()).filter(
|
|
78
|
-
(plugin) => !staticPlugins.includes(plugin.name)
|
|
79
|
-
);
|
|
80
|
-
for (const plugin of plugins) {
|
|
81
|
-
await loadPlugin(plugin);
|
|
82
|
-
state.registerPlugin(
|
|
83
|
-
plugin.name,
|
|
84
|
-
saltcorn[plugin.name],
|
|
85
|
-
plugin.configuration
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
return plugins;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* add <script> tags dynamically
|
|
93
|
-
*/
|
|
94
|
-
async function addScripts(version_tag) {
|
|
95
|
-
const scripts = [
|
|
96
|
-
{ src: `static_assets/${version_tag}/jquery-3.6.0.min.js` },
|
|
97
|
-
{ src: "js/bundle/common_chunks.bundle.js" },
|
|
98
|
-
{ src: "js/bundle/markup.bundle.js", name: "markup" },
|
|
99
|
-
{ src: "js/bundle/data.bundle.js", name: "data" },
|
|
100
|
-
{ src: "js/bundle/base_plugin.bundle.js", name: "base_plugin" },
|
|
101
|
-
{ src: "js/bundle/sbadmin2.bundle.js", name: "sbadmin2" },
|
|
102
|
-
];
|
|
103
|
-
for (const script of scripts) {
|
|
104
|
-
await addScript(script);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const prepareHeader = (header) => {
|
|
109
|
-
let result = Object.assign({}, header);
|
|
110
|
-
if (result.script?.startsWith("/")) {
|
|
111
|
-
result.script = result.script.substring(1);
|
|
112
|
-
}
|
|
113
|
-
return result;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
/*
|
|
117
|
-
A plugin exports headers either as array, as key values object, or
|
|
118
|
-
as a function with a configuration parameter that returns an Array.
|
|
119
|
-
*/
|
|
120
|
-
const collectPluginHeaders = (pluginRows) => {
|
|
121
|
-
const config = saltcorn.data.state.getState().mobileConfig;
|
|
122
|
-
config.pluginHeaders = [];
|
|
123
|
-
for (const row of pluginRows) {
|
|
124
|
-
const pluginHeaders = saltcorn[row.name].headers;
|
|
125
|
-
if (pluginHeaders) {
|
|
126
|
-
if (Array.isArray(pluginHeaders))
|
|
127
|
-
for (const header of pluginHeaders) {
|
|
128
|
-
config.pluginHeaders.push(prepareHeader(header));
|
|
129
|
-
}
|
|
130
|
-
else if (typeof pluginHeaders === "function") {
|
|
131
|
-
const headerResult = pluginHeaders(row.configuration || {});
|
|
132
|
-
if (Array.isArray(headerResult)) {
|
|
133
|
-
for (const header of headerResult)
|
|
134
|
-
config.pluginHeaders.push(prepareHeader(header));
|
|
135
|
-
}
|
|
136
|
-
} else
|
|
137
|
-
for (const [key, value] of Object.entries(pluginHeaders)) {
|
|
138
|
-
config.pluginHeaders.push(prepareHeader(value));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const initJwt = async () => {
|
|
145
|
-
if (!(await saltcorn.data.db.tableExists("jwt_table"))) {
|
|
146
|
-
await createJwtTable();
|
|
147
|
-
} else {
|
|
148
|
-
const jwt = await getJwt();
|
|
149
|
-
if (jwt) {
|
|
150
|
-
const state = saltcorn.data.state.getState();
|
|
151
|
-
state.mobileConfig.jwt = jwt;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const initI18Next = async () => {
|
|
157
|
-
const resources = {};
|
|
158
|
-
for (const key of Object.keys(
|
|
159
|
-
saltcorn.data.models.config.available_languages
|
|
160
|
-
)) {
|
|
161
|
-
const localeFile = await readJSON(
|
|
162
|
-
`${key}.json`,
|
|
163
|
-
`${cordova.file.applicationDirectory}www/locales`
|
|
164
|
-
);
|
|
165
|
-
resources[key] = {
|
|
166
|
-
translation: localeFile,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
await i18next.use(i18nextSprintfPostProcessor).init({
|
|
170
|
-
lng: "en",
|
|
171
|
-
resources,
|
|
172
|
-
});
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const readSiteLogo = async (state) => {
|
|
176
|
-
try {
|
|
177
|
-
const base64 = await readText(
|
|
178
|
-
"encoded_site_logo.txt",
|
|
179
|
-
`${cordova.file.applicationDirectory}www`
|
|
180
|
-
);
|
|
181
|
-
state.mobileConfig.encodedSiteLogo = base64;
|
|
182
|
-
} catch (error) {
|
|
183
|
-
console.log(
|
|
184
|
-
`Unable to read the site logo file: ${
|
|
185
|
-
error.message ? error.message : "Unknown error"
|
|
186
|
-
}`
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const showErrorPage = async (error) => {
|
|
192
|
-
const state = saltcorn.data.state.getState();
|
|
193
|
-
state.mobileConfig.inErrorState = true;
|
|
194
|
-
const page = await router.resolve({
|
|
195
|
-
pathname: "get/error_page",
|
|
196
|
-
fullWrap: true,
|
|
197
|
-
alerts: [
|
|
198
|
-
{
|
|
199
|
-
type: "error",
|
|
200
|
-
msg: error.message ? error.message : "An error occured.",
|
|
201
|
-
},
|
|
202
|
-
],
|
|
203
|
-
});
|
|
204
|
-
await replaceIframe(page.content);
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
// the app comes back from background
|
|
208
|
-
const onResume = async () => {
|
|
209
|
-
if (typeof saltcorn === "undefined") return;
|
|
210
|
-
const state = saltcorn.data.state.getState();
|
|
211
|
-
const mobileConfig = state.mobileConfig;
|
|
212
|
-
if (mobileConfig?.allowOfflineMode) {
|
|
213
|
-
mobileConfig.networkState = navigator.connection.type;
|
|
214
|
-
if (
|
|
215
|
-
mobileConfig.networkState === "none" &&
|
|
216
|
-
!mobileConfig.isOfflineMode &&
|
|
217
|
-
mobileConfig.jwt
|
|
218
|
-
) {
|
|
219
|
-
try {
|
|
220
|
-
await offlineHelper.startOfflineMode();
|
|
221
|
-
clearHistory();
|
|
222
|
-
if (mobileConfig.user_id) await gotoEntryView();
|
|
223
|
-
else {
|
|
224
|
-
const decodedJwt = jwt_decode(mobileConfig.jwt);
|
|
225
|
-
mobileConfig.user = decodedJwt.user;
|
|
226
|
-
// TODO remove these, use 'user' everywhere
|
|
227
|
-
mobileConfig.role_id = decodedJwt.user.role_id
|
|
228
|
-
? decodedJwt.user.role_id
|
|
229
|
-
: 100;
|
|
230
|
-
mobileConfig.user_id = decodedJwt.user.id;
|
|
231
|
-
mobileConfig.user_name = decodedJwt.user.email;
|
|
232
|
-
mobileConfig.language = decodedJwt.user.language;
|
|
233
|
-
|
|
234
|
-
mobileConfig.isPublicUser = false;
|
|
235
|
-
}
|
|
236
|
-
addRoute({ route: entryPoint, query: undefined });
|
|
237
|
-
const page = await router.resolve({
|
|
238
|
-
pathname: mobileConfig.entry_point,
|
|
239
|
-
fullWrap: true,
|
|
240
|
-
alerts: [],
|
|
241
|
-
});
|
|
242
|
-
} catch (error) {
|
|
243
|
-
await showErrorPage(error);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
const isPublicJwt = (jwt) => {
|
|
250
|
-
try {
|
|
251
|
-
if (!jwt) return false;
|
|
252
|
-
const decoded = jwt_decode(jwt);
|
|
253
|
-
return decoded.sub === "public";
|
|
254
|
-
} catch (error) {
|
|
255
|
-
console.log(
|
|
256
|
-
`Unable to inspect '${jwt}': ${
|
|
257
|
-
error.message ? error.message : "Unknown error"
|
|
258
|
-
}`
|
|
259
|
-
);
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
const isPublicEntryPoint = async (entryPoint) => {
|
|
265
|
-
try {
|
|
266
|
-
const tokens = entryPoint.split("/");
|
|
267
|
-
if (tokens.length < 3) throw new Error("The format is incorrect");
|
|
268
|
-
const name = tokens[tokens.length - 1];
|
|
269
|
-
const entryObj =
|
|
270
|
-
tokens[tokens.length - 2] === "view"
|
|
271
|
-
? saltcorn.data.models.View.findOne({ name: name })
|
|
272
|
-
: saltcorn.data.models.Page.findOne({ name: name });
|
|
273
|
-
if (!entryObj) throw new Error(`The object '${name}' does not exist`);
|
|
274
|
-
else return entryObj.min_role === 100;
|
|
275
|
-
} catch (error) {
|
|
276
|
-
console.log(
|
|
277
|
-
`Unable to inspect '${entryPoint}': ${
|
|
278
|
-
error.message ? error.message : "Unknown error"
|
|
279
|
-
}`
|
|
280
|
-
);
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const showLogin = async (alerts) => {
|
|
286
|
-
const page = await router.resolve({
|
|
287
|
-
pathname: "get/auth/login",
|
|
288
|
-
alerts,
|
|
289
|
-
});
|
|
290
|
-
await replaceIframe(page.content);
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
const takeLastLocation = () => {
|
|
294
|
-
let result = null;
|
|
295
|
-
const lastLocation = localStorage.getItem("lastLocation");
|
|
296
|
-
localStorage.removeItem("lastLocation");
|
|
297
|
-
if (lastLocation) {
|
|
298
|
-
try {
|
|
299
|
-
result = JSON.parse(lastLocation);
|
|
300
|
-
} catch (error) {
|
|
301
|
-
console.log(
|
|
302
|
-
`Unable to parse the last location: ${
|
|
303
|
-
error.message ? error.message : "Unknown error"
|
|
304
|
-
}`
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return result;
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
// device is ready
|
|
312
|
-
const init = async () => {
|
|
313
|
-
try {
|
|
314
|
-
const lastLocation = takeLastLocation();
|
|
315
|
-
document.addEventListener("resume", onResume, false);
|
|
316
|
-
const config = await readJSON(
|
|
317
|
-
"config",
|
|
318
|
-
`${cordova.file.applicationDirectory}www`
|
|
319
|
-
);
|
|
320
|
-
const { created_at } = await readJSON(
|
|
321
|
-
"tables_created_at.json",
|
|
322
|
-
`${cordova.file.applicationDirectory}${"www"}`
|
|
323
|
-
);
|
|
324
|
-
let tablesJSON = null;
|
|
325
|
-
await addScripts(config.version_tag);
|
|
326
|
-
saltcorn.data.db.connectObj.version_tag = config.version_tag;
|
|
327
|
-
await saltcorn.data.db.init();
|
|
328
|
-
const updateNeeded = await dbUpdateNeeded(created_at);
|
|
329
|
-
if (updateNeeded) {
|
|
330
|
-
tablesJSON = await readJSON(
|
|
331
|
-
"tables.json",
|
|
332
|
-
`${cordova.file.applicationDirectory}${"www"}`
|
|
333
|
-
);
|
|
334
|
-
// update '_sc_plugins' first because of loadPlugins()
|
|
335
|
-
await updateScPlugins(tablesJSON);
|
|
336
|
-
}
|
|
337
|
-
saltcorn.data.state.features.version_plugin_serve_path = false;
|
|
338
|
-
const state = saltcorn.data.state.getState();
|
|
339
|
-
state.mobileConfig = config;
|
|
340
|
-
state.registerPlugin("base", saltcorn.base_plugin);
|
|
341
|
-
state.registerPlugin("sbadmin2", saltcorn.sbadmin2);
|
|
342
|
-
collectPluginHeaders(await loadPlugins(state));
|
|
343
|
-
if (updateNeeded) {
|
|
344
|
-
if (!tablesJSON)
|
|
345
|
-
tablesJSON = await readJSON(
|
|
346
|
-
"tables.json",
|
|
347
|
-
`${cordova.file.applicationDirectory}${"www"}`
|
|
348
|
-
);
|
|
349
|
-
await updateDb(tablesJSON);
|
|
350
|
-
}
|
|
351
|
-
await createSyncInfoTables(config.synchedTables);
|
|
352
|
-
await initJwt();
|
|
353
|
-
await state.refresh_tables();
|
|
354
|
-
await state.refresh_views();
|
|
355
|
-
await state.refresh_pages();
|
|
356
|
-
await state.refresh_page_groups();
|
|
357
|
-
await state.refresh_triggers();
|
|
358
|
-
state.mobileConfig.localTableIds = await getTableIds(
|
|
359
|
-
config.localUserTables
|
|
360
|
-
);
|
|
361
|
-
await state.setConfig("base_url", config.server_path);
|
|
362
|
-
await initRoutes();
|
|
363
|
-
const entryPoint = config.entry_point;
|
|
364
|
-
await initI18Next();
|
|
365
|
-
await readSiteLogo(state);
|
|
366
|
-
state.mobileConfig.networkState = navigator.connection.type;
|
|
367
|
-
document.addEventListener(
|
|
368
|
-
"offline",
|
|
369
|
-
offlineHelper.offlineCallback,
|
|
370
|
-
false
|
|
371
|
-
);
|
|
372
|
-
document.addEventListener(
|
|
373
|
-
"online",
|
|
374
|
-
offlineHelper.onlineCallback,
|
|
375
|
-
false
|
|
376
|
-
);
|
|
377
|
-
const networkDisabled = state.mobileConfig.networkState === "none";
|
|
378
|
-
const jwt = state.mobileConfig.jwt;
|
|
379
|
-
const alerts = [];
|
|
380
|
-
if ((networkDisabled && jwt) || (await checkJWT(jwt))) {
|
|
381
|
-
const mobileConfig = state.mobileConfig;
|
|
382
|
-
const decodedJwt = jwt_decode(mobileConfig.jwt);
|
|
383
|
-
mobileConfig.user = decodedJwt.user;
|
|
384
|
-
// TODO remove these, use 'user' everywhere
|
|
385
|
-
mobileConfig.role_id = decodedJwt.user.role_id
|
|
386
|
-
? decodedJwt.user.role_id
|
|
387
|
-
: 100;
|
|
388
|
-
mobileConfig.user_id = decodedJwt.user.id;
|
|
389
|
-
mobileConfig.user_name = decodedJwt.user.email;
|
|
390
|
-
mobileConfig.language = decodedJwt.user.language;
|
|
391
|
-
|
|
392
|
-
mobileConfig.isPublicUser = false;
|
|
393
|
-
await i18next.changeLanguage(mobileConfig.language);
|
|
394
|
-
if (mobileConfig.allowOfflineMode) {
|
|
395
|
-
const { offlineUser } =
|
|
396
|
-
(await offlineHelper.getLastOfflineSession()) || {};
|
|
397
|
-
if (networkDisabled) {
|
|
398
|
-
if (offlineUser && offlineUser !== mobileConfig.user_name)
|
|
399
|
-
throw new Error(
|
|
400
|
-
`The offline mode is not available, '${offlineUser}' has not yet uploaded offline data.`
|
|
401
|
-
);
|
|
402
|
-
else
|
|
403
|
-
try {
|
|
404
|
-
await offlineHelper.startOfflineMode();
|
|
405
|
-
} catch (error) {
|
|
406
|
-
throw new Error(
|
|
407
|
-
`Neither an internet connection nor the offline mode are available: ${
|
|
408
|
-
error.message ? error.message : "Unknown error"
|
|
409
|
-
}`
|
|
410
|
-
);
|
|
411
|
-
}
|
|
412
|
-
} else if (offlineUser) {
|
|
413
|
-
if (offlineUser === mobileConfig.user_name) {
|
|
414
|
-
await offlineHelper.sync();
|
|
415
|
-
alerts.push({
|
|
416
|
-
type: "info",
|
|
417
|
-
msg: "Synchronized your offline data.",
|
|
418
|
-
});
|
|
419
|
-
} else
|
|
420
|
-
alerts.push({
|
|
421
|
-
type: "warning",
|
|
422
|
-
msg: `'${offlineUser}' has not yet uploaded offline data.`,
|
|
423
|
-
});
|
|
424
|
-
} else {
|
|
425
|
-
await offlineHelper.sync();
|
|
426
|
-
alerts.push({
|
|
427
|
-
type: "info",
|
|
428
|
-
msg: "Synchronized your offline data.",
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
let page = null;
|
|
433
|
-
if (!lastLocation) {
|
|
434
|
-
addRoute({ route: entryPoint, query: undefined });
|
|
435
|
-
page = await router.resolve({
|
|
436
|
-
pathname: entryPoint,
|
|
437
|
-
fullWrap: true,
|
|
438
|
-
alerts,
|
|
439
|
-
});
|
|
440
|
-
} else {
|
|
441
|
-
addRoute({
|
|
442
|
-
route: lastLocation.route,
|
|
443
|
-
query: lastLocation.query,
|
|
444
|
-
});
|
|
445
|
-
page = await router.resolve({
|
|
446
|
-
pathname: lastLocation.route,
|
|
447
|
-
query: lastLocation.query,
|
|
448
|
-
fullWrap: true,
|
|
449
|
-
alerts,
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
if (page.content) await replaceIframe(page.content, page.isFile);
|
|
453
|
-
} else if (isPublicJwt(jwt)) {
|
|
454
|
-
const config = state.mobileConfig;
|
|
455
|
-
config.user = { role_id: 100, user_name: "public", language: "en" };
|
|
456
|
-
// TODO remove these, use 'user' everywhere
|
|
457
|
-
config.role_id = 100;
|
|
458
|
-
config.user_name = "public";
|
|
459
|
-
config.language = "en";
|
|
460
|
-
|
|
461
|
-
config.isPublicUser = true;
|
|
462
|
-
i18next.changeLanguage(config.language);
|
|
463
|
-
addRoute({ route: entryPoint, query: undefined });
|
|
464
|
-
const page = await router.resolve({
|
|
465
|
-
pathname: entryPoint,
|
|
466
|
-
fullWrap: true,
|
|
467
|
-
alerts,
|
|
468
|
-
});
|
|
469
|
-
if (page.content) await replaceIframe(page.content, page.isFile);
|
|
470
|
-
} else if (
|
|
471
|
-
(await isPublicEntryPoint(entryPoint)) &&
|
|
472
|
-
state.mobileConfig.autoPublicLogin
|
|
473
|
-
) {
|
|
474
|
-
if (networkDisabled)
|
|
475
|
-
throw new Error(
|
|
476
|
-
"No internet connection or previous login is available. " +
|
|
477
|
-
"Please go online and reload, the public login is not yet supported."
|
|
478
|
-
);
|
|
479
|
-
await publicLogin(entryPoint);
|
|
480
|
-
} else await showLogin(alerts);
|
|
481
|
-
} catch (error) {
|
|
482
|
-
if (
|
|
483
|
-
typeof saltcorn === "undefined" ||
|
|
484
|
-
typeof router === "undefined"
|
|
485
|
-
) {
|
|
486
|
-
const msg = `An error occured: ${
|
|
487
|
-
error.message ? error.message : "Unknown error"
|
|
488
|
-
}`;
|
|
489
|
-
console.log(msg);
|
|
490
|
-
alert(msg);
|
|
491
|
-
} else {
|
|
492
|
-
if (error.httpCode === 401) await showLogin([]);
|
|
493
|
-
else await showErrorPage(error);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
};
|
|
497
|
-
|
|
498
|
-
document.addEventListener("deviceready", init);
|
|
499
|
-
|
|
8
|
+
<script src="data/tables.js"></script>
|
|
9
|
+
<script src="data/tables_created_at.js"></script>
|
|
10
|
+
<script src="data/config.js"></script>
|
|
11
|
+
<script src="data/translations.js"></script>
|
|
12
|
+
<script src="data/encoded_site_logo.js"></script>
|
|
13
|
+
<script type="module" src="./dist/bundle.js"></script>
|
|
14
|
+
<script src="js/iframe_view_utils.js"></script>
|
|
15
|
+
|
|
16
|
+
<script type="module">
|
|
17
|
+
import { mobileApp } from "./dist/bundle.js";
|
|
18
|
+
if (window.saltcorn) window.saltcorn.mobileApp = mobileApp;
|
|
19
|
+
else window.saltcorn = { mobileApp };
|
|
20
|
+
|
|
21
|
+
document.addEventListener("deviceready", () =>
|
|
22
|
+
saltcorn.mobileApp.init({
|
|
23
|
+
mobileConfig: _sc_mobile_config,
|
|
24
|
+
tablesSchema: _sc_tables,
|
|
25
|
+
schemaCreatedAt: _sc_tables_created_at,
|
|
26
|
+
translations: _sc_translations,
|
|
27
|
+
siteLogo: _sc_site_logo,
|
|
28
|
+
})
|
|
29
|
+
);
|
|
500
30
|
document.addEventListener("backbutton", async () => {
|
|
501
|
-
await goBack(1, true);
|
|
31
|
+
await saltcorn.mobileApp.navigation.goBack(1, true);
|
|
502
32
|
});
|
|
503
33
|
</script>
|
|
504
34
|
</head>
|