@saltcorn/mobile-app 1.1.0-beta.11 → 1.1.0-beta.13

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.
Files changed (39) hide show
  1. package/.babelrc +3 -0
  2. package/build_scripts/modify_android_manifest.js +47 -0
  3. package/build_scripts/modify_gradle_cfg.js +34 -0
  4. package/package.json +20 -11
  5. package/src/.eslintrc +21 -0
  6. package/src/helpers/api.js +41 -0
  7. package/src/helpers/auth.js +191 -0
  8. package/src/helpers/common.js +175 -0
  9. package/{www/js/utils/table_utils.js → src/helpers/db_schema.js} +18 -40
  10. package/src/helpers/file_system.js +102 -0
  11. package/{www/js/utils/global_utils.js → src/helpers/navigation.js} +169 -335
  12. package/src/helpers/offline_mode.js +645 -0
  13. package/src/index.js +20 -0
  14. package/src/init.js +424 -0
  15. package/src/routing/index.js +98 -0
  16. package/{www/js → src/routing}/mocks/request.js +5 -5
  17. package/{www/js → src/routing}/mocks/response.js +1 -1
  18. package/{www/js → src/routing}/routes/api.js +10 -15
  19. package/{www/js → src/routing}/routes/auth.js +12 -6
  20. package/{www/js → src/routing}/routes/delete.js +9 -6
  21. package/{www/js → src/routing}/routes/edit.js +9 -6
  22. package/src/routing/routes/error.js +6 -0
  23. package/{www/js → src/routing}/routes/fields.js +7 -2
  24. package/{www/js → src/routing}/routes/page.js +14 -9
  25. package/{www/js → src/routing}/routes/sync.js +9 -5
  26. package/{www/js → src/routing}/routes/view.js +16 -11
  27. package/{www/js/routes/common.js → src/routing/utils.js} +15 -13
  28. package/webpack.config.js +31 -0
  29. package/www/data/encoded_site_logo.js +1 -0
  30. package/www/index.html +23 -491
  31. package/www/js/{utils/iframe_view_utils.js → iframe_view_utils.js} +137 -269
  32. package/config.xml +0 -27
  33. package/res/icon/android/icon.png +0 -0
  34. package/res/screen/android/splash-icon.png +0 -0
  35. package/res/screen/ios/Default@2x~universal~anyany.png +0 -0
  36. package/www/js/routes/error.js +0 -5
  37. package/www/js/routes/init.js +0 -76
  38. package/www/js/utils/file_helpers.js +0 -108
  39. package/www/js/utils/offline_mode_helper.js +0 -625
@@ -30,8 +30,12 @@ async function execLink(url, linkSrc) {
30
30
  showLoadSpinner();
31
31
  if (url.startsWith("javascript:")) eval(url.substring(11));
32
32
  else {
33
- const { path, query } = parent.splitPathQuery(url);
34
- await parent.handleRoute(`get${path}`, query);
33
+ const { path, query } =
34
+ parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
35
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
36
+ `get${path}`,
37
+ query
38
+ );
35
39
  }
36
40
  } finally {
37
41
  removeLoadSpinner();
@@ -39,8 +43,9 @@ async function execLink(url, linkSrc) {
39
43
  }
40
44
 
41
45
  async function runUrl(url, method = "get") {
42
- const { path, query } = parent.splitPathQuery(url);
43
- const page = await parent.router.resolve({
46
+ const { path, query } =
47
+ parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
48
+ const page = await parent.saltcorn.mobileApp.navigation.router.resolve({
44
49
  pathname: `${method}${path}`,
45
50
  query: query,
46
51
  });
@@ -84,17 +89,23 @@ async function formSubmit(e, urlSuffix, viewname, noSubmitCb, matchingState) {
84
89
  const tokens = entry[1].split("/");
85
90
  const fileName = tokens[tokens.length - 1];
86
91
  const directory = tokens.splice(0, tokens.length - 1).join("/");
87
- // read and add file to submit
88
- const binary = await parent.readBinary(fileName, directory);
89
- files[entry[0]] = new File([binary], fileName);
92
+ const { buffer, file } =
93
+ await parent.saltcorn.mobileApp.fileSystem.readBinaryCordova(
94
+ fileName,
95
+ directory
96
+ );
97
+ files[entry[0]] = {
98
+ blob: new Blob([buffer], { type: file.type }),
99
+ fileObj: file,
100
+ };
90
101
  } else if (!matchingState) urlParams.append(entry[0], entry[1]);
91
102
  else data[entry[0]] = entry[1];
92
103
  }
93
104
  }
94
105
  const queryStr = !matchingState
95
106
  ? urlParams.toString()
96
- : parent.currentQuery() || "";
97
- await parent.handleRoute(
107
+ : parent.saltcorn.mobileApp.navigation.currentQuery() || "";
108
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
98
109
  `post${urlSuffix}${viewname}`,
99
110
  queryStr,
100
111
  files,
@@ -116,13 +127,13 @@ async function inline_local_submit(e, opts1) {
116
127
  urlParams.append(entry[0], entry[1]);
117
128
  }
118
129
  const url = form.attr("action");
119
- await parent.router.resolve({
130
+ await parent.saltcorn.mobileApp.navigation.router.resolve({
120
131
  pathname: `post${url}`,
121
132
  query: urlParams.toString(),
122
133
  });
123
134
  inline_submit_success(e, form, opts);
124
135
  } catch (error) {
125
- parent.showAlerts([
136
+ parent.saltcorn.mobileApp.common.showAlerts([
126
137
  {
127
138
  type: "error",
128
139
  msg: error.message ? error.message : "An error occured.",
@@ -145,7 +156,7 @@ async function saveAndContinue(e, action, k) {
145
156
  const form = $(e).closest("form");
146
157
  submitWithEmptyAction(form[0]);
147
158
  const queryStr = new URLSearchParams(new FormData(form[0])).toString();
148
- const res = await parent.router.resolve({
159
+ const res = await parent.saltcorn.mobileApp.navigation.router.resolve({
149
160
  pathname: `post${action}`,
150
161
  query: queryStr,
151
162
  xhr: true,
@@ -162,95 +173,16 @@ async function saveAndContinue(e, action, k) {
162
173
  }
163
174
  }
164
175
 
165
- async function loginRequest({ email, password, isSignup, isPublic }) {
166
- const opts = isPublic
167
- ? {
168
- method: "GET",
169
- path: "/auth/login-with/jwt",
170
- }
171
- : isSignup
172
- ? {
173
- method: "POST",
174
- path: "/auth/signup",
175
- body: {
176
- email,
177
- password,
178
- },
179
- }
180
- : {
181
- method: "GET",
182
- path: "/auth/login-with/jwt",
183
- params: {
184
- email,
185
- password,
186
- },
187
- };
188
- const response = await parent.apiCall(opts);
189
- return response.data;
190
- }
191
-
192
176
  async function login(e, entryPoint, isSignup) {
193
177
  try {
194
178
  showLoadSpinner();
195
179
  const formData = new FormData(e);
196
- const loginResult = await loginRequest({
180
+ await parent.saltcorn.mobileApp.auth.login({
197
181
  email: formData.get("email"),
198
182
  password: formData.get("password"),
199
183
  isSignup,
184
+ entryPoint,
200
185
  });
201
- if (typeof loginResult === "string") {
202
- // use it as a token
203
- const decodedJwt = parent.jwt_decode(loginResult);
204
- const state = parent.saltcorn.data.state.getState();
205
- const config = state.mobileConfig;
206
- config.role_id = decodedJwt.user.role_id ? decodedJwt.user.role_id : 100;
207
- config.user_name = decodedJwt.user.email;
208
- config.user_id = decodedJwt.user.id;
209
- config.language = decodedJwt.user.language;
210
- config.user = decodedJwt.user;
211
- config.isPublicUser = false;
212
- config.isOfflineMode = false;
213
- await parent.insertUser(config.user);
214
- await parent.setJwt(loginResult);
215
- config.jwt = loginResult;
216
- await parent.i18next.changeLanguage(config.language);
217
- const alerts = [];
218
- if (config.allowOfflineMode) {
219
- const { offlineUser, hasOfflineData } =
220
- (await parent.offlineHelper.getLastOfflineSession()) || {};
221
- if (!offlineUser || offlineUser === config.user_name) {
222
- await parent.offlineHelper.sync();
223
- } else {
224
- if (hasOfflineData)
225
- alerts.push({
226
- type: "warning",
227
- msg: `'${offlineUser}' has not yet uploaded offline data.`,
228
- });
229
- else {
230
- await deleteOfflineData(true);
231
- await parent.offlineHelper.sync();
232
- }
233
- }
234
- }
235
- alerts.push({
236
- type: "success",
237
- msg: parent.i18next.t("Welcome, %s!", {
238
- postProcess: "sprintf",
239
- sprintf: [config.user_name],
240
- }),
241
- });
242
- parent.addRoute({ route: entryPoint, query: undefined });
243
- const page = await parent.router.resolve({
244
- pathname: entryPoint,
245
- fullWrap: true,
246
- alerts,
247
- });
248
- if (page.content) await parent.replaceIframe(page.content, page.isFile);
249
- } else if (loginResult?.alerts) {
250
- parent.showAlerts(loginResult?.alerts);
251
- } else {
252
- throw new Error("The login failed.");
253
- }
254
186
  } finally {
255
187
  removeLoadSpinner();
256
188
  }
@@ -259,77 +191,16 @@ async function login(e, entryPoint, isSignup) {
259
191
  async function publicLogin(entryPoint) {
260
192
  try {
261
193
  showLoadSpinner();
262
- const loginResult = await loginRequest({ isPublic: true });
263
- if (typeof loginResult === "string") {
264
- const config = parent.saltcorn.data.state.getState().mobileConfig;
265
- config.user = {
266
- role_id: 100,
267
- user_name: "public",
268
- language: "en",
269
- };
270
- // TODO remove these, use 'user' everywhere
271
- config.role_id = 100;
272
- config.user_name = "public";
273
- config.language = "en";
274
-
275
- config.isPublicUser = true;
276
- await parent.setJwt(loginResult);
277
- config.jwt = loginResult;
278
- parent.i18next.changeLanguage(config.language);
279
- parent.addRoute({ route: entryPoint, query: undefined });
280
- const page = await parent.router.resolve({
281
- pathname: entryPoint,
282
- fullWrap: true,
283
- alerts: [
284
- {
285
- type: "success",
286
- msg: parent.i18next.t("Welcome to %s!", {
287
- postProcess: "sprintf",
288
- sprintf: [
289
- parent.saltcorn.data.state.getState().getConfig("site_name") ||
290
- "Saltcorn",
291
- ],
292
- }),
293
- },
294
- ],
295
- });
296
- if (page.content) await parent.replaceIframe(page.content, page.isFile);
297
- } else if (loginResult?.alerts) {
298
- parent.showAlerts(loginResult?.alerts);
299
- } else {
300
- throw new Error("The login failed.");
301
- }
302
- } catch (error) {
303
- console.log(error);
304
- parent.showAlerts([
305
- {
306
- type: "error",
307
- msg: error.message ? error.message : "An error occured.",
308
- },
309
- ]);
310
- throw error;
194
+ await parent.saltcorn.mobileApp.auth.publicLogin(entryPoint);
311
195
  } finally {
312
196
  removeLoadSpinner();
313
197
  }
314
198
  }
315
199
 
316
200
  async function logout() {
317
- const config = parent.saltcorn.data.state.getState().mobileConfig;
318
201
  try {
319
202
  showLoadSpinner();
320
- const page = await parent.router.resolve({
321
- pathname: "get/auth/logout",
322
- entryView: config.entry_point,
323
- versionTag: config.version_tag,
324
- });
325
- await parent.replaceIframe(page.content);
326
- } catch (error) {
327
- parent.showAlerts([
328
- {
329
- type: "error",
330
- msg: error.message ? error.message : "An error occured.",
331
- },
332
- ]);
203
+ await parent.saltcorn.mobileApp.auth.logout();
333
204
  } finally {
334
205
  removeLoadSpinner();
335
206
  }
@@ -339,7 +210,7 @@ async function signupFormSubmit(e, entryView) {
339
210
  try {
340
211
  await login(e, entryView, true);
341
212
  } catch (error) {
342
- parent.errorAlert(error);
213
+ parent.saltcorn.mobileApp.common.errorAlert(error);
343
214
  }
344
215
  }
345
216
 
@@ -353,7 +224,7 @@ async function loginFormSubmit(e, entryView) {
353
224
  }
354
225
  await login(e, safeEntryView, false);
355
226
  } catch (error) {
356
- parent.errorAlert(error);
227
+ parent.saltcorn.mobileApp.common.errorAlert(error);
357
228
  }
358
229
  }
359
230
 
@@ -363,8 +234,9 @@ async function local_post_btn(e) {
363
234
  const form = $(e).closest("form");
364
235
  const url = form.attr("action");
365
236
  const method = form.attr("method");
366
- const { path, query } = parent.splitPathQuery(url);
367
- await parent.handleRoute(
237
+ const { path, query } =
238
+ parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
239
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
368
240
  `${method}${path}`,
369
241
  combineFormAndQuery(form, query)
370
242
  );
@@ -382,7 +254,7 @@ async function stateFormSubmit(e, path) {
382
254
  try {
383
255
  showLoadSpinner();
384
256
  const formQuery = new URLSearchParams(new FormData(e)).toString();
385
- await parent.handleRoute(path, formQuery);
257
+ await parent.saltcorn.mobileApp.navigation.handleRoute(path, formQuery);
386
258
  } finally {
387
259
  removeLoadSpinner();
388
260
  }
@@ -432,7 +304,7 @@ async function set_state_fields(kvs, href) {
432
304
  try {
433
305
  showLoadSpinner();
434
306
  let queryParams = [];
435
- let currentQuery = parent.currentQuery();
307
+ let currentQuery = parent.saltcorn.mobileApp.navigation.currentQuery();
436
308
  if (Object.keys(kvs).some((k) => !is_paging_param(k))) {
437
309
  currentQuery = invalidate_pagings(currentQuery);
438
310
  }
@@ -446,7 +318,10 @@ async function set_state_fields(kvs, href) {
446
318
  for (const [k, v] of new URLSearchParams(currentQuery).entries()) {
447
319
  queryParams.push(`${k}=${v}`);
448
320
  }
449
- await parent.handleRoute(href, queryParams.join("&"));
321
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
322
+ href,
323
+ queryParams.join("&")
324
+ );
450
325
  } finally {
451
326
  removeLoadSpinner();
452
327
  }
@@ -455,8 +330,15 @@ async function set_state_fields(kvs, href) {
455
330
  async function set_state_field(key, value) {
456
331
  try {
457
332
  showLoadSpinner();
458
- const query = updateQueryStringParameter(parent.currentQuery(), key, value);
459
- await parent.handleRoute(parent.currentLocation(), query);
333
+ const query = updateQueryStringParameter(
334
+ parent.saltcorn.mobileApp.navigation.currentQuery(),
335
+ key,
336
+ value
337
+ );
338
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
339
+ parent.saltcorn.mobileApp.navigation.currentLocation(),
340
+ query
341
+ );
460
342
  } finally {
461
343
  removeLoadSpinner();
462
344
  }
@@ -465,9 +347,12 @@ async function set_state_field(key, value) {
465
347
  async function unset_state_field(key) {
466
348
  try {
467
349
  showLoadSpinner();
468
- const href = parent.currentLocation();
469
- const query = removeQueryStringParameter(parent.currentLocation(), key);
470
- await parent.handleRoute(href, query);
350
+ const href = parent.saltcorn.mobileApp.navigation.currentLocation();
351
+ const query = removeQueryStringParameter(
352
+ parent.saltcorn.mobileApp.navigation.currentLocation(),
353
+ key
354
+ );
355
+ await parent.saltcorn.mobileApp.navigation.handleRoute(href, query);
471
356
  } finally {
472
357
  removeLoadSpinner();
473
358
  }
@@ -479,7 +364,7 @@ async function sortby(k, desc, viewIdentifier) {
479
364
  [`_${viewIdentifier}_sortby`]: k,
480
365
  [`_${viewIdentifier}_sortdesc`]: desc ? "on" : { unset: true },
481
366
  },
482
- parent.currentLocation()
367
+ parent.saltcorn.mobileApp.navigation.currentLocation()
483
368
  );
484
369
  }
485
370
 
@@ -490,7 +375,7 @@ async function gopage(n, pagesize, viewIdentifier, extra) {
490
375
  [`_${viewIdentifier}_page`]: n,
491
376
  [`_${viewIdentifier}_pagesize`]: pagesize,
492
377
  },
493
- parent.currentLocation()
378
+ parent.saltcorn.mobileApp.navigation.currentLocation()
494
379
  );
495
380
  }
496
381
 
@@ -529,18 +414,19 @@ async function mobile_modal(url, opts = {}) {
529
414
  if (opts.submitReload === false) $("#scmodal").addClass("no-submit-reload");
530
415
  else $("#scmodal").removeClass("no-submit-reload");
531
416
  try {
532
- const { path, query } = parent.splitPathQuery(url);
417
+ const { path, query } =
418
+ parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
533
419
  const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
534
420
  if (
535
421
  mobileConfig.networkState === "none" &&
536
422
  mobileConfig.allowOfflineMode &&
537
423
  !mobileConfig.isOfflineMode
538
424
  ) {
539
- await parent.offlineHelper.startOfflineMode();
540
- parent.clearHistory();
541
- await parent.gotoEntryView();
425
+ await parent.saltcorn.mobileApp.offlineMode.startOfflineMode();
426
+ parent.saltcorn.mobileApp.navigation.clearHistory();
427
+ await parent.saltcorn.mobileApp.navigation.gotoEntryView();
542
428
  } else {
543
- const page = await parent.router.resolve({
429
+ const page = await parent.saltcorn.mobileApp.navigation.router.resolve({
544
430
  pathname: `get${path}`,
545
431
  query: query,
546
432
  alerts: [],
@@ -553,7 +439,7 @@ async function mobile_modal(url, opts = {}) {
553
439
  // onOpen onClose initialize_page?
554
440
  }
555
441
  } catch (error) {
556
- parent.showAlerts([
442
+ parent.saltcorn.mobileApp.common.showAlerts([
557
443
  {
558
444
  type: "error",
559
445
  msg: error.message ? error.message : "An error occured.",
@@ -569,14 +455,15 @@ function closeModal() {
569
455
  async function local_post(url, args) {
570
456
  try {
571
457
  showLoadSpinner();
572
- const result = await parent.router.resolve({
458
+ const result = await parent.saltcorn.mobileApp.navigation.router.resolve({
573
459
  pathname: `post${url}`,
574
460
  data: args,
575
461
  });
576
- if (result.redirect) await parent.handleRoute(result.redirect);
462
+ if (result.redirect)
463
+ await parent.saltcorn.mobileApp.navigation.handleRoute(result.redirect);
577
464
  else await common_done(result, "", false);
578
465
  } catch (error) {
579
- parent.errorAlert(error);
466
+ parent.saltcorn.mobileApp.common.errorAlert(error);
580
467
  } finally {
581
468
  removeLoadSpinner();
582
469
  }
@@ -585,17 +472,18 @@ async function local_post(url, args) {
585
472
  async function local_post_json(url, data, cb) {
586
473
  try {
587
474
  showLoadSpinner();
588
- const result = await parent.router.resolve({
475
+ const result = await parent.saltcorn.mobileApp.navigation.router.resolve({
589
476
  pathname: `post${url}`,
590
477
  data: data,
591
- query: parent.currentQuery(),
478
+ query: parent.saltcorn.mobileApp.navigation.currentQuery(),
592
479
  });
593
480
  if (result.server_eval) await evalServerCode(url);
594
- if (result.redirect) await parent.handleRoute(result.redirect);
481
+ if (result.redirect)
482
+ await parent.saltcorn.mobileApp.navigation.handleRoute(result.redirect);
595
483
  else await common_done(result, "", false);
596
484
  if (cb?.success) cb.success(result);
597
485
  } catch (error) {
598
- parent.errorAlert(error);
486
+ parent.saltcorn.mobileApp.common.errorAlert(error);
599
487
  if (cb?.error) cb.error(error);
600
488
  } finally {
601
489
  removeLoadSpinner();
@@ -603,7 +491,7 @@ async function local_post_json(url, data, cb) {
603
491
  }
604
492
 
605
493
  async function evalServerCode(url) {
606
- await parent.apiCall({
494
+ await parent.saltcorn.mobileApp.api.apiCall({
607
495
  method: "POST",
608
496
  path: url,
609
497
  });
@@ -626,7 +514,7 @@ async function make_unique_field(
626
514
  )}=${encodeURIComponent(value)}&fields=${encodeURIComponent(field_name)}`;
627
515
  try {
628
516
  // TODO ch support local tables
629
- const response = await parent.apiCall({
517
+ const response = await parent.saltcorn.mobileApp.api.apiCall({
630
518
  method: "GET",
631
519
  path,
632
520
  });
@@ -643,7 +531,7 @@ async function make_unique_field(
643
531
  );
644
532
  }
645
533
  } catch (error) {
646
- parent.showAlerts([
534
+ parent.saltcorn.mobileApp.common.showAlerts([
647
535
  {
648
536
  type: "error",
649
537
  msg: "unable to 'make_unique_field'",
@@ -688,11 +576,14 @@ async function select_id(id) {
688
576
  try {
689
577
  showLoadSpinner();
690
578
  const newQuery = updateQueryStringParameter(
691
- parent.currentQuery(),
579
+ parent.saltcorn.mobileApp.navigation.currentQuery(),
692
580
  "id",
693
581
  id
694
582
  );
695
- await parent.handleRoute(parent.currentLocation(), newQuery);
583
+ await parent.handleRoute(
584
+ parent.saltcorn.mobileApp.navigation.currentLocation(),
585
+ newQuery
586
+ );
696
587
  } finally {
697
588
  removeLoadSpinner();
698
589
  }
@@ -703,9 +594,16 @@ async function check_state_field(that) {
703
594
  showLoadSpinner();
704
595
  const name = that.name;
705
596
  const newQuery = that.checked
706
- ? updateQueryStringParameter(parent.currentQuery(), name, that.value)
597
+ ? updateQueryStringParameter(
598
+ parent.saltcorn.mobileApp.navigation.currentQuery(),
599
+ name,
600
+ that.value
601
+ )
707
602
  : removeQueryStringParameter(name);
708
- await parent.handleRoute(parent.currentLocation(), newQuery);
603
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
604
+ parent.saltcorn.mobileApp.navigation.currentLocation(),
605
+ newQuery
606
+ );
709
607
  } finally {
710
608
  removeLoadSpinner();
711
609
  }
@@ -714,7 +612,10 @@ async function check_state_field(that) {
714
612
  async function clear_state() {
715
613
  try {
716
614
  showLoadSpinner();
717
- await parent.handleRoute(parent.currentLocation(), undefined);
615
+ await parent.saltcorn.mobileApp.navigation.handleRoute(
616
+ parent.saltcorn.mobileApp.navigation.currentLocation(),
617
+ undefined
618
+ );
718
619
  } finally {
719
620
  removeLoadSpinner();
720
621
  }
@@ -728,7 +629,7 @@ async function view_post(viewnameOrElem, route, data, onDone, sendState) {
728
629
  .closest("[data-sc-embed-viewname]")
729
630
  .attr("data-sc-embed-viewname");
730
631
  const buildQuery = () => {
731
- const query = parent.currentQuery();
632
+ const query = parent.saltcorn.mobileApp.navigation.currentQuery();
732
633
  return query ? `?${query}` : "";
733
634
  };
734
635
  const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
@@ -741,13 +642,13 @@ async function view_post(viewnameOrElem, route, data, onDone, sendState) {
741
642
  mobileConfig.isOfflineMode ||
742
643
  (view?.table_id && mobileConfig.localTableIds.indexOf(view.table_id) >= 0)
743
644
  ) {
744
- respData = await parent.router.resolve({
645
+ respData = await parent.saltcorn.mobileApp.navigation.router.resolve({
745
646
  pathname: `post/view/${viewname}/${route}`,
746
647
  data,
747
648
  query,
748
649
  });
749
650
  } else {
750
- const response = await parent.apiCall({
651
+ const response = await parent.saltcorn.mobileApp.api.apiCall({
751
652
  method: "POST",
752
653
  path: "/view/" + viewname + "/" + route + query,
753
654
  body: data,
@@ -760,7 +661,7 @@ async function view_post(viewnameOrElem, route, data, onDone, sendState) {
760
661
  if (onDone) await onDone(respData);
761
662
  await common_done(respData, viewname, false);
762
663
  } catch (error) {
763
- parent.errorAlert(error);
664
+ parent.saltcorn.mobileApp.common.errorAlert(error);
764
665
  } finally {
765
666
  removeLoadSpinner();
766
667
  }
@@ -783,37 +684,41 @@ async function switchNetworkMode() {
783
684
  const state = parent.saltcorn.data.state.getState();
784
685
  const { isOfflineMode, networkState } = state.mobileConfig;
785
686
  if (!isOfflineMode) {
786
- await parent.offlineHelper.startOfflineMode();
787
- parent.clearHistory();
788
- parent.addRoute({ route: "/" });
789
- parent.addRoute({ route: "get/sync/sync_settings" });
790
- parent.showAlerts(
687
+ await parent.saltcorn.mobileApp.offlineMode.startOfflineMode();
688
+ parent.saltcorn.mobileApp.navigation.clearHistory();
689
+ parent.saltcorn.mobileApp.navigation.addRoute({ route: "/" });
690
+ parent.saltcorn.mobileApp.navigation.addRoute({
691
+ route: "get/sync/sync_settings",
692
+ });
693
+ parent.saltcorn.mobileApp.common.showAlerts(
791
694
  [
792
695
  {
793
696
  type: "info",
794
- msg: parent.offlineHelper.getOfflineMsg(),
697
+ msg: parent.saltcorn.mobileApp.offlineMode.getOfflineMsg(),
795
698
  },
796
699
  ],
797
700
  false
798
701
  );
799
- parent.clearAlerts();
702
+ parent.saltcorn.mobileApp.common.clearAlerts();
800
703
  } else {
801
704
  if (networkState === "none")
802
705
  throw new Error("No internet connection is available.");
803
- await parent.offlineHelper.endOfflineMode();
804
- parent.clearHistory();
805
- parent.addRoute({ route: "/" });
806
- parent.addRoute({ route: "get/sync/sync_settings" });
807
- parent.showAlerts([
706
+ await parent.saltcorn.mobileApp.offlineMode.endOfflineMode();
707
+ parent.saltcorn.mobileApp.navigation.clearHistory();
708
+ parent.saltcorn.mobileApp.navigation.addRoute({ route: "/" });
709
+ parent.saltcorn.mobileApp.navigation.addRoute({
710
+ route: "get/sync/sync_settings",
711
+ });
712
+ parent.saltcorn.mobileApp.common.showAlerts([
808
713
  {
809
714
  type: "info",
810
715
  msg: "You are online again.",
811
716
  },
812
717
  ]);
813
- parent.clearTopAlerts();
718
+ parent.saltcorn.mobileApp.common.clearTopAlerts();
814
719
  }
815
720
  } catch (error) {
816
- parent.showAlerts([
721
+ parent.saltcorn.mobileApp.common.showAlerts([
817
722
  {
818
723
  type: "error",
819
724
  msg: `Unable to change the network mode: ${
@@ -833,7 +738,7 @@ async function callSync() {
833
738
  try {
834
739
  const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
835
740
  if (mobileConfig.networkState === "none") {
836
- parent.showAlerts([
741
+ parent.saltcorn.mobileApp.common.showAlerts([
837
742
  {
838
743
  type: "error",
839
744
  msg: "You don't have an internet connection.",
@@ -842,10 +747,10 @@ async function callSync() {
842
747
  } else {
843
748
  const wasOffline = mobileConfig.isOfflineMode;
844
749
  showLoadSpinner();
845
- await parent.offlineHelper.sync();
846
- parent.clearAlerts();
750
+ await parent.saltcorn.mobileApp.offlineMode.sync();
751
+ parent.saltcorn.mobileApp.common.clearAlerts();
847
752
  if (!wasOffline) {
848
- parent.showAlerts([
753
+ parent.saltcorn.mobileApp.common.showAlerts([
849
754
  {
850
755
  type: "info",
851
756
  msg: "Synchronized your offline data.",
@@ -853,38 +758,41 @@ async function callSync() {
853
758
  ]);
854
759
  } else {
855
760
  setNetworSwitcherOn();
856
- parent.clearHistory();
857
- parent.addRoute({ route: "/" });
858
- parent.addRoute({ route: "get/sync/sync_settings" });
859
- parent.showAlerts([
761
+ parent.saltcorn.mobileApp.navigation.clearHistory();
762
+ parent.saltcorn.mobileApp.navigation.addRoute({ route: "/" });
763
+ parent.saltcorn.mobileApp.navigation.addRoute({
764
+ route: "get/sync/sync_settings",
765
+ });
766
+ parent.saltcorn.mobileApp.common.showAlerts([
860
767
  {
861
768
  type: "info",
862
769
  msg: "Synchronized your offline data, you are online again.",
863
770
  },
864
771
  ]);
865
- parent.clearTopAlerts();
772
+ parent.saltcorn.mobileApp.common.clearTopAlerts();
866
773
  }
867
774
  }
868
775
  } catch (error) {
869
776
  console.log(error);
870
- parent.errorAlert(error);
777
+ parent.saltcorn.mobileApp.common.errorAlert(error);
871
778
  } finally {
872
779
  removeLoadSpinner();
873
780
  }
874
781
  }
875
782
 
876
783
  async function deleteOfflineDataClicked() {
877
- const lastOfflineSession = await parent.offlineHelper.getLastOfflineSession();
878
- const { user_name } = parent.saltcorn.data.state.getState().mobileConfig;
784
+ const lastOfflineSession =
785
+ await parent.saltcorn.mobileApp.offlineMode.getLastOfflineSession();
786
+ const { user } = parent.saltcorn.data.state.getState().mobileConfig;
879
787
  if (!lastOfflineSession?.offlineUser) {
880
- parent.showAlerts([
788
+ parent.saltcorn.mobileApp.common.showAlerts([
881
789
  {
882
790
  type: "error",
883
791
  msg: "You don't have any offline data.",
884
792
  },
885
793
  ]);
886
- } else if (lastOfflineSession.offlineUser !== user_name) {
887
- parent.showAlerts([
794
+ } else if (lastOfflineSession.offlineUser !== user.email) {
795
+ parent.saltcorn.mobileApp.common.showAlerts([
888
796
  {
889
797
  type: "error",
890
798
  msg: `The offline data is owned by '${lastOfflineSession.offlineUser}'.`,
@@ -895,30 +803,8 @@ async function deleteOfflineDataClicked() {
895
803
  }
896
804
  }
897
805
 
898
- async function deleteOfflineData(noFeedback) {
899
- const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
900
- try {
901
- mobileConfig.inLoadState = true;
902
- if (!noFeedback) showLoadSpinner();
903
- await parent.offlineHelper.clearLocalData(false);
904
- await parent.offlineHelper.setHasOfflineData(false);
905
- if (!noFeedback)
906
- parent.showAlerts([
907
- {
908
- type: "info",
909
- msg: "Deleted your offline data.",
910
- },
911
- ]);
912
- } catch (error) {
913
- parent.errorAlert(error);
914
- } finally {
915
- mobileConfig.inLoadState = false;
916
- if (!noFeedback) removeLoadSpinner();
917
- }
918
- }
919
-
920
806
  function showLoadSpinner() {
921
- if (!parent.isHtmlFile()) {
807
+ if (!parent.saltcorn.mobileApp.navigation.isHtmlFile()) {
922
808
  const spinner = $("#scspinner");
923
809
  if (spinner.length === 0) {
924
810
  $("body").append(`
@@ -961,7 +847,7 @@ function showLoadSpinner() {
961
847
  }
962
848
 
963
849
  function removeLoadSpinner() {
964
- if (!parent.isHtmlFile()) {
850
+ if (!parent.saltcorn.mobileApp.navigation.isHtmlFile()) {
965
851
  const spinner = $("#scspinner");
966
852
  if (spinner.length > 0) {
967
853
  const count = parseInt(spinner.attr("spinner-count")) - 1;
@@ -977,29 +863,11 @@ function removeLoadSpinner() {
977
863
  * @param {*} fieldName
978
864
  */
979
865
  async function getPicture(fieldName) {
980
- const cameraOptions = {
981
- quality: 50,
982
- encodingType: parent.Camera.EncodingType.JPEG,
983
- destinationType: parent.Camera.DestinationType.FILE_URI,
984
- };
985
- const getPictureWithPromise = () => {
986
- return new Promise((resolve, reject) => {
987
- parent.navigator.camera.getPicture(
988
- (imageDate) => {
989
- return resolve(imageDate);
990
- },
991
- (message) => {
992
- return reject(message);
993
- },
994
- cameraOptions
995
- );
996
- });
997
- };
998
866
  try {
999
867
  const form = $(`#cptbtn${fieldName}`).closest("form");
1000
868
  const onsubmit = form.attr("onsubmit");
1001
869
  form.attr("onsubmit", "javascript:void(0)");
1002
- const fileURI = await getPictureWithPromise();
870
+ const fileURI = await parent.saltcorn.mobileApp.common.takePhoto("uri");
1003
871
  form.attr("onsubmit", onsubmit);
1004
872
  const inputId = `input${fieldName}`;
1005
873
  form.find(`#${inputId}`).remove();
@@ -1009,7 +877,7 @@ async function getPicture(fieldName) {
1009
877
  const tokens = fileURI.split("/");
1010
878
  $(`#cpt-file-name-${fieldName}`).text(tokens[tokens.length - 1]);
1011
879
  } catch (error) {
1012
- parent.errorAlert(error);
880
+ parent.saltcorn.mobileApp.common.errorAlert(error);
1013
881
  }
1014
882
  }
1015
883
 
@@ -1024,7 +892,7 @@ async function updateMatchingRows(e, viewname) {
1024
892
  true
1025
893
  );
1026
894
  } catch (error) {
1027
- parent.errorAlert(error);
895
+ parent.saltcorn.mobileApp.common.errorAlert(error);
1028
896
  }
1029
897
  }
1030
898