@sumaris-net/ngx-components 18.24.24 → 18.25.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.
- package/doc/changelog.md +7 -0
- package/esm2022/src/app/core/services/account.service.mjs +33 -10
- package/esm2022/src/app/core/services/platform.service.mjs +3 -3
- package/esm2022/src/app/core/services/startup.constants.mjs +10 -0
- package/esm2022/src/app/core/services/startup.model.mjs +2 -0
- package/esm2022/src/app/core/services/startup.service.mjs +148 -0
- package/esm2022/src/app/shared/shared.module.mjs +2 -2
- package/esm2022/src/app/shared/storage/storage.service.mjs +2 -3
- package/esm2022/src/environments/environment.class.mjs +4 -1
- package/esm2022/src/environments/environment.mjs +2 -1
- package/esm2022/testing/sumaris-net-ngx-components-testing.mjs +5 -0
- package/esm2022/testing/test/login-env.mjs +122 -0
- package/esm2022/testing/testing_api.mjs +10 -0
- package/esm2022/testing/utils/auth.utils.mjs +64 -0
- package/esm2022/testing/utils/ionic.utils.mjs +66 -0
- package/esm2022/testing/utils/material.utils.mjs +100 -0
- package/esm2022/testing/utils/startup.constants.mjs +4 -0
- package/esm2022/testing/utils/ui.utils.mjs +139 -0
- package/fesm2022/sumaris-net-ngx-components-testing.mjs +499 -0
- package/fesm2022/sumaris-net-ngx-components-testing.mjs.map +1 -0
- package/fesm2022/sumaris-net.ngx-components.mjs +314 -139
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +8 -1
- package/src/app/core/services/account.service.d.ts +5 -2
- package/src/app/core/services/startup.constants.d.ts +1 -0
- package/src/app/core/services/startup.model.d.ts +1 -0
- package/src/app/core/services/startup.service.d.ts +31 -0
- package/src/assets/manifest.json +1 -1
- package/src/environments/environment.class.d.ts +2 -0
- package/testing/index.d.ts +5 -0
- package/testing/test/login-env.d.ts +76 -0
- package/testing/testing_api.d.ts +6 -0
- package/testing/utils/auth.utils.d.ts +21 -0
- package/testing/utils/ionic.utils.d.ts +51 -0
- package/testing/utils/material.utils.d.ts +57 -0
- package/testing/utils/startup.constants.d.ts +1 -0
- package/testing/utils/ui.utils.d.ts +79 -0
|
@@ -222,6 +222,9 @@ class Environment {
|
|
|
222
222
|
// Default authentication /!\ For DEV only
|
|
223
223
|
// (see values in the test database - XML files in Pod's module)
|
|
224
224
|
defaultAuthValues;
|
|
225
|
+
// Auto login /!\ For DEV only
|
|
226
|
+
// (the order defines the method precedence)
|
|
227
|
+
startupOrder;
|
|
225
228
|
// Account
|
|
226
229
|
account;
|
|
227
230
|
entityEditor;
|
|
@@ -16440,138 +16443,6 @@ const StorageDrivers = {
|
|
|
16440
16443
|
};
|
|
16441
16444
|
const APP_STORAGE = new InjectionToken('Storage');
|
|
16442
16445
|
|
|
16443
|
-
// This file can be replaced during build by using the `fileReplacements` array.
|
|
16444
|
-
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
|
|
16445
|
-
// The list of file replacements can be found in `angular.json`.
|
|
16446
|
-
/*
|
|
16447
|
-
* In development mode, to ignore zone related error stack frames such as
|
|
16448
|
-
* `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
|
|
16449
|
-
* import the following file, but please comment it out in production mode
|
|
16450
|
-
* because it will have performance impact when throw error
|
|
16451
|
-
*/
|
|
16452
|
-
//import 'zone.js/plugins/zone-error';
|
|
16453
|
-
const environment = Object.freeze({
|
|
16454
|
-
name: '@sumaris-net/ngx-components', // overridden by ENVIRONMENT token
|
|
16455
|
-
version: '1.0', // overridden by ENVIRONMENT token
|
|
16456
|
-
// Do NOT set to false - because this value will be used by releases
|
|
16457
|
-
//production: false,
|
|
16458
|
-
production: true,
|
|
16459
|
-
// Do NOT set - because this value will be used by releases
|
|
16460
|
-
//externalEnvironmentUrl: null,
|
|
16461
|
-
baseUrl: '/',
|
|
16462
|
-
defaultLocale: 'fr',
|
|
16463
|
-
defaultLatLongFormat: 'DDMM',
|
|
16464
|
-
apolloFetchPolicy: 'cache-first',
|
|
16465
|
-
useHash: false,
|
|
16466
|
-
allowDarkMode: true,
|
|
16467
|
-
//defaultRoute: '/home',
|
|
16468
|
-
//enableMenu: true,
|
|
16469
|
-
// FIXME: enable cache
|
|
16470
|
-
persistCache: false,
|
|
16471
|
-
// TODO: make this works
|
|
16472
|
-
//offline: true,
|
|
16473
|
-
peerMinVersion: '1.8.0',
|
|
16474
|
-
peerDefaultPrefix: 'http://',
|
|
16475
|
-
enableSelectPeerByFeature: true,
|
|
16476
|
-
sendAppVersionHeaders: true,
|
|
16477
|
-
defaultPeer: {
|
|
16478
|
-
host: 'localhost',
|
|
16479
|
-
port: 8081,
|
|
16480
|
-
},
|
|
16481
|
-
defaultPeers: [
|
|
16482
|
-
{
|
|
16483
|
-
host: 'localhost',
|
|
16484
|
-
port: 8080,
|
|
16485
|
-
},
|
|
16486
|
-
{
|
|
16487
|
-
host: 'localhost',
|
|
16488
|
-
port: 8081,
|
|
16489
|
-
},
|
|
16490
|
-
{
|
|
16491
|
-
host: '192.168.0.45',
|
|
16492
|
-
port: 8080,
|
|
16493
|
-
},
|
|
16494
|
-
{
|
|
16495
|
-
host: '192.168.0.24',
|
|
16496
|
-
port: 8080,
|
|
16497
|
-
},
|
|
16498
|
-
{
|
|
16499
|
-
host: '192.168.0.29',
|
|
16500
|
-
port: 8080,
|
|
16501
|
-
},
|
|
16502
|
-
{
|
|
16503
|
-
host: '192.168.0.107',
|
|
16504
|
-
port: 8080,
|
|
16505
|
-
},
|
|
16506
|
-
{
|
|
16507
|
-
host: 'sih.sfa.sc',
|
|
16508
|
-
port: 443,
|
|
16509
|
-
},
|
|
16510
|
-
{
|
|
16511
|
-
host: 'test.sumaris.net',
|
|
16512
|
-
port: 443,
|
|
16513
|
-
},
|
|
16514
|
-
{
|
|
16515
|
-
host: 'open.sumaris.net',
|
|
16516
|
-
port: 443,
|
|
16517
|
-
},
|
|
16518
|
-
{
|
|
16519
|
-
host: 'server.e-is.pro',
|
|
16520
|
-
port: 443,
|
|
16521
|
-
},
|
|
16522
|
-
],
|
|
16523
|
-
defaultAppName: 'SUMARiS',
|
|
16524
|
-
defaultAndroidInstallUrl: 'https://play.google.com/store/apps/details?id=net.sumaris.app',
|
|
16525
|
-
defaultIOSInstallUrl: 'https://apps.apple.com/us/app/sumaris/id6736747523',
|
|
16526
|
-
defaultDesktopInstallUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/releases',
|
|
16527
|
-
// Storage
|
|
16528
|
-
storage: {
|
|
16529
|
-
driverOrder: [StorageDrivers.SQLLite, StorageDrivers.IndexedDB, StorageDrivers.WebSQL, StorageDrivers.LocalStorage],
|
|
16530
|
-
},
|
|
16531
|
-
// About
|
|
16532
|
-
sourceUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components',
|
|
16533
|
-
reportIssueUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/issues',
|
|
16534
|
-
forumUrl: null, //'https://forum.sumaris.net',
|
|
16535
|
-
helpUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-doc/-/blob/master/user-manual/index_fr.md',
|
|
16536
|
-
privacyPolicyUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/master/doc/privacy_policy_fr.md',
|
|
16537
|
-
termsOfUseUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/master/doc/terms_of_use_fr.md?ref_type=heads',
|
|
16538
|
-
// Development
|
|
16539
|
-
defaultAuthValues: {
|
|
16540
|
-
// Token auth (using Person.pubkey)
|
|
16541
|
-
username: 'admin@sumaris.net',
|
|
16542
|
-
password: 'admin',
|
|
16543
|
-
},
|
|
16544
|
-
account: {
|
|
16545
|
-
enableListenChanges: true,
|
|
16546
|
-
listenIntervalInSeconds: 60,
|
|
16547
|
-
enableAvatarEdit: true,
|
|
16548
|
-
},
|
|
16549
|
-
entityEditor: {
|
|
16550
|
-
enableListenChanges: true,
|
|
16551
|
-
listenIntervalInSeconds: 60,
|
|
16552
|
-
},
|
|
16553
|
-
feed: {
|
|
16554
|
-
jsonFeed: {
|
|
16555
|
-
fr: [
|
|
16556
|
-
'/api/feed.json',
|
|
16557
|
-
'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/raw/master/doc/feed/feed-fr.json',
|
|
16558
|
-
// Example with JsonFeed version 1 (and not 1.1)
|
|
16559
|
-
//'https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/feed-fr.json',
|
|
16560
|
-
// Example with discourse API :
|
|
16561
|
-
//'https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-fr-FR.json',
|
|
16562
|
-
],
|
|
16563
|
-
en: [
|
|
16564
|
-
'/api/feed.json',
|
|
16565
|
-
'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/raw/master/doc/feed/feed-en.json'
|
|
16566
|
-
],
|
|
16567
|
-
},
|
|
16568
|
-
maxContentLength: 1000,
|
|
16569
|
-
maxAgeInMonths: -1,
|
|
16570
|
-
maxCount: 3,
|
|
16571
|
-
},
|
|
16572
|
-
buildDate: new Date().toISOString(),
|
|
16573
|
-
});
|
|
16574
|
-
|
|
16575
16446
|
class StorageService extends StartableService {
|
|
16576
16447
|
storage;
|
|
16577
16448
|
environment;
|
|
@@ -16587,7 +16458,7 @@ class StorageService extends StartableService {
|
|
|
16587
16458
|
}
|
|
16588
16459
|
async ngOnStart() {
|
|
16589
16460
|
try {
|
|
16590
|
-
console.debug(`[storage] Starting... {driverOrder: ${environment.storage?.driverOrder}}`);
|
|
16461
|
+
console.debug(`[storage] Starting... {driverOrder: ${this.environment.storage?.driverOrder}}`);
|
|
16591
16462
|
// Define Cordova SQLLite driver
|
|
16592
16463
|
await this.storage.defineDriver(CordovaSQLiteDriver);
|
|
16593
16464
|
// Create the storage instance
|
|
@@ -17106,6 +16977,139 @@ function isOnFieldMode(value) {
|
|
|
17106
16977
|
}
|
|
17107
16978
|
const APP_LOCALES = new InjectionToken('locales');
|
|
17108
16979
|
|
|
16980
|
+
// This file can be replaced during build by using the `fileReplacements` array.
|
|
16981
|
+
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
|
|
16982
|
+
// The list of file replacements can be found in `angular.json`.
|
|
16983
|
+
/*
|
|
16984
|
+
* In development mode, to ignore zone related error stack frames such as
|
|
16985
|
+
* `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
|
|
16986
|
+
* import the following file, but please comment it out in production mode
|
|
16987
|
+
* because it will have performance impact when throw error
|
|
16988
|
+
*/
|
|
16989
|
+
//import 'zone.js/plugins/zone-error';
|
|
16990
|
+
const environment = Object.freeze({
|
|
16991
|
+
name: '@sumaris-net/ngx-components', // overridden by ENVIRONMENT token
|
|
16992
|
+
version: '1.0', // overridden by ENVIRONMENT token
|
|
16993
|
+
// Do NOT set to false - because this value will be used by releases
|
|
16994
|
+
//production: false,
|
|
16995
|
+
production: true,
|
|
16996
|
+
// Do NOT set - because this value will be used by releases
|
|
16997
|
+
//externalEnvironmentUrl: null,
|
|
16998
|
+
baseUrl: '/',
|
|
16999
|
+
defaultLocale: 'fr',
|
|
17000
|
+
defaultLatLongFormat: 'DDMM',
|
|
17001
|
+
apolloFetchPolicy: 'cache-first',
|
|
17002
|
+
useHash: false,
|
|
17003
|
+
allowDarkMode: true,
|
|
17004
|
+
//defaultRoute: '/home',
|
|
17005
|
+
//enableMenu: true,
|
|
17006
|
+
// FIXME: enable cache
|
|
17007
|
+
persistCache: false,
|
|
17008
|
+
// TODO: make this works
|
|
17009
|
+
//offline: true,
|
|
17010
|
+
peerMinVersion: '1.8.0',
|
|
17011
|
+
peerDefaultPrefix: 'http://',
|
|
17012
|
+
enableSelectPeerByFeature: true,
|
|
17013
|
+
sendAppVersionHeaders: true,
|
|
17014
|
+
defaultPeer: {
|
|
17015
|
+
host: 'localhost',
|
|
17016
|
+
port: 8081,
|
|
17017
|
+
},
|
|
17018
|
+
defaultPeers: [
|
|
17019
|
+
{
|
|
17020
|
+
host: 'localhost',
|
|
17021
|
+
port: 8080,
|
|
17022
|
+
},
|
|
17023
|
+
{
|
|
17024
|
+
host: 'localhost',
|
|
17025
|
+
port: 8081,
|
|
17026
|
+
},
|
|
17027
|
+
{
|
|
17028
|
+
host: '192.168.0.45',
|
|
17029
|
+
port: 8080,
|
|
17030
|
+
},
|
|
17031
|
+
{
|
|
17032
|
+
host: '192.168.0.24',
|
|
17033
|
+
port: 8080,
|
|
17034
|
+
},
|
|
17035
|
+
{
|
|
17036
|
+
host: '192.168.0.29',
|
|
17037
|
+
port: 8080,
|
|
17038
|
+
},
|
|
17039
|
+
{
|
|
17040
|
+
host: '192.168.0.107',
|
|
17041
|
+
port: 8080,
|
|
17042
|
+
},
|
|
17043
|
+
{
|
|
17044
|
+
host: 'sih.sfa.sc',
|
|
17045
|
+
port: 443,
|
|
17046
|
+
},
|
|
17047
|
+
{
|
|
17048
|
+
host: 'test.sumaris.net',
|
|
17049
|
+
port: 443,
|
|
17050
|
+
},
|
|
17051
|
+
{
|
|
17052
|
+
host: 'open.sumaris.net',
|
|
17053
|
+
port: 443,
|
|
17054
|
+
},
|
|
17055
|
+
{
|
|
17056
|
+
host: 'server.e-is.pro',
|
|
17057
|
+
port: 443,
|
|
17058
|
+
},
|
|
17059
|
+
],
|
|
17060
|
+
defaultAppName: 'SUMARiS',
|
|
17061
|
+
defaultAndroidInstallUrl: 'https://play.google.com/store/apps/details?id=net.sumaris.app',
|
|
17062
|
+
defaultIOSInstallUrl: 'https://apps.apple.com/us/app/sumaris/id6736747523',
|
|
17063
|
+
defaultDesktopInstallUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/releases',
|
|
17064
|
+
// Storage
|
|
17065
|
+
storage: {
|
|
17066
|
+
driverOrder: [StorageDrivers.SQLLite, StorageDrivers.IndexedDB, StorageDrivers.WebSQL, StorageDrivers.LocalStorage],
|
|
17067
|
+
},
|
|
17068
|
+
// About
|
|
17069
|
+
sourceUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components',
|
|
17070
|
+
reportIssueUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/issues',
|
|
17071
|
+
forumUrl: null, //'https://forum.sumaris.net',
|
|
17072
|
+
helpUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-doc/-/blob/master/user-manual/index_fr.md',
|
|
17073
|
+
privacyPolicyUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/master/doc/privacy_policy_fr.md',
|
|
17074
|
+
termsOfUseUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/master/doc/terms_of_use_fr.md?ref_type=heads',
|
|
17075
|
+
// Development
|
|
17076
|
+
defaultAuthValues: {
|
|
17077
|
+
// Token auth (using Person.pubkey)
|
|
17078
|
+
username: 'admin@sumaris.net',
|
|
17079
|
+
password: 'admin',
|
|
17080
|
+
},
|
|
17081
|
+
startupOrder: ['url', 'window', 'environment'],
|
|
17082
|
+
account: {
|
|
17083
|
+
enableListenChanges: true,
|
|
17084
|
+
listenIntervalInSeconds: 60,
|
|
17085
|
+
enableAvatarEdit: true,
|
|
17086
|
+
},
|
|
17087
|
+
entityEditor: {
|
|
17088
|
+
enableListenChanges: true,
|
|
17089
|
+
listenIntervalInSeconds: 60,
|
|
17090
|
+
},
|
|
17091
|
+
feed: {
|
|
17092
|
+
jsonFeed: {
|
|
17093
|
+
fr: [
|
|
17094
|
+
'/api/feed.json',
|
|
17095
|
+
'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/raw/master/doc/feed/feed-fr.json',
|
|
17096
|
+
// Example with JsonFeed version 1 (and not 1.1)
|
|
17097
|
+
//'https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/feed-fr.json',
|
|
17098
|
+
// Example with discourse API :
|
|
17099
|
+
//'https://raw.githubusercontent.com/duniter/cesium/master/doc/feed/1.1/feed-fr-FR.json',
|
|
17100
|
+
],
|
|
17101
|
+
en: [
|
|
17102
|
+
'/api/feed.json',
|
|
17103
|
+
'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/raw/master/doc/feed/feed-en.json'
|
|
17104
|
+
],
|
|
17105
|
+
},
|
|
17106
|
+
maxContentLength: 1000,
|
|
17107
|
+
maxAgeInMonths: -1,
|
|
17108
|
+
maxCount: 3,
|
|
17109
|
+
},
|
|
17110
|
+
buildDate: new Date().toISOString(),
|
|
17111
|
+
});
|
|
17112
|
+
|
|
17109
17113
|
class EntityClasses {
|
|
17110
17114
|
static CLASSES_BY_NAME = new Map();
|
|
17111
17115
|
static register(typename, entityClass) {
|
|
@@ -23893,6 +23897,154 @@ class Base58 {
|
|
|
23893
23897
|
}
|
|
23894
23898
|
}
|
|
23895
23899
|
|
|
23900
|
+
// Standalone startup constants, with NO Angular DI dependency.
|
|
23901
|
+
// Kept separate from startup.service.ts so it can be safely imported by e2e tests
|
|
23902
|
+
// (Playwright's transpiler does not support Angular parameter decorators).
|
|
23903
|
+
// Key used to bridge auto-peer/login data across a version-check reload.
|
|
23904
|
+
// platform.service may reload the page via location.href = ..., which destroys both
|
|
23905
|
+
// URL params (hash/search) and the window object. sessionStorage survives same-tab
|
|
23906
|
+
// reloads, is tab-scoped, non-persistent (cleared on tab close), and not accessible
|
|
23907
|
+
// cross-origin — making it safe for transient credential bridging.
|
|
23908
|
+
const STARTUP_DATA_STORAGE_KEY = '__appStartupData';
|
|
23909
|
+
|
|
23910
|
+
class StartupService {
|
|
23911
|
+
_data = { password: null, username: null, offline: null, peerUrl: null };
|
|
23912
|
+
storage = inject(StorageService);
|
|
23913
|
+
environment = inject(ENVIRONMENT, { optional: true });
|
|
23914
|
+
get data() {
|
|
23915
|
+
return this._data;
|
|
23916
|
+
}
|
|
23917
|
+
set data(data) {
|
|
23918
|
+
if (isNotNilOrBlank(data.username))
|
|
23919
|
+
this._data.username = data.username;
|
|
23920
|
+
if (isNotNilOrBlank(data.password))
|
|
23921
|
+
this._data.password = data.password;
|
|
23922
|
+
if (isNotNil(data.offline))
|
|
23923
|
+
this._data.offline = data.offline;
|
|
23924
|
+
if (isNotNilOrBlank(data.peerUrl))
|
|
23925
|
+
this._data.peerUrl = data.peerUrl;
|
|
23926
|
+
}
|
|
23927
|
+
hasPeer() {
|
|
23928
|
+
return isNotNilOrBlank(this._data?.peerUrl);
|
|
23929
|
+
}
|
|
23930
|
+
consumePeer() {
|
|
23931
|
+
if (!this._data)
|
|
23932
|
+
return null;
|
|
23933
|
+
const autoPeer = this._data?.peerUrl;
|
|
23934
|
+
this._data.peerUrl = null;
|
|
23935
|
+
return autoPeer;
|
|
23936
|
+
}
|
|
23937
|
+
hasAuth() {
|
|
23938
|
+
return isNotNilOrBlank(this._data?.username) && isNotNilOrBlank(this._data?.password);
|
|
23939
|
+
}
|
|
23940
|
+
consumeAuth() {
|
|
23941
|
+
if (!this._data)
|
|
23942
|
+
return null;
|
|
23943
|
+
const { username, password, offline } = this._data;
|
|
23944
|
+
this._data.username = null;
|
|
23945
|
+
this._data.password = null;
|
|
23946
|
+
this._data.offline = null;
|
|
23947
|
+
return { username, password, offline };
|
|
23948
|
+
}
|
|
23949
|
+
async start() {
|
|
23950
|
+
const authMethods = this.environment?.startupOrder;
|
|
23951
|
+
if (isEmptyArray(authMethods))
|
|
23952
|
+
return; // Skip if no auth methods configured
|
|
23953
|
+
await this.storage.ready();
|
|
23954
|
+
console.debug(`[startup] Initializing methods: ${authMethods.join(' -> ')}`);
|
|
23955
|
+
const urlHashParams = new URLSearchParams(window.location.hash?.slice(1) || '');
|
|
23956
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
23957
|
+
const windowStartupData = window[STARTUP_DATA_STORAGE_KEY];
|
|
23958
|
+
const rawData = sessionStorage.getItem(STARTUP_DATA_STORAGE_KEY);
|
|
23959
|
+
const data = rawData ? JSON.parse(rawData) : null;
|
|
23960
|
+
const settingsRaw = await this.storage.get('settings');
|
|
23961
|
+
const settings = typeof settingsRaw === 'string' ? JSON.parse(settingsRaw) : (settingsRaw ?? {});
|
|
23962
|
+
// Resolve auto auth data from each configured source
|
|
23963
|
+
if (data) {
|
|
23964
|
+
// Restore from sessionStorage in case of a previous version-check reload
|
|
23965
|
+
this.data = data;
|
|
23966
|
+
}
|
|
23967
|
+
else {
|
|
23968
|
+
// Resolve each configured source by priority (first method has highest priority)
|
|
23969
|
+
let username = null;
|
|
23970
|
+
let password = null;
|
|
23971
|
+
let offline = null;
|
|
23972
|
+
let peerUrl = null;
|
|
23973
|
+
for (const authMethod of authMethods.reverse()) {
|
|
23974
|
+
switch (authMethod) {
|
|
23975
|
+
case 'url':
|
|
23976
|
+
username = urlHashParams.get('username') || urlSearchParams.get('username');
|
|
23977
|
+
password = urlHashParams.get('password') || urlSearchParams.get('password');
|
|
23978
|
+
offline = urlHashParams.get('offline') === 'true' || urlSearchParams.get('offline') === 'true';
|
|
23979
|
+
peerUrl = urlHashParams.get('peerUrl') || urlSearchParams.get('peerUrl');
|
|
23980
|
+
break;
|
|
23981
|
+
case 'window':
|
|
23982
|
+
username = windowStartupData?.username ?? null;
|
|
23983
|
+
password = windowStartupData?.password ?? null;
|
|
23984
|
+
offline = windowStartupData?.offline ?? null;
|
|
23985
|
+
peerUrl = windowStartupData?.peerUrl ?? null;
|
|
23986
|
+
break;
|
|
23987
|
+
case 'environment':
|
|
23988
|
+
username = this.environment?.defaultAuthValues?.username;
|
|
23989
|
+
password = this.environment?.defaultAuthValues?.password;
|
|
23990
|
+
offline = this.environment?.offline;
|
|
23991
|
+
peerUrl = Peer.fromObject(this.environment?.peer)?.url ||
|
|
23992
|
+
settings?.peerUrl || Peer.fromObject(this.environment.defaultPeer)?.url;
|
|
23993
|
+
break;
|
|
23994
|
+
default:
|
|
23995
|
+
console.warn('[startup] Unknown method:', authMethod);
|
|
23996
|
+
}
|
|
23997
|
+
this.data = { username, password, offline, peerUrl };
|
|
23998
|
+
}
|
|
23999
|
+
}
|
|
24000
|
+
const sensitiveParams = ['username', 'password', 'offline', 'peerUrl'];
|
|
24001
|
+
const hasHashSensitiveParam = sensitiveParams.some((p) => urlHashParams.has(p));
|
|
24002
|
+
const hasSearchSensitiveParam = sensitiveParams.some((p) => urlSearchParams.has(p));
|
|
24003
|
+
const hasWindowData = !!windowStartupData;
|
|
24004
|
+
const hasExternalSource = hasHashSensitiveParam || hasSearchSensitiveParam || hasWindowData;
|
|
24005
|
+
// Persist to sessionStorage so data survives a potential version-check reload
|
|
24006
|
+
if (hasExternalSource && (this.hasPeer() || this.hasAuth())) {
|
|
24007
|
+
sessionStorage.setItem(STARTUP_DATA_STORAGE_KEY, JSON.stringify(this._data));
|
|
24008
|
+
}
|
|
24009
|
+
// Apply auto peer by saving peerUrl to localStorage so the app connects to the right peer
|
|
24010
|
+
if (this.hasPeer()) {
|
|
24011
|
+
settings.peerUrl = this.consumePeer();
|
|
24012
|
+
console.debug(`[startup] Set peer URL to ${settings.peerUrl}`);
|
|
24013
|
+
await this.storage.set('settings', JSON.stringify(settings));
|
|
24014
|
+
}
|
|
24015
|
+
// Remove sensitive parameters from the URL
|
|
24016
|
+
if (hasHashSensitiveParam || hasSearchSensitiveParam) {
|
|
24017
|
+
sensitiveParams.forEach((p) => urlSearchParams.delete(p));
|
|
24018
|
+
const search = urlSearchParams.toString() ? `?${urlSearchParams}` : '';
|
|
24019
|
+
window.history.replaceState(null, '', window.location.pathname + search);
|
|
24020
|
+
}
|
|
24021
|
+
// Clear sessionStorage bridge after consumption (post-reload path only)
|
|
24022
|
+
if (data) {
|
|
24023
|
+
sessionStorage.removeItem(STARTUP_DATA_STORAGE_KEY);
|
|
24024
|
+
}
|
|
24025
|
+
// Remove the window bridge object
|
|
24026
|
+
delete window[STARTUP_DATA_STORAGE_KEY];
|
|
24027
|
+
}
|
|
24028
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StartupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
24029
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StartupService, providedIn: 'root' });
|
|
24030
|
+
}
|
|
24031
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StartupService, decorators: [{
|
|
24032
|
+
type: Injectable,
|
|
24033
|
+
args: [{ providedIn: 'root' }]
|
|
24034
|
+
}] });
|
|
24035
|
+
/**
|
|
24036
|
+
* Factory function for the app startup initializer.
|
|
24037
|
+
* In Angular 18, this is used with APP_INITIALIZER:
|
|
24038
|
+
* { provide: APP_INITIALIZER, useFactory: createAppStartupInitializer, multi: true }
|
|
24039
|
+
*
|
|
24040
|
+
* inject() is called during factory execution (in injection context), then the
|
|
24041
|
+
* returned function calls the already-injected service.
|
|
24042
|
+
*/
|
|
24043
|
+
function createAppStartupInitializer() {
|
|
24044
|
+
const service = inject(StartupService);
|
|
24045
|
+
return () => service.start();
|
|
24046
|
+
}
|
|
24047
|
+
|
|
23896
24048
|
const TOKEN_STORAGE_KEY = 'token';
|
|
23897
24049
|
const PUBKEY_STORAGE_KEY = 'pubkey';
|
|
23898
24050
|
const SECKEY_STORAGE_KEY = 'seckey';
|
|
@@ -24089,6 +24241,7 @@ class AccountService extends BaseGraphqlService {
|
|
|
24089
24241
|
settings;
|
|
24090
24242
|
storage;
|
|
24091
24243
|
file;
|
|
24244
|
+
startupService;
|
|
24092
24245
|
translate;
|
|
24093
24246
|
toastController;
|
|
24094
24247
|
environment;
|
|
@@ -24164,13 +24317,14 @@ class AccountService extends BaseGraphqlService {
|
|
|
24164
24317
|
get remoteLocalSettingsKeys() {
|
|
24165
24318
|
return this._remoteLocalSettingsKeys;
|
|
24166
24319
|
}
|
|
24167
|
-
constructor(network, graphql, settings, storage, file, translate, toastController, environment, options, accountOptions) {
|
|
24320
|
+
constructor(network, graphql, settings, storage, file, startupService, translate, toastController, environment, options, accountOptions) {
|
|
24168
24321
|
super(graphql, environment);
|
|
24169
24322
|
this.network = network;
|
|
24170
24323
|
this.graphql = graphql;
|
|
24171
24324
|
this.settings = settings;
|
|
24172
24325
|
this.storage = storage;
|
|
24173
24326
|
this.file = file;
|
|
24327
|
+
this.startupService = startupService;
|
|
24174
24328
|
this.translate = translate;
|
|
24175
24329
|
this.toastController = toastController;
|
|
24176
24330
|
this.environment = environment;
|
|
@@ -24213,7 +24367,11 @@ class AccountService extends BaseGraphqlService {
|
|
|
24213
24367
|
this.restart();
|
|
24214
24368
|
}
|
|
24215
24369
|
}));
|
|
24216
|
-
|
|
24370
|
+
// Try to auto login, or restore locally
|
|
24371
|
+
const autoLogin = await this.autoLogin();
|
|
24372
|
+
if (!autoLogin) {
|
|
24373
|
+
await this.restoreLocally();
|
|
24374
|
+
}
|
|
24217
24375
|
await this.listenSettings();
|
|
24218
24376
|
return this._data;
|
|
24219
24377
|
}
|
|
@@ -24859,6 +25017,20 @@ class AccountService extends BaseGraphqlService {
|
|
|
24859
25017
|
.pipe(debounceTime(2000), filter(() => this.isLogin() && this.network.online))
|
|
24860
25018
|
.subscribe((settings) => this.saveLocalSettingsRemotely(settings)));
|
|
24861
25019
|
}
|
|
25020
|
+
async autoLogin() {
|
|
25021
|
+
if (!this.startupService?.hasAuth())
|
|
25022
|
+
return false; // Skip if no auth data
|
|
25023
|
+
try {
|
|
25024
|
+
const authData = this.startupService.consumeAuth();
|
|
25025
|
+
console.debug('[account] Attempting auto login as:', authData.username);
|
|
25026
|
+
await this.login(authData);
|
|
25027
|
+
return true;
|
|
25028
|
+
}
|
|
25029
|
+
catch (error) {
|
|
25030
|
+
console.warn('[account] Auto auth failed:', error);
|
|
25031
|
+
return false;
|
|
25032
|
+
}
|
|
25033
|
+
}
|
|
24862
25034
|
async restoreLocally() {
|
|
24863
25035
|
// Restore from storage
|
|
24864
25036
|
const values = await Promise.all([
|
|
@@ -25238,13 +25410,15 @@ class AccountService extends BaseGraphqlService {
|
|
|
25238
25410
|
showToast(opts) {
|
|
25239
25411
|
return Toasts.show(this.toastController, this.translate, opts);
|
|
25240
25412
|
}
|
|
25241
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccountService, deps: [{ token: NetworkService }, { token: GraphqlService }, { token: LocalSettingsService }, { token: i2$4.Storage }, { token: FileService }, { token: i1$1.TranslateService, optional: true }, { token: i2$1.ToastController, optional: true }, { token: ENVIRONMENT }, { token: APP_USER_SETTINGS_OPTIONS, optional: true }, { token: APP_ACCOUNT_SERVICE_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
25413
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccountService, deps: [{ token: NetworkService }, { token: GraphqlService }, { token: LocalSettingsService }, { token: i2$4.Storage }, { token: FileService }, { token: StartupService, optional: true }, { token: i1$1.TranslateService, optional: true }, { token: i2$1.ToastController, optional: true }, { token: ENVIRONMENT }, { token: APP_USER_SETTINGS_OPTIONS, optional: true }, { token: APP_ACCOUNT_SERVICE_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
25242
25414
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccountService, providedIn: 'root' });
|
|
25243
25415
|
}
|
|
25244
25416
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccountService, decorators: [{
|
|
25245
25417
|
type: Injectable,
|
|
25246
25418
|
args: [{ providedIn: 'root', deps: [ENVIRONMENT] }]
|
|
25247
|
-
}], ctorParameters: () => [{ type: NetworkService }, { type: GraphqlService }, { type: LocalSettingsService }, { type: i2$4.Storage }, { type: FileService }, { type:
|
|
25419
|
+
}], ctorParameters: () => [{ type: NetworkService }, { type: GraphqlService }, { type: LocalSettingsService }, { type: i2$4.Storage }, { type: FileService }, { type: StartupService, decorators: [{
|
|
25420
|
+
type: Optional
|
|
25421
|
+
}] }, { type: i1$1.TranslateService, decorators: [{
|
|
25248
25422
|
type: Optional
|
|
25249
25423
|
}] }, { type: i2$1.ToastController, decorators: [{
|
|
25250
25424
|
type: Optional
|
|
@@ -26278,7 +26452,8 @@ class PlatformService extends StartableService {
|
|
|
26278
26452
|
// Hide accessory bar (iOS only)
|
|
26279
26453
|
if (this.isApp() && this.isIOS()) {
|
|
26280
26454
|
pluginName = CapacitorPlugins.Keyboard;
|
|
26281
|
-
|
|
26455
|
+
// Let Capacitor config handle accessory bar
|
|
26456
|
+
//await Keyboard.setAccessoryBarVisible({ isVisible: false });
|
|
26282
26457
|
}
|
|
26283
26458
|
}
|
|
26284
26459
|
catch (err) {
|
|
@@ -27346,7 +27521,7 @@ class SharedModule {
|
|
|
27346
27521
|
},
|
|
27347
27522
|
{
|
|
27348
27523
|
provide: ENVIRONMENT,
|
|
27349
|
-
deps: [EnvironmentLoader
|
|
27524
|
+
deps: [EnvironmentLoader],
|
|
27350
27525
|
useFactory: (loader) => loader.get(),
|
|
27351
27526
|
},
|
|
27352
27527
|
]
|