@acorex-platform/framework-client 0.0.18 → 0.0.20

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 (108) hide show
  1. package/fesm2022/acorex-platform-framework-client-auth.mjs +872 -314
  2. package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs → acorex-platform-framework-client-common-common-settings.provider-CLm2BVk-.mjs} +88 -5
  4. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-CLm2BVk-.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-framework-client-common.mjs +2666 -693
  6. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-framework-client-core.mjs +685 -721
  8. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-framework-client-domain.mjs +16 -16
  10. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +124 -72
  11. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
  12. package/fesm2022/{acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs → acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-oE8CeLE8.mjs} +8 -6
  13. package/fesm2022/{acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs.map → acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-oE8CeLE8.mjs.map} +1 -1
  14. package/fesm2022/{acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs → acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-BtLEUWAA.mjs} +4 -4
  15. package/fesm2022/{acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs.map → acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-BtLEUWAA.mjs.map} +1 -1
  16. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +2988 -857
  17. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-framework-client-layout-designer.mjs +277 -185
  19. package/fesm2022/acorex-platform-framework-client-layout-designer.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-BXOMs6oD.mjs +29184 -0
  21. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-BXOMs6oD.mjs.map +1 -0
  22. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-DCK-qb-F.mjs} +34 -20
  23. package/fesm2022/acorex-platform-framework-client-layout-entity-attachments-page.component-DCK-qb-F.mjs.map +1 -0
  24. package/fesm2022/acorex-platform-framework-client-layout-entity-bulk-entity.command-Cs3agnpF.mjs +162 -0
  25. package/fesm2022/acorex-platform-framework-client-layout-entity-bulk-entity.command-Cs3agnpF.mjs.map +1 -0
  26. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-p0hxDb0W.mjs} +31 -19
  27. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-p0hxDb0W.mjs.map +1 -0
  28. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-DYV9YPyw.mjs} +30 -18
  29. package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DYV9YPyw.mjs.map +1 -0
  30. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +2 -27090
  31. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs.map +1 -1
  32. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +382 -154
  33. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  34. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +646 -280
  35. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  36. package/fesm2022/{acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs → acorex-platform-framework-client-layout-widgets-button-widget-designer.component-BiWerYcu.mjs} +16 -10
  37. package/fesm2022/{acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs.map → acorex-platform-framework-client-layout-widgets-button-widget-designer.component-BiWerYcu.mjs.map} +1 -1
  38. package/fesm2022/{acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs → acorex-platform-framework-client-layout-widgets-image-preview.popup-BOrrMm3U.mjs} +9 -8
  39. package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-BOrrMm3U.mjs.map +1 -0
  40. package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-WzIiwnGC.mjs} +20 -12
  41. package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs.map → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-WzIiwnGC.mjs.map} +1 -1
  42. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-3CO4xJB3.mjs} +32 -18
  43. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-3CO4xJB3.mjs.map} +1 -1
  44. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-CRST84ou.mjs} +8 -7
  45. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs.map → acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-CRST84ou.mjs.map} +1 -1
  46. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-FjtSRxIX.mjs} +4 -4
  47. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs.map → acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-FjtSRxIX.mjs.map} +1 -1
  48. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-D6HFPmGC.mjs} +10 -8
  49. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs.map → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-D6HFPmGC.mjs.map} +1 -1
  50. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +4868 -2548
  51. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs.map +1 -1
  52. package/fesm2022/acorex-platform-framework-client-native.mjs +7 -7
  53. package/fesm2022/acorex-platform-framework-client-realtime-set-presence-availability.command-CetlUjnM.mjs +29 -0
  54. package/fesm2022/acorex-platform-framework-client-realtime-set-presence-availability.command-CetlUjnM.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-framework-client-realtime.mjs +463 -26
  56. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -1
  57. package/fesm2022/acorex-platform-framework-client-runtime.mjs +300 -137
  58. package/fesm2022/acorex-platform-framework-client-runtime.mjs.map +1 -1
  59. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs → acorex-platform-framework-client-themes-default-entity-master-create-view.component-yeftgJ_K.mjs} +10 -7
  60. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs.map → acorex-platform-framework-client-themes-default-entity-master-create-view.component-yeftgJ_K.mjs.map} +1 -1
  61. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs → acorex-platform-framework-client-themes-default-entity-master-modify-view.component-DWE3OWGm.mjs} +10 -7
  62. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs.map → acorex-platform-framework-client-themes-default-entity-master-modify-view.component-DWE3OWGm.mjs.map} +1 -1
  63. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs → acorex-platform-framework-client-themes-default-entity-master-single-view.component-C2Abf7Lb.mjs} +21 -19
  64. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-C2Abf7Lb.mjs.map +1 -0
  65. package/fesm2022/{acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs → acorex-platform-framework-client-themes-default-error-401.component-BrTotLx1.mjs} +5 -5
  66. package/fesm2022/{acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs.map → acorex-platform-framework-client-themes-default-error-401.component-BrTotLx1.mjs.map} +1 -1
  67. package/fesm2022/{acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs → acorex-platform-framework-client-themes-default-error-404.component-DsC7_s59.mjs} +5 -5
  68. package/fesm2022/{acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs.map → acorex-platform-framework-client-themes-default-error-404.component-DsC7_s59.mjs.map} +1 -1
  69. package/fesm2022/{acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs → acorex-platform-framework-client-themes-default-error-offline.component-CngiQycG.mjs} +6 -6
  70. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-CngiQycG.mjs.map +1 -0
  71. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +421 -265
  72. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  73. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CbZALjB5.mjs} +8 -6
  74. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs.map → acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CbZALjB5.mjs.map} +1 -1
  75. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BRrNT6x2.mjs} +8 -6
  76. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs.map → acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BRrNT6x2.mjs.map} +1 -1
  77. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BIsQTr6B.mjs} +4 -4
  78. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs.map → acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BIsQTr6B.mjs.map} +1 -1
  79. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-ZclmSbt9.mjs} +16 -10
  80. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs.map → acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-ZclmSbt9.mjs.map} +1 -1
  81. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +538 -133
  82. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  83. package/fesm2022/acorex-platform-framework-client-workflow.mjs +26 -66
  84. package/fesm2022/acorex-platform-framework-client-workflow.mjs.map +1 -1
  85. package/package.json +10 -10
  86. package/realtime/README.md +16 -0
  87. package/runtime/README.md +14 -0
  88. package/types/acorex-platform-framework-client-auth.d.ts +291 -52
  89. package/types/acorex-platform-framework-client-common.d.ts +613 -87
  90. package/types/acorex-platform-framework-client-core.d.ts +213 -206
  91. package/types/acorex-platform-framework-client-layout-builder.d.ts +14 -8
  92. package/types/acorex-platform-framework-client-layout-components.d.ts +392 -28
  93. package/types/acorex-platform-framework-client-layout-entity.d.ts +667 -417
  94. package/types/acorex-platform-framework-client-layout-views.d.ts +31 -11
  95. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +66 -17
  96. package/types/acorex-platform-framework-client-layout-widgets.d.ts +294 -67
  97. package/types/acorex-platform-framework-client-realtime.d.ts +183 -6
  98. package/types/acorex-platform-framework-client-runtime.d.ts +134 -28
  99. package/types/acorex-platform-framework-client-themes-default.d.ts +9 -1
  100. package/types/acorex-platform-framework-client-themes-shared.d.ts +8 -2
  101. package/types/acorex-platform-framework-client-workflow.d.ts +11 -35
  102. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs.map +0 -1
  103. package/fesm2022/acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs.map +0 -1
  104. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs.map +0 -1
  105. package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs.map +0 -1
  106. package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs.map +0 -1
  107. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs.map +0 -1
  108. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs.map +0 -1
@@ -2,11 +2,11 @@ import * as i0 from '@angular/core';
2
2
  import { NgModule, Injectable } from '@angular/core';
3
3
 
4
4
  class AXPNativeModule {
5
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeModule }); }
7
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeModule }); }
5
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeModule }); }
7
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeModule }); }
8
8
  }
9
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeModule, decorators: [{
9
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeModule, decorators: [{
10
10
  type: NgModule,
11
11
  args: [{
12
12
  imports: [],
@@ -139,10 +139,10 @@ class AXPNativeService {
139
139
  console.error('FlutterChannel is not defined');
140
140
  }
141
141
  }
142
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
143
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeService, providedIn: 'root' }); }
142
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
143
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeService, providedIn: 'root' }); }
144
144
  }
145
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNativeService, decorators: [{
145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPNativeService, decorators: [{
146
146
  type: Injectable,
147
147
  args: [{ providedIn: 'root' }]
148
148
  }], ctorParameters: () => [] });
@@ -0,0 +1,29 @@
1
+ import { runtimeCommandFailure, runtimeCommandSuccessObject } from '@acorex-platform/framework-shared/core';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, Injectable } from '@angular/core';
4
+ import { AXPUserPresenceService } from './acorex-platform-framework-client-realtime.mjs';
5
+
6
+ //#endregion
7
+ //#region ----- Command -----
8
+ class AXPSetPresenceAvailabilityCommand {
9
+ constructor() {
10
+ this.presence = inject(AXPUserPresenceService);
11
+ }
12
+ async execute(input) {
13
+ const status = input?.status;
14
+ if (status !== 'online' && status !== 'away' && status !== 'busy') {
15
+ return runtimeCommandFailure('Invalid presence status');
16
+ }
17
+ await this.presence.setAvailability(status, 'manual');
18
+ return runtimeCommandSuccessObject(undefined);
19
+ }
20
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPSetPresenceAvailabilityCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
21
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPSetPresenceAvailabilityCommand, providedIn: 'root' }); }
22
+ }
23
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPSetPresenceAvailabilityCommand, decorators: [{
24
+ type: Injectable,
25
+ args: [{ providedIn: 'root' }]
26
+ }] });
27
+
28
+ export { AXPSetPresenceAvailabilityCommand };
29
+ //# sourceMappingURL=acorex-platform-framework-client-realtime-set-presence-availability.command-CetlUjnM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-framework-client-realtime-set-presence-availability.command-CetlUjnM.mjs","sources":["../../../../../libs/framework/client/realtime/src/lib/presence/set-presence-availability.command.ts"],"sourcesContent":["import { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { runtimeCommandFailure, runtimeCommandSuccessObject } from '@acorex-platform/framework-shared/core';\nimport { inject, Injectable } from '@angular/core';\nimport { AXPUserPresenceService } from './user-presence.service';\n\n//#region ----- Types -----\n\nexport interface AXPSetPresenceAvailabilityInput {\n status?: 'online' | 'away' | 'busy';\n}\n\n//#endregion\n\n//#region ----- Command -----\n\n@Injectable({ providedIn: 'root' })\nexport class AXPSetPresenceAvailabilityCommand implements AXPCommand<AXPSetPresenceAvailabilityInput, void> {\n private readonly presence = inject(AXPUserPresenceService);\n\n async execute(input?: AXPSetPresenceAvailabilityInput): AXPCommandExecuteResultPromise<void> {\n const status = input?.status;\n if (status !== 'online' && status !== 'away' && status !== 'busy') {\n return runtimeCommandFailure('Invalid presence status');\n }\n await this.presence.setAvailability(status, 'manual');\n return runtimeCommandSuccessObject(undefined);\n }\n}\n\n//#endregion\n"],"names":[],"mappings":";;;;;AAWA;AAEA;MAGa,iCAAiC,CAAA;AAD9C,IAAA,WAAA,GAAA;AAEmB,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAU3D,IAAA;IARC,MAAM,OAAO,CAAC,KAAuC,EAAA;AACnD,QAAA,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM;AAC5B,QAAA,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE;AACjE,YAAA,OAAO,qBAAqB,CAAC,yBAAyB,CAAC;QACzD;QACA,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC;AACrD,QAAA,OAAO,2BAA2B,CAAC,SAAS,CAAC;IAC/C;8GAVW,iCAAiC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAjC,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iCAAiC,cADpB,MAAM,EAAA,CAAA,CAAA;;2FACnB,iCAAiC,EAAA,UAAA,EAAA,CAAA;kBAD7C,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;;;"}
@@ -1,8 +1,13 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Optional, Inject, Injectable, inject, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
2
+ import { InjectionToken, Optional, Inject, Injectable, inject, DestroyRef, makeEnvironmentProviders } from '@angular/core';
3
3
  import { AXPSessionService, AXPSessionStatus } from '@acorex-platform/framework-client/auth';
4
4
  import { io } from 'socket.io-client';
5
- import { BehaviorSubject } from 'rxjs';
5
+ import { BehaviorSubject, Subject } from 'rxjs';
6
+ import { provideAppStartUpTask, AXP_APP_STARTUP_PRIORITY } from '@acorex-platform/framework-client/core';
7
+ import { provideCommandSetups } from '@acorex-platform/framework-client/runtime';
8
+ import { PRESENCE_SET_AVAILABILITY } from '@acorex-platform/framework-shared/runtime';
9
+ import { DOCUMENT } from '@angular/common';
10
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
11
 
7
12
  //#region ---- Client realtime types ----
8
13
  //#endregion
@@ -10,10 +15,18 @@ import { BehaviorSubject } from 'rxjs';
10
15
  //#region ---- Client topic constants (mirror server) ----
11
16
  const AXP_REALTIME_TOPIC_INBOX_REFRESH = 'inbox.refresh';
12
17
  const AXP_REALTIME_TOPIC_CONVERSATION_MESSAGE = 'conversation.message';
18
+ const AXP_REALTIME_TOPIC_CONVERSATION_TYPING = 'conversation.typing';
19
+ const AXP_REALTIME_TOPIC_CONVERSATION_CALL = 'conversation.call';
13
20
  const AXP_REALTIME_TOPIC_ENTITY_MUTATION = 'entity.mutation';
21
+ const AXP_REALTIME_TOPIC_USER_PRESENCE = 'user.presence';
14
22
  const AXP_REALTIME_SOCKET_EVENT = 'realtime';
15
23
  const AXP_REALTIME_SUBSCRIBE_CONVERSATION = 'subscribe.conversation';
16
24
  const AXP_REALTIME_UNSUBSCRIBE_CONVERSATION = 'unsubscribe.conversation';
25
+ const AXP_REALTIME_SUBSCRIBE_PRESENCE = 'subscribe.presence';
26
+ const AXP_REALTIME_UNSUBSCRIBE_PRESENCE = 'unsubscribe.presence';
27
+ const AXP_REALTIME_PRESENCE_LEAVE = 'presence.leave';
28
+ const AXP_REALTIME_PRESENCE_SET = 'presence.set';
29
+ const AXP_REALTIME_EMIT_TYPING = 'conversation.typing.emit';
17
30
  //#endregion
18
31
 
19
32
  //#region ---- Realtime URL helpers ----
@@ -67,10 +80,10 @@ class AXPRealtimeDispatcherService {
67
80
  await registration.handle(envelope);
68
81
  }
69
82
  }
70
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPRealtimeDispatcherService, deps: [{ token: AXP_REALTIME_TOPIC_HANDLER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
71
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPRealtimeDispatcherService }); }
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPRealtimeDispatcherService, deps: [{ token: AXP_REALTIME_TOPIC_HANDLER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
84
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPRealtimeDispatcherService }); }
72
85
  }
73
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPRealtimeDispatcherService, decorators: [{
86
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPRealtimeDispatcherService, decorators: [{
74
87
  type: Injectable
75
88
  }], ctorParameters: () => [{ type: undefined, decorators: [{
76
89
  type: Optional
@@ -79,9 +92,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
79
92
  args: [AXP_REALTIME_TOPIC_HANDLER]
80
93
  }] }] });
81
94
 
82
- //#region ---- Connection service ----
83
- class AXPRealtimeConnectionService {
95
+ /**
96
+ * Always-on realtime connection used by the app shell.
97
+ * Built-in implementation uses Socket.IO; alternate backends may replace this port.
98
+ */
99
+ class AXPRealtimeConnectionPort {
100
+ }
101
+ //#endregion
102
+
103
+ //#region ---- Socket.IO connection (built-in) ----
104
+ /**
105
+ * Built-in always-on realtime connection via Socket.IO.
106
+ */
107
+ class AXPRealtimeConnectionService extends AXPRealtimeConnectionPort {
84
108
  constructor(config) {
109
+ super();
85
110
  this.config = config;
86
111
  this.session = inject(AXPSessionService);
87
112
  this.dispatcher = inject(AXPRealtimeDispatcherService);
@@ -95,11 +120,11 @@ class AXPRealtimeConnectionService {
95
120
  return;
96
121
  }
97
122
  this.statusSub = this.session.status$.subscribe((status) => {
98
- if (status === AXPSessionStatus.Authenticated || status === AXPSessionStatus.Authorized) {
123
+ if (status === AXPSessionStatus.Authorized) {
99
124
  this.connect();
100
125
  }
101
126
  else {
102
- this.disconnect();
127
+ void this.leaveAndDisconnect();
103
128
  }
104
129
  });
105
130
  }
@@ -107,10 +132,14 @@ class AXPRealtimeConnectionService {
107
132
  this.statusSub?.unsubscribe();
108
133
  this.disconnect();
109
134
  }
135
+ /** Sign-out: tell the server to skip grace, then close the socket. */
136
+ async leaveAndDisconnect() {
137
+ await this.leavePresence();
138
+ this.disconnect();
139
+ }
110
140
  connect() {
111
- const token = this.session.getToken()?.trim();
112
141
  const url = this.config?.url?.trim();
113
- if (!token || !url) {
142
+ if (!url || !this.session.hasSessionCredentials()) {
114
143
  this.connectionStatusSubject.next('disconnected');
115
144
  return;
116
145
  }
@@ -122,9 +151,10 @@ class AXPRealtimeConnectionService {
122
151
  return;
123
152
  }
124
153
  this.connectionStatusSubject.next('connecting');
154
+ // Auth uses HttpOnly access cookie (same-site / proxied); no token in JS.
125
155
  this.socket = io(url, {
126
156
  transports: ['websocket', 'polling'],
127
- auth: { token },
157
+ withCredentials: true,
128
158
  autoConnect: true,
129
159
  reconnection: true,
130
160
  });
@@ -177,10 +207,57 @@ class AXPRealtimeConnectionService {
177
207
  this.joinedConversations.delete(id);
178
208
  this.socket?.emit(AXP_REALTIME_UNSUBSCRIBE_CONVERSATION, { conversationId: id });
179
209
  }
180
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPRealtimeConnectionService, deps: [{ token: AXP_REALTIME_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
181
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPRealtimeConnectionService }); }
210
+ emitConversationTyping(conversationId, active) {
211
+ const id = conversationId?.trim();
212
+ if (!id || !this.socket?.connected) {
213
+ return;
214
+ }
215
+ this.socket.emit(AXP_REALTIME_EMIT_TYPING, { conversationId: id, active });
216
+ }
217
+ subscribePresence(userIds) {
218
+ const ids = userIds.map((id) => id.trim()).filter(Boolean);
219
+ if (ids.length === 0 || !this.socket?.connected) {
220
+ return Promise.resolve([]);
221
+ }
222
+ return new Promise((resolve) => {
223
+ this.socket?.emit(AXP_REALTIME_SUBSCRIBE_PRESENCE, { userIds: ids }, (result) => {
224
+ resolve(Array.isArray(result?.items) ? result.items : []);
225
+ });
226
+ });
227
+ }
228
+ unsubscribePresence(userIds) {
229
+ const ids = userIds.map((id) => id.trim()).filter(Boolean);
230
+ if (ids.length === 0) {
231
+ return;
232
+ }
233
+ this.socket?.emit(AXP_REALTIME_UNSUBSCRIBE_PRESENCE, { userIds: ids });
234
+ }
235
+ leavePresence() {
236
+ if (!this.socket?.connected) {
237
+ return Promise.resolve();
238
+ }
239
+ return new Promise((resolve) => {
240
+ const timer = setTimeout(resolve, 400);
241
+ this.socket?.emit(AXP_REALTIME_PRESENCE_LEAVE, {}, () => {
242
+ clearTimeout(timer);
243
+ resolve();
244
+ });
245
+ });
246
+ }
247
+ setPresence(status, source = 'manual') {
248
+ if (!this.socket?.connected) {
249
+ return Promise.resolve(undefined);
250
+ }
251
+ return new Promise((resolve) => {
252
+ this.socket?.emit(AXP_REALTIME_PRESENCE_SET, { status, source }, (result) => {
253
+ resolve(result?.ok ? result.item : undefined);
254
+ });
255
+ });
256
+ }
257
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPRealtimeConnectionService, deps: [{ token: AXP_REALTIME_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
258
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPRealtimeConnectionService }); }
182
259
  }
183
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPRealtimeConnectionService, decorators: [{
260
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPRealtimeConnectionService, decorators: [{
184
261
  type: Injectable
185
262
  }], ctorParameters: () => [{ type: undefined, decorators: [{
186
263
  type: Optional
@@ -189,8 +266,313 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
189
266
  args: [AXP_REALTIME_CONFIG]
190
267
  }] }] });
191
268
 
192
- //#region ---- provideRealtime ----
269
+ //#region ----- Constants -----
270
+ /** Idle without input before automatic Away. Keep in sync with server `AXP_USER_PRESENCE_IDLE_MS`. */
271
+ const AXP_USER_PRESENCE_IDLE_MS = 5 * 60_000;
272
+ //#endregion
273
+
274
+ //#region ----- Presence helpers -----
275
+ const PRESENCE_STATUSES = ['online', 'offline', 'away', 'busy'];
276
+ function isWatchablePresenceUserId(userId) {
277
+ const id = userId?.trim() ?? '';
278
+ if (!id || id === 'system') {
279
+ return false;
280
+ }
281
+ return !id.startsWith('assist-');
282
+ }
283
+ function parseUserPresencePayload(payload) {
284
+ if (!payload || typeof payload !== 'object') {
285
+ return null;
286
+ }
287
+ const raw = payload;
288
+ const userId = raw.userId?.trim();
289
+ if (!userId) {
290
+ return null;
291
+ }
292
+ const status = PRESENCE_STATUSES.includes(raw.status) ? raw.status : 'offline';
293
+ const lastSeen = typeof raw.lastSeen === 'string' && raw.lastSeen.trim() ? raw.lastSeen.trim() : undefined;
294
+ const since = typeof raw.since === 'string' && raw.since.trim() ? raw.since.trim() : undefined;
295
+ const source = raw.source === 'auto' || raw.source === 'manual' ? raw.source : undefined;
296
+ return {
297
+ userId,
298
+ status,
299
+ ...(lastSeen ? { lastSeen } : {}),
300
+ ...(since ? { since } : {}),
301
+ ...(source ? { source } : {}),
302
+ };
303
+ }
304
+ //#endregion
305
+
306
+ //#region ----- User presence store -----
307
+ const FLUSH_DEBOUNCE_MS = 40;
308
+ class AXPUserPresenceService {
309
+ //#endregion
310
+ constructor() {
311
+ //#region ----- Services & Dependencies -----
312
+ this.connection = inject(AXPRealtimeConnectionService, { optional: true });
313
+ //#endregion
314
+ //#region ----- State -----
315
+ this.presenceByUserId = new Map();
316
+ this.watchCounts = new Map();
317
+ this.subjects = new Map();
318
+ this.updatesSubject = new Subject();
319
+ this.flushTimer = null;
320
+ this.pendingSubscribe = new Set();
321
+ this.pendingUnsubscribe = new Set();
322
+ this.updates$ = this.updatesSubject.asObservable();
323
+ this.connection?.connectionStatus$.subscribe((status) => {
324
+ if (status === 'connected') {
325
+ this.resubscribeAll();
326
+ }
327
+ });
328
+ }
329
+ //#region ----- Public API -----
330
+ get(userId) {
331
+ const id = userId?.trim();
332
+ if (!id) {
333
+ return undefined;
334
+ }
335
+ return this.presenceByUserId.get(id);
336
+ }
337
+ presence$(userId) {
338
+ const id = userId?.trim();
339
+ const fallback = { userId: id, status: 'offline' };
340
+ if (!id) {
341
+ return new BehaviorSubject(fallback).asObservable();
342
+ }
343
+ let subject = this.subjects.get(id);
344
+ if (!subject) {
345
+ subject = new BehaviorSubject(this.presenceByUserId.get(id) ?? fallback);
346
+ this.subjects.set(id, subject);
347
+ }
348
+ return subject.asObservable();
349
+ }
350
+ watch(userId) {
351
+ if (!isWatchablePresenceUserId(userId)) {
352
+ return;
353
+ }
354
+ const id = userId.trim();
355
+ const next = (this.watchCounts.get(id) ?? 0) + 1;
356
+ this.watchCounts.set(id, next);
357
+ if (next === 1) {
358
+ this.pendingUnsubscribe.delete(id);
359
+ this.pendingSubscribe.add(id);
360
+ this.scheduleFlush();
361
+ }
362
+ }
363
+ watchMany(userIds) {
364
+ for (const userId of userIds) {
365
+ this.watch(userId);
366
+ }
367
+ }
368
+ /** Watch only if this user is not already in the local watch set. */
369
+ ensureWatch(userId) {
370
+ const id = userId?.trim();
371
+ if (!id || (this.watchCounts.get(id) ?? 0) > 0) {
372
+ return;
373
+ }
374
+ this.watch(id);
375
+ }
376
+ ensureWatchMany(userIds) {
377
+ for (const userId of userIds) {
378
+ this.ensureWatch(userId);
379
+ }
380
+ }
381
+ unwatch(userId) {
382
+ const id = userId?.trim();
383
+ if (!id) {
384
+ return;
385
+ }
386
+ const current = this.watchCounts.get(id) ?? 0;
387
+ if (current <= 1) {
388
+ this.watchCounts.delete(id);
389
+ this.pendingSubscribe.delete(id);
390
+ this.pendingUnsubscribe.add(id);
391
+ this.scheduleFlush();
392
+ return;
393
+ }
394
+ this.watchCounts.set(id, current - 1);
395
+ }
396
+ applySnapshot(items) {
397
+ for (const item of items) {
398
+ this.applyPresence(item);
399
+ }
400
+ }
401
+ applyEnvelopePayload(payload) {
402
+ const parsed = parseUserPresencePayload(payload);
403
+ if (parsed) {
404
+ this.applyPresence(parsed);
405
+ }
406
+ }
407
+ async setAvailability(status, source = 'manual') {
408
+ const item = await this.connection?.setPresence(status, source);
409
+ if (item) {
410
+ this.applyPresence(item);
411
+ }
412
+ }
413
+ //#endregion
414
+ //#region ----- Store updates -----
415
+ applyPresence(presence) {
416
+ const previous = this.presenceByUserId.get(presence.userId);
417
+ if (previous &&
418
+ previous.status === presence.status &&
419
+ previous.lastSeen === presence.lastSeen &&
420
+ previous.since === presence.since) {
421
+ return;
422
+ }
423
+ this.presenceByUserId.set(presence.userId, presence);
424
+ const subject = this.subjects.get(presence.userId);
425
+ if (subject && !subject.closed) {
426
+ subject.next(presence);
427
+ }
428
+ this.updatesSubject.next(presence);
429
+ }
430
+ scheduleFlush() {
431
+ if (this.flushTimer) {
432
+ return;
433
+ }
434
+ this.flushTimer = setTimeout(() => {
435
+ this.flushTimer = null;
436
+ void this.flush();
437
+ }, FLUSH_DEBOUNCE_MS);
438
+ }
439
+ async flush() {
440
+ const subscribeIds = Array.from(this.pendingSubscribe);
441
+ const unsubscribeIds = Array.from(this.pendingUnsubscribe);
442
+ this.pendingSubscribe.clear();
443
+ this.pendingUnsubscribe.clear();
444
+ if (unsubscribeIds.length > 0) {
445
+ this.connection?.unsubscribePresence(unsubscribeIds);
446
+ }
447
+ if (subscribeIds.length === 0) {
448
+ return;
449
+ }
450
+ const items = (await this.connection?.subscribePresence(subscribeIds)) ?? [];
451
+ this.applySnapshot(items);
452
+ }
453
+ resubscribeAll() {
454
+ const watched = Array.from(this.watchCounts.keys());
455
+ if (watched.length === 0) {
456
+ return;
457
+ }
458
+ this.pendingUnsubscribe.clear();
459
+ for (const id of watched) {
460
+ this.pendingSubscribe.add(id);
461
+ }
462
+ this.scheduleFlush();
463
+ }
464
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserPresenceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
465
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserPresenceService, providedIn: 'root' }); }
466
+ }
467
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserPresenceService, decorators: [{
468
+ type: Injectable,
469
+ args: [{ providedIn: 'root' }]
470
+ }], ctorParameters: () => [] });
471
+
472
+ //#region ----- Automatic away from idle -----
473
+ const IDLE_CHECK_MS = 15_000;
474
+ const ACTIVITY_THROTTLE_MS = 1_000;
475
+ class AXPUserPresenceIdleService {
476
+ //#endregion
477
+ constructor() {
478
+ //#region ----- Services & Dependencies -----
479
+ this.document = inject(DOCUMENT);
480
+ this.session = inject(AXPSessionService);
481
+ this.presence = inject(AXPUserPresenceService);
482
+ this.destroyRef = inject(DestroyRef);
483
+ //#endregion
484
+ //#region ----- State -----
485
+ this.lastActivityAt = Date.now();
486
+ this.lastActivityEmitAt = 0;
487
+ this.idle = false;
488
+ this.checkTimer = null;
489
+ this.started = false;
490
+ //#endregion
491
+ //#region ----- Activity -----
492
+ this.onActivity = () => {
493
+ const now = Date.now();
494
+ this.lastActivityAt = now;
495
+ if (now - this.lastActivityEmitAt < ACTIVITY_THROTTLE_MS) {
496
+ return;
497
+ }
498
+ this.lastActivityEmitAt = now;
499
+ if (this.idle) {
500
+ this.idle = false;
501
+ void this.presence.setAvailability('online', 'auto');
502
+ }
503
+ };
504
+ this.onVisibility = () => {
505
+ if (!this.document.hidden) {
506
+ this.onActivity();
507
+ }
508
+ };
509
+ this.session.status$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((status) => {
510
+ if (status === AXPSessionStatus.Authorized) {
511
+ this.start();
512
+ return;
513
+ }
514
+ this.stop();
515
+ });
516
+ }
517
+ //#region ----- Lifecycle -----
518
+ start() {
519
+ if (this.started) {
520
+ return;
521
+ }
522
+ this.started = true;
523
+ this.lastActivityAt = Date.now();
524
+ this.idle = false;
525
+ const target = this.document.defaultView ?? this.document;
526
+ target.addEventListener('mousemove', this.onActivity, { passive: true });
527
+ target.addEventListener('keydown', this.onActivity, { passive: true });
528
+ target.addEventListener('mousedown', this.onActivity, { passive: true });
529
+ target.addEventListener('touchstart', this.onActivity, { passive: true });
530
+ this.document.addEventListener('visibilitychange', this.onVisibility);
531
+ this.checkTimer = setInterval(() => this.checkIdle(), IDLE_CHECK_MS);
532
+ }
533
+ stop() {
534
+ if (!this.started) {
535
+ return;
536
+ }
537
+ this.started = false;
538
+ this.idle = false;
539
+ const target = this.document.defaultView ?? this.document;
540
+ target.removeEventListener('mousemove', this.onActivity);
541
+ target.removeEventListener('keydown', this.onActivity);
542
+ target.removeEventListener('mousedown', this.onActivity);
543
+ target.removeEventListener('touchstart', this.onActivity);
544
+ this.document.removeEventListener('visibilitychange', this.onVisibility);
545
+ if (this.checkTimer) {
546
+ clearInterval(this.checkTimer);
547
+ this.checkTimer = null;
548
+ }
549
+ }
550
+ checkIdle() {
551
+ if (!this.started || this.idle) {
552
+ return;
553
+ }
554
+ if (Date.now() - this.lastActivityAt < AXP_USER_PRESENCE_IDLE_MS) {
555
+ return;
556
+ }
557
+ this.idle = true;
558
+ void this.presence.setAvailability('away', 'auto');
559
+ }
560
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserPresenceIdleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
561
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserPresenceIdleService, providedIn: 'root' }); }
562
+ }
563
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserPresenceIdleService, decorators: [{
564
+ type: Injectable,
565
+ args: [{ providedIn: 'root' }]
566
+ }], ctorParameters: () => [] });
567
+
568
+ /**
569
+ * Registers built-in always-on realtime (Socket.IO) + topic dispatcher.
570
+ */
193
571
  function provideRealtime(config = {}) {
572
+ const backend = config.backend ?? 'builtin';
573
+ if (backend !== 'builtin') {
574
+ throw new Error(`Unsupported realtime backend '${String(backend)}'. Use 'builtin'.`);
575
+ }
194
576
  const url = config.url?.trim() ||
195
577
  (config.apiBaseUrl?.trim() ? resolveRealtimeSocketUrl(config.apiBaseUrl) : undefined);
196
578
  return makeEnvironmentProviders([
@@ -204,24 +586,79 @@ function provideRealtime(config = {}) {
204
586
  AXPRealtimeDispatcherService,
205
587
  AXPRealtimeConnectionService,
206
588
  {
207
- provide: APP_INITIALIZER,
208
- multi: true,
209
- useFactory: () => {
210
- const connection = inject(AXPRealtimeConnectionService);
211
- return () => {
212
- // Connection lifecycle is owned by AXPRealtimeConnectionService (session.status$).
589
+ provide: AXPRealtimeConnectionPort,
590
+ useExisting: AXPRealtimeConnectionService,
591
+ },
592
+ provideCommandSetups([
593
+ {
594
+ key: PRESENCE_SET_AVAILABILITY,
595
+ command: () => import('./acorex-platform-framework-client-realtime-set-presence-availability.command-CetlUjnM.mjs').then((c) => c.AXPSetPresenceAvailabilityCommand),
596
+ },
597
+ ]),
598
+ provideAppStartUpTask(() => {
599
+ inject(AXPUserPresenceIdleService);
600
+ return {
601
+ name: 'user-presence-idle',
602
+ priority: AXP_APP_STARTUP_PRIORITY.realtimeSubscriptions,
603
+ run: async () => undefined,
604
+ };
605
+ }),
606
+ provideAppStartUpTask(() => {
607
+ const dispatcher = inject(AXPRealtimeDispatcherService);
608
+ const presence = inject(AXPUserPresenceService);
609
+ return {
610
+ name: 'user-presence-handler',
611
+ priority: AXP_APP_STARTUP_PRIORITY.realtimeHandlers,
612
+ run: async () => {
613
+ dispatcher.register({
614
+ topic: AXP_REALTIME_TOPIC_USER_PRESENCE,
615
+ handle: (envelope) => {
616
+ presence.applyEnvelopePayload(envelope.payload);
617
+ },
618
+ });
619
+ },
620
+ };
621
+ }),
622
+ provideAppStartUpTask(() => {
623
+ const connection = inject(AXPRealtimeConnectionPort);
624
+ return {
625
+ name: 'realtime-connect',
626
+ priority: AXP_APP_STARTUP_PRIORITY.realtimeConnect,
627
+ run: async () => {
628
+ // Connection lifecycle is owned by the connection service (session.status$).
213
629
  // Eagerly invoke connect once so an already-authenticated session connects on bootstrap.
214
630
  connection.connect();
215
- };
216
- },
217
- },
631
+ },
632
+ };
633
+ }),
218
634
  ]);
219
635
  }
220
636
  //#endregion
221
637
 
638
+ //#endregion
639
+
640
+ //#region ----- Presence duration tooltip -----
641
+ function presenceDurationBucket(ms) {
642
+ const elapsed = Math.max(0, ms);
643
+ if (elapsed < 60_000) {
644
+ return { key: 'duration.less-than-a-minute' };
645
+ }
646
+ const minutes = Math.floor(elapsed / 60_000);
647
+ if (minutes < 60) {
648
+ return minutes === 1 ? { key: 'duration.one-minute' } : { key: 'duration.minutes', params: { count: minutes } };
649
+ }
650
+ const hours = Math.floor(minutes / 60);
651
+ if (hours < 24) {
652
+ return hours === 1 ? { key: 'duration.one-hour' } : { key: 'duration.hours', params: { count: hours } };
653
+ }
654
+ const days = Math.floor(hours / 24);
655
+ return days === 1 ? { key: 'duration.one-day' } : { key: 'duration.days', params: { count: days } };
656
+ }
657
+ //#endregion
658
+
222
659
  /**
223
660
  * Generated bundle index. Do not edit.
224
661
  */
225
662
 
226
- export { AXPRealtimeConnectionService, AXPRealtimeDispatcherService, AXP_REALTIME_CONFIG, AXP_REALTIME_SOCKET_EVENT, AXP_REALTIME_SUBSCRIBE_CONVERSATION, AXP_REALTIME_TOPIC_CONVERSATION_MESSAGE, AXP_REALTIME_TOPIC_ENTITY_MUTATION, AXP_REALTIME_TOPIC_HANDLER, AXP_REALTIME_TOPIC_INBOX_REFRESH, AXP_REALTIME_UNSUBSCRIBE_CONVERSATION, provideRealtime, resolveRealtimeSocketUrl };
663
+ export { AXPRealtimeConnectionPort, AXPRealtimeConnectionService, AXPRealtimeDispatcherService, AXPUserPresenceIdleService, AXPUserPresenceService, AXP_REALTIME_CONFIG, AXP_REALTIME_EMIT_TYPING, AXP_REALTIME_PRESENCE_LEAVE, AXP_REALTIME_PRESENCE_SET, AXP_REALTIME_SOCKET_EVENT, AXP_REALTIME_SUBSCRIBE_CONVERSATION, AXP_REALTIME_SUBSCRIBE_PRESENCE, AXP_REALTIME_TOPIC_CONVERSATION_CALL, AXP_REALTIME_TOPIC_CONVERSATION_MESSAGE, AXP_REALTIME_TOPIC_CONVERSATION_TYPING, AXP_REALTIME_TOPIC_ENTITY_MUTATION, AXP_REALTIME_TOPIC_HANDLER, AXP_REALTIME_TOPIC_INBOX_REFRESH, AXP_REALTIME_TOPIC_USER_PRESENCE, AXP_REALTIME_UNSUBSCRIBE_CONVERSATION, AXP_REALTIME_UNSUBSCRIBE_PRESENCE, AXP_USER_PRESENCE_IDLE_MS, isWatchablePresenceUserId, parseUserPresencePayload, presenceDurationBucket, provideRealtime, resolveRealtimeSocketUrl };
227
664
  //# sourceMappingURL=acorex-platform-framework-client-realtime.mjs.map