stream-chat-angular 4.66.1 → 5.0.0-v5.1

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 (157) hide show
  1. package/assets/version.d.ts +1 -1
  2. package/{esm2015/assets/version.js → esm2020/assets/version.mjs} +2 -2
  3. package/esm2020/lib/attachment-configuration.service.mjs +185 -0
  4. package/esm2020/lib/attachment-list/attachment-list.component.mjs +205 -0
  5. package/esm2020/lib/attachment-preview-list/attachment-preview-list.component.mjs +45 -0
  6. package/esm2020/lib/attachment.service.mjs +262 -0
  7. package/esm2020/lib/avatar/avatar.component.mjs +163 -0
  8. package/esm2020/lib/avatar-placeholder/avatar-placeholder.component.mjs +74 -0
  9. package/esm2020/lib/channel/channel.component.mjs +46 -0
  10. package/esm2020/lib/channel-header/channel-header.component.mjs +79 -0
  11. package/esm2020/lib/channel-list/channel-list-toggle.service.mjs +72 -0
  12. package/esm2020/lib/channel-list/channel-list.component.mjs +60 -0
  13. package/esm2020/lib/channel-preview/channel-preview.component.mjs +155 -0
  14. package/esm2020/lib/channel.service.mjs +1460 -0
  15. package/esm2020/lib/chat-client.service.mjs +206 -0
  16. package/{esm2015/lib/custom-templates.service.js → esm2020/lib/custom-templates.service.mjs} +3 -3
  17. package/{esm2015/lib/date-parser.service.js → esm2020/lib/date-parser.service.mjs} +3 -3
  18. package/esm2020/lib/edit-message-form/edit-message-form.component.mjs +83 -0
  19. package/esm2020/lib/get-channel-display-text.mjs +14 -0
  20. package/esm2020/lib/get-message-translation.mjs +12 -0
  21. package/esm2020/lib/icon/icon.component.mjs +21 -0
  22. package/esm2020/lib/icon-placeholder/icon-placeholder.component.mjs +31 -0
  23. package/esm2020/lib/loading-indicator/loading-indicator.component.mjs +31 -0
  24. package/esm2020/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.mjs +38 -0
  25. package/esm2020/lib/message/message.component.mjs +422 -0
  26. package/esm2020/lib/message-actions-box/message-actions-box.component.mjs +130 -0
  27. package/esm2020/lib/message-actions.service.mjs +119 -0
  28. package/esm2020/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +71 -0
  29. package/esm2020/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +262 -0
  30. package/{esm2015/lib/message-input/emoji-input.service.js → esm2020/lib/message-input/emoji-input.service.mjs} +3 -3
  31. package/{esm2015/lib/message-input/message-input-config.service.js → esm2020/lib/message-input/message-input-config.service.mjs} +3 -3
  32. package/esm2020/lib/message-input/message-input.component.mjs +443 -0
  33. package/{esm2015/lib/message-input/textarea/textarea.component.js → esm2020/lib/message-input/textarea/textarea.component.mjs} +5 -9
  34. package/esm2020/lib/message-input/textarea.directive.mjs +89 -0
  35. package/esm2020/lib/message-list/group-styles.mjs +52 -0
  36. package/{esm2015/lib/message-list/image-load.service.js → esm2020/lib/message-list/image-load.service.mjs} +3 -3
  37. package/esm2020/lib/message-list/message-list.component.mjs +699 -0
  38. package/esm2020/lib/message-preview.mjs +21 -0
  39. package/esm2020/lib/message-reactions/message-reactions.component.mjs +255 -0
  40. package/{esm2015/lib/message-reactions.service.js → esm2020/lib/message-reactions.service.mjs} +3 -3
  41. package/{esm2015/lib/message.service.js → esm2020/lib/message.service.mjs} +4 -4
  42. package/esm2020/lib/modal/modal.component.mjs +69 -0
  43. package/esm2020/lib/notification/notification.component.mjs +20 -0
  44. package/esm2020/lib/notification-list/notification-list.component.mjs +37 -0
  45. package/esm2020/lib/notification.service.mjs +79 -0
  46. package/esm2020/lib/read-by.mjs +12 -0
  47. package/{esm2015/lib/stream-autocomplete-textarea.module.js → esm2020/lib/stream-autocomplete-textarea.module.mjs} +6 -6
  48. package/{esm2015/lib/stream-avatar.module.js → esm2020/lib/stream-avatar.module.mjs} +5 -5
  49. package/{esm2015/lib/stream-chat.module.js → esm2020/lib/stream-chat.module.mjs} +8 -10
  50. package/{esm2015/lib/stream-i18n.service.js → esm2020/lib/stream-i18n.service.mjs} +5 -5
  51. package/{esm2015/lib/stream-textarea.module.js → esm2020/lib/stream-textarea.module.mjs} +6 -6
  52. package/esm2020/lib/theme.service.mjs +123 -0
  53. package/esm2020/lib/thread/thread.component.mjs +51 -0
  54. package/{esm2015/lib/transliteration.service.js → esm2020/lib/transliteration.service.mjs} +3 -3
  55. package/esm2020/lib/types.mjs +2 -0
  56. package/esm2020/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +183 -0
  57. package/esm2020/lib/voice-recording/voice-recording.component.mjs +102 -0
  58. package/fesm2015/{stream-chat-angular.js → stream-chat-angular.mjs} +304 -412
  59. package/fesm2015/stream-chat-angular.mjs.map +1 -0
  60. package/fesm2020/stream-chat-angular.mjs +7128 -0
  61. package/fesm2020/stream-chat-angular.mjs.map +1 -0
  62. package/lib/attachment-list/attachment-list.component.d.ts +3 -3
  63. package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +1 -1
  64. package/lib/attachment.service.d.ts +0 -1
  65. package/lib/avatar/avatar.component.d.ts +1 -1
  66. package/lib/avatar-placeholder/avatar-placeholder.component.d.ts +1 -1
  67. package/lib/channel/channel.component.d.ts +1 -1
  68. package/lib/channel-header/channel-header.component.d.ts +1 -1
  69. package/lib/channel-list/channel-list-toggle.service.d.ts +0 -1
  70. package/lib/channel-list/channel-list.component.d.ts +1 -1
  71. package/lib/channel-preview/channel-preview.component.d.ts +1 -1
  72. package/lib/channel.service.d.ts +7 -7
  73. package/lib/chat-client.service.d.ts +1 -1
  74. package/lib/edit-message-form/edit-message-form.component.d.ts +1 -1
  75. package/lib/get-message-translation.d.ts +1 -1
  76. package/lib/icon/icon.component.d.ts +1 -1
  77. package/lib/icon-placeholder/icon-placeholder.component.d.ts +1 -1
  78. package/lib/loading-indicator/loading-indicator.component.d.ts +1 -1
  79. package/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.d.ts +1 -1
  80. package/lib/message/message.component.d.ts +1 -2
  81. package/lib/message-actions-box/message-actions-box.component.d.ts +2 -4
  82. package/lib/message-actions.service.d.ts +0 -1
  83. package/lib/message-bounce-prompt/message-bounce-prompt.component.d.ts +1 -1
  84. package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +1 -1
  85. package/lib/message-input/message-input.component.d.ts +2 -2
  86. package/lib/message-input/textarea/textarea.component.d.ts +1 -1
  87. package/lib/message-input/textarea.directive.d.ts +1 -1
  88. package/lib/message-list/group-styles.d.ts +1 -1
  89. package/lib/message-list/message-list.component.d.ts +4 -5
  90. package/lib/message-reactions/message-reactions.component.d.ts +1 -1
  91. package/lib/message.service.d.ts +0 -1
  92. package/lib/modal/modal.component.d.ts +1 -1
  93. package/lib/notification/notification.component.d.ts +1 -1
  94. package/lib/notification-list/notification-list.component.d.ts +2 -2
  95. package/lib/notification.service.d.ts +2 -5
  96. package/lib/theme.service.d.ts +1 -2
  97. package/lib/thread/thread.component.d.ts +1 -1
  98. package/lib/types.d.ts +18 -18
  99. package/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.d.ts +2 -2
  100. package/lib/voice-recording/voice-recording.component.d.ts +1 -1
  101. package/package.json +28 -15
  102. package/src/assets/version.ts +1 -1
  103. package/bundles/stream-chat-angular.umd.js +0 -8445
  104. package/bundles/stream-chat-angular.umd.js.map +0 -1
  105. package/esm2015/lib/attachment-configuration.service.js +0 -186
  106. package/esm2015/lib/attachment-list/attachment-list.component.js +0 -209
  107. package/esm2015/lib/attachment-preview-list/attachment-preview-list.component.js +0 -49
  108. package/esm2015/lib/attachment.service.js +0 -276
  109. package/esm2015/lib/avatar/avatar.component.js +0 -172
  110. package/esm2015/lib/avatar-placeholder/avatar-placeholder.component.js +0 -78
  111. package/esm2015/lib/channel/channel.component.js +0 -50
  112. package/esm2015/lib/channel-header/channel-header.component.js +0 -86
  113. package/esm2015/lib/channel-list/channel-list-toggle.service.js +0 -73
  114. package/esm2015/lib/channel-list/channel-list.component.js +0 -67
  115. package/esm2015/lib/channel-preview/channel-preview.component.js +0 -167
  116. package/esm2015/lib/channel.service.js +0 -1487
  117. package/esm2015/lib/chat-client.service.js +0 -211
  118. package/esm2015/lib/edit-message-form/edit-message-form.component.js +0 -87
  119. package/esm2015/lib/get-channel-display-text.js +0 -15
  120. package/esm2015/lib/get-message-translation.js +0 -13
  121. package/esm2015/lib/icon/icon.component.js +0 -25
  122. package/esm2015/lib/icon-placeholder/icon-placeholder.component.js +0 -35
  123. package/esm2015/lib/loading-indicator/loading-indicator.component.js +0 -35
  124. package/esm2015/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.js +0 -42
  125. package/esm2015/lib/message/message.component.js +0 -436
  126. package/esm2015/lib/message-actions-box/message-actions-box.component.js +0 -137
  127. package/esm2015/lib/message-actions.service.js +0 -114
  128. package/esm2015/lib/message-bounce-prompt/message-bounce-prompt.component.js +0 -80
  129. package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +0 -262
  130. package/esm2015/lib/message-input/message-input.component.js +0 -455
  131. package/esm2015/lib/message-input/textarea.directive.js +0 -90
  132. package/esm2015/lib/message-list/group-styles.js +0 -53
  133. package/esm2015/lib/message-list/message-list.component.js +0 -726
  134. package/esm2015/lib/message-preview.js +0 -7
  135. package/esm2015/lib/message-reactions/message-reactions.component.js +0 -266
  136. package/esm2015/lib/modal/modal.component.js +0 -74
  137. package/esm2015/lib/notification/notification.component.js +0 -24
  138. package/esm2015/lib/notification-list/notification-list.component.js +0 -38
  139. package/esm2015/lib/notification.service.js +0 -79
  140. package/esm2015/lib/read-by.js +0 -13
  141. package/esm2015/lib/theme.service.js +0 -122
  142. package/esm2015/lib/thread/thread.component.js +0 -55
  143. package/esm2015/lib/types.js +0 -2
  144. package/esm2015/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.js +0 -192
  145. package/esm2015/lib/voice-recording/voice-recording.component.js +0 -115
  146. package/fesm2015/stream-chat-angular.js.map +0 -1
  147. /package/{esm2015/assets/i18n/en.js → esm2020/assets/i18n/en.mjs} +0 -0
  148. /package/{esm2015/lib/injection-tokens.js → esm2020/lib/injection-tokens.mjs} +0 -0
  149. /package/{esm2015/lib/is-image-attachment.js → esm2020/lib/is-image-attachment.mjs} +0 -0
  150. /package/{esm2015/lib/is-image-file.js → esm2020/lib/is-image-file.mjs} +0 -0
  151. /package/{esm2015/lib/is-on-separate-date.js → esm2020/lib/is-on-separate-date.mjs} +0 -0
  152. /package/{esm2015/lib/list-users.js → esm2020/lib/list-users.mjs} +0 -0
  153. /package/{esm2015/lib/message-input/textarea.interface.js → esm2020/lib/message-input/textarea.interface.mjs} +0 -0
  154. /package/{esm2015/lib/parse-date.js → esm2020/lib/parse-date.mjs} +0 -0
  155. /package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
  156. /package/{esm2015/stream-chat-angular.js → esm2020/stream-chat-angular.mjs} +0 -0
  157. /package/{stream-chat-angular.d.ts → index.d.ts} +0 -0
@@ -1,115 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { Component, Input, ViewChild, } from '@angular/core';
3
- import prettybytes from 'pretty-bytes';
4
- import * as i0 from "@angular/core";
5
- import * as i1 from "../icon-placeholder/icon-placeholder.component";
6
- import * as i2 from "./voice-recording-wavebar/voice-recording-wavebar.component";
7
- import * as i3 from "@angular/common";
8
- import * as i4 from "@ngx-translate/core";
9
- /**
10
- * This component can be used to display an attachment with type `voiceRecording`. The component allows playing the attachment inside the browser.
11
- */
12
- export class VoiceRecordingComponent {
13
- constructor(ngZone, cdRef) {
14
- this.ngZone = ngZone;
15
- this.cdRef = cdRef;
16
- this.fileSize = '';
17
- this.durationFormatted = '';
18
- this.secondsElapsed = 0;
19
- this.isError = false;
20
- this.secondsElapsedFormatted = this.getFormattedDuration(this.secondsElapsed);
21
- }
22
- ngOnChanges(changes) {
23
- var _a;
24
- if (changes.attachment) {
25
- this.fileSize = this.getFileSize();
26
- this.durationFormatted = this.getFormattedDuration((_a = this.attachment) === null || _a === void 0 ? void 0 : _a.duration);
27
- }
28
- }
29
- ngAfterViewInit() {
30
- // timeupdate fired frequntly so we optimize change detections
31
- this.ngZone.runOutsideAngular(() => {
32
- var _a;
33
- (_a = this.audioElement) === null || _a === void 0 ? void 0 : _a.nativeElement.addEventListener('timeupdate', () => {
34
- var _a, _b, _c, _d, _e;
35
- const secondsElapsed = ((_b = (_a = this.audioElement) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.ended)
36
- ? ((_c = this.attachment) === null || _c === void 0 ? void 0 : _c.duration) || 0
37
- : Math.round(((_e = (_d = this.audioElement) === null || _d === void 0 ? void 0 : _d.nativeElement) === null || _e === void 0 ? void 0 : _e.currentTime) || 0);
38
- if (this.secondsElapsed !== secondsElapsed) {
39
- this.ngZone.run(() => {
40
- this.secondsElapsed = secondsElapsed;
41
- this.secondsElapsedFormatted = this.getFormattedDuration(this.secondsElapsed);
42
- this.cdRef.detectChanges();
43
- });
44
- }
45
- });
46
- });
47
- }
48
- togglePlay() {
49
- var _a, _b;
50
- return __awaiter(this, void 0, void 0, function* () {
51
- if (!this.audioElement || !((_a = this.attachment) === null || _a === void 0 ? void 0 : _a.asset_url)) {
52
- return;
53
- }
54
- try {
55
- ((_b = this.audioElement) === null || _b === void 0 ? void 0 : _b.nativeElement.paused)
56
- ? yield this.audioElement.nativeElement.play()
57
- : this.audioElement.nativeElement.pause();
58
- this.isError = false;
59
- }
60
- catch (e) {
61
- this.isError = true;
62
- }
63
- });
64
- }
65
- setPlaybackRate() {
66
- var _a, _b, _c;
67
- if (!((_a = this.audioElement) === null || _a === void 0 ? void 0 : _a.nativeElement)) {
68
- return;
69
- }
70
- let playbackRate = ((_c = (_b = this.audioElement) === null || _b === void 0 ? void 0 : _b.nativeElement) === null || _c === void 0 ? void 0 : _c.playbackRate) + 0.5;
71
- if (playbackRate > 2) {
72
- playbackRate = 1;
73
- }
74
- this.audioElement.nativeElement.playbackRate = playbackRate;
75
- }
76
- getFormattedDuration(duration) {
77
- if (duration === undefined || duration <= 0)
78
- return '00:00';
79
- const [hours, hoursLeftover] = this.divMod(duration, 3600);
80
- const [minutes, seconds] = this.divMod(hoursLeftover, 60);
81
- const roundedSeconds = Math.ceil(seconds);
82
- const prependHrsZero = hours.toString().length === 1 ? '0' : '';
83
- const prependMinZero = minutes.toString().length === 1 ? '0' : '';
84
- const prependSecZero = roundedSeconds.toString().length === 1 ? '0' : '';
85
- const minSec = `${prependMinZero}${minutes}:${prependSecZero}${roundedSeconds}`;
86
- return hours ? `${prependHrsZero}${hours}:` + minSec : minSec;
87
- }
88
- getFileSize() {
89
- var _a, _b;
90
- if (((_a = this.attachment) === null || _a === void 0 ? void 0 : _a.file_size) === undefined ||
91
- ((_b = this.attachment) === null || _b === void 0 ? void 0 : _b.file_size) === null) {
92
- return '';
93
- }
94
- return prettybytes(Number(this.attachment.file_size || 0));
95
- }
96
- divMod(num, divisor) {
97
- return [Math.floor(num / divisor), num % divisor];
98
- }
99
- }
100
- VoiceRecordingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: VoiceRecordingComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
101
- VoiceRecordingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: VoiceRecordingComponent, selector: "stream-voice-recording", inputs: { attachment: "attachment" }, viewQueries: [{ propertyName: "audioElement", first: true, predicate: ["audioElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__message-attachment__voice-recording-widget\"\n [class.str-chat__message-attachment__voice-recording-widget--error]=\"isError\"\n data-testid=\"voice-recording-widget\"\n>\n <!-- Empty event handlers to trigger change detection -->\n <audio\n #audioElement\n (play)=\"(null)\"\n (pause)=\"(null)\"\n (ended)=\"(null)\"\n (error)=\"isError = true\"\n (abort)=\"isError = true\"\n >\n <source\n data-testid=\"audio-source\"\n [src]=\"attachment?.asset_url\"\n [type]=\"attachment?.mime_type\"\n />\n </audio>\n <button\n class=\"str-chat__message-attachment-audio-widget--play-button\"\n data-testid=\"play-button\"\n (click)=\"togglePlay()\"\n >\n <stream-icon-placeholder\n [icon]=\"audioElement?.paused ? 'play' : 'pause'\"\n ></stream-icon-placeholder>\n </button>\n <div class=\"str-chat__message-attachment__voice-recording-widget__metadata\">\n <div class=\"str-chat__message-attachment-voice-recording-widget--first-row\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__title\"\n data-testid=\"voice-recording-title\"\n [title]=\"attachment?.title\"\n >\n {{ attachment?.title }}\n </div>\n </div>\n\n <ng-container *ngIf=\"isError; else state\">\n <div\n class=\"\n str-chat__message-attachment__voice-recording-widget__error-message\n \"\n >\n <stream-icon-placeholder\n [size]=\"20\"\n icon=\"error\"\n ></stream-icon-placeholder>\n <span data-testid=\"error-message\">{{\n \"streamChat.Error playing audio\" | translate\n }}</span>\n </div>\n </ng-container>\n <ng-template #state>\n <div\n class=\"\n str-chat__message-attachment__voice-recording-widget__audio-state\n \"\n >\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__timer\"\n >\n <span\n data-testid=\"duration\"\n *ngIf=\"!!attachment?.duration; else fileSizeTemplate\"\n >\n {{\n secondsElapsed > 0 || !audioElement.paused\n ? secondsElapsedFormatted\n : durationFormatted\n }}</span\n >\n <ng-template #fileSizeTemplate>\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testid=\"file-size-indicator\"\n >\n {{ fileSize }}\n </span>\n </ng-template>\n </div>\n <stream-voice-recording-wavebar\n *ngIf=\"attachment?.waveform_data && attachment?.duration\"\n [waveFormData]=\"attachment?.waveform_data || []\"\n [duration]=\"attachment?.duration\"\n [audioElement]=\"audioElement\"\n ></stream-voice-recording-wavebar>\n </div>\n </ng-template>\n </div>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__right-section\"\n >\n <button\n *ngIf=\"!audioElement?.paused; else fileIcon\"\n class=\"str-chat__message_attachment__playback-rate-button\"\n data-testid=\"playback-rate-button\"\n (click)=\"setPlaybackRate()\"\n >\n {{ audioElement?.playbackRate | number: \"1.1-1\" }}x\n </button>\n <ng-template #fileIcon>\n <stream-icon-placeholder\n icon=\"audio-file\"\n [size]=\"40\"\n ></stream-icon-placeholder>\n </ng-template>\n </div>\n</div>\n", components: [{ type: i1.IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: i2.VoiceRecordingWavebarComponent, selector: "stream-voice-recording-wavebar", inputs: ["audioElement", "waveFormData", "duration"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "translate": i4.TranslatePipe, "number": i3.DecimalPipe } });
102
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: VoiceRecordingComponent, decorators: [{
103
- type: Component,
104
- args: [{
105
- selector: 'stream-voice-recording',
106
- templateUrl: './voice-recording.component.html',
107
- styles: [],
108
- }]
109
- }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { attachment: [{
110
- type: Input
111
- }], audioElement: [{
112
- type: ViewChild,
113
- args: ['audioElement']
114
- }] } });
115
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidm9pY2UtcmVjb3JkaW5nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi92b2ljZS1yZWNvcmRpbmcvdm9pY2UtcmVjb3JkaW5nLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi92b2ljZS1yZWNvcmRpbmcvdm9pY2UtcmVjb3JkaW5nLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBR0wsU0FBUyxFQUVULEtBQUssRUFJTCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxXQUFXLE1BQU0sY0FBYyxDQUFDOzs7Ozs7QUFFdkM7O0dBRUc7QUFNSCxNQUFNLE9BQU8sdUJBQXVCO0lBYWxDLFlBQW9CLE1BQWMsRUFBVSxLQUF3QjtRQUFoRCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQVUsVUFBSyxHQUFMLEtBQUssQ0FBbUI7UUFScEUsYUFBUSxHQUFXLEVBQUUsQ0FBQztRQUV0QixzQkFBaUIsR0FBVyxFQUFFLENBQUM7UUFDL0IsbUJBQWMsR0FBRyxDQUFDLENBQUM7UUFDbkIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUtkLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQ3RELElBQUksQ0FBQyxjQUFjLENBQ3BCLENBQUM7SUFDSixDQUFDO0lBRUQsV0FBVyxDQUFDLE9BQXNCOztRQUNoQyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFDdEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FDaEQsTUFBQSxJQUFJLENBQUMsVUFBVSwwQ0FBRSxRQUFRLENBQzFCLENB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QUM7b0JBQ1QsUUFBUSxFQUFFLHdCQUF3QjtvQkFDbEMsV0FBVyxFQUFFLGtDQUFrQztvQkFDL0MsTUFBTSxFQUFFLEVBQUU7aUJBQ1g7NkhBS1UsVUFBVTtzQkFBbEIsS0FBSztnQkFPRSxZQUFZO3NCQURuQixTQUFTO3VCQUFDLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdHRhY2htZW50IH0gZnJvbSAnc3RyZWFtLWNoYXQnO1xuaW1wb3J0IHsgRGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcyB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCBwcmV0dHlieXRlcyBmcm9tICdwcmV0dHktYnl0ZXMnO1xuXG4vKipcbiAqIFRoaXMgY29tcG9uZW50IGNhbiBiZSB1c2VkIHRvIGRpc3BsYXkgYW4gYXR0YWNobWVudCB3aXRoIHR5cGUgYHZvaWNlUmVjb3JkaW5nYC4gVGhlIGNvbXBvbmVudCBhbGxvd3MgcGxheWluZyB0aGUgYXR0YWNobWVudCBpbnNpZGUgdGhlIGJyb3dzZXIuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3N0cmVhbS12b2ljZS1yZWNvcmRpbmcnLFxuICB0ZW1wbGF0ZVVybDogJy4vdm9pY2UtcmVjb3JkaW5nLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVzOiBbXSxcbn0pXG5leHBvcnQgY2xhc3MgVm9pY2VSZWNvcmRpbmdDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQge1xuICAvKipcbiAgICogVGhlIHZvaWNlIHJlY29yZGluZyBhdHRhY2htZW50XG4gICAqL1xuICBASW5wdXQoKSBhdHRhY2htZW50PzogQXR0YWNobWVudDxEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzPjtcbiAgZmlsZVNpemU6IHN0cmluZyA9ICcnO1xuICBzZWNvbmRzRWxhcHNlZEZvcm1hdHRlZDogc3RyaW5nO1xuICBkdXJhdGlvbkZvcm1hdHRlZDogc3RyaW5nID0gJyc7XG4gIHNlY29uZHNFbGFwc2VkID0gMDtcbiAgaXNFcnJvciA9IGZhbHNlO1xuICBAVmlld0NoaWxkKCdhdWRpb0VsZW1lbnQnKVxuICBwcml2YXRlIGF1ZGlvRWxlbWVudD86IEVsZW1lbnRSZWY8SFRNTEF1ZGlvRWxlbWVudD47XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSwgcHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHtcbiAgICB0aGlzLnNlY29uZHNFbGFwc2VkRm9ybWF0dGVkID0gdGhpcy5nZXRGb3JtYXR0ZWREdXJhdGlvbihcbiAgICAgIHRoaXMuc2Vjb25kc0VsYXBzZWRcbiAgICApO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLmF0dGFjaG1lbnQpIHtcbiAgICAgIHRoaXMuZmlsZVNpemUgPSB0aGlzLmdldEZpbGVTaXplKCk7XG4gICAgICB0aGlzLmR1cmF0aW9uRm9ybWF0dGVkID0gdGhpcy5nZXRGb3JtYXR0ZWREdXJhdGlvbihcbiAgICAgICAgdGhpcy5hdHRhY2htZW50Py5kdXJhdGlvblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgLy8gdGltZXVwZGF0ZSBmaXJlZCBmcmVxdW50bHkgc28gd2Ugb3B0aW1pemUgY2hhbmdlIGRldGVjdGlvbnNcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICB0aGlzLmF1ZGlvRWxlbWVudD8ubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0aW1ldXBkYXRlJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBzZWNvbmRzRWxhcHNlZCA9IHRoaXMuYXVkaW9FbGVtZW50Py5uYXRpdmVFbGVtZW50Py5lbmRlZFxuICAgICAgICAgID8gdGhpcy5hdHRhY2htZW50Py5kdXJhdGlvbiB8fCAwXG4gICAgICAgICAgOiBNYXRoLnJvdW5kKHRoaXMuYXVkaW9FbGVtZW50Py5uYXRpdmVFbGVtZW50Py5jdXJyZW50VGltZSB8fCAwKTtcbiAgICAgICAgaWYgKHRoaXMuc2Vjb25kc0VsYXBzZWQgIT09IHNlY29uZHNFbGFwc2VkKSB7XG4gICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kc0VsYXBzZWQgPSBzZWNvbmRzRWxhcHNlZDtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kc0VsYXBzZWRGb3JtYXR0ZWQgPSB0aGlzLmdldEZvcm1hdHRlZER1cmF0aW9uKFxuICAgICAgICAgICAgICB0aGlzLnNlY29uZHNFbGFwc2VkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgdG9nZ2xlUGxheSgpIHtcbiAgICBpZiAoIXRoaXMuYXVkaW9FbGVtZW50IHx8ICF0aGlzLmF0dGFjaG1lbnQ/LmFzc2V0X3VybCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgdGhpcy5hdWRpb0VsZW1lbnQ/Lm5hdGl2ZUVsZW1lbnQucGF1c2VkXG4gICAgICAgID8gYXdhaXQgdGhpcy5hdWRpb0VsZW1lbnQubmF0aXZlRWxlbWVudC5wbGF5KClcbiAgICAgICAgOiB0aGlzLmF1ZGlvRWxlbWVudC5uYXRpdmVFbGVtZW50LnBhdXNlKCk7XG4gICAgICB0aGlzLmlzRXJyb3IgPSBmYWxzZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmlzRXJyb3IgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHNldFBsYXliYWNrUmF0ZSgpIHtcbiAgICBpZiAoIXRoaXMuYXVkaW9FbGVtZW50Py5uYXRpdmVFbGVtZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBwbGF5YmFja1JhdGUgPSB0aGlzLmF1ZGlvRWxlbWVudD8ubmF0aXZlRWxlbWVudD8ucGxheWJhY2tSYXRlICsgMC41O1xuICAgIGlmIChwbGF5YmFja1JhdGUgPiAyKSB7XG4gICAgICBwbGF5YmFja1JhdGUgPSAxO1xuICAgIH1cbiAgICB0aGlzLmF1ZGlvRWxlbWVudC5uYXRpdmVFbGVtZW50LnBsYXliYWNrUmF0ZSA9IHBsYXliYWNrUmF0ZTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Rm9ybWF0dGVkRHVyYXRpb24oZHVyYXRpb24/OiBudW1iZXIpIHtcbiAgICBpZiAoZHVyYXRpb24gPT09IHVuZGVmaW5lZCB8fCBkdXJhdGlvbiA8PSAwKSByZXR1cm4gJzAwOjAwJztcblxuICAgIGNvbnN0IFtob3VycywgaG91cnNMZWZ0b3Zlcl0gPSB0aGlzLmRpdk1vZChkdXJhdGlvbiwgMzYwMCk7XG4gICAgY29uc3QgW21pbnV0ZXMsIHNlY29uZHNdID0gdGhpcy5kaXZNb2QoaG91cnNMZWZ0b3ZlciwgNjApO1xuICAgIGNvbnN0IHJvdW5kZWRTZWNvbmRzID0gTWF0aC5jZWlsKHNlY29uZHMpO1xuXG4gICAgY29uc3QgcHJlcGVuZEhyc1plcm8gPSBob3Vycy50b1N0cmluZygpLmxlbmd0aCA9PT0gMSA/ICcwJyA6ICcnO1xuICAgIGNvbnN0IHByZXBlbmRNaW5aZXJvID0gbWludXRlcy50b1N0cmluZygpLmxlbmd0aCA9PT0gMSA/ICcwJyA6ICcnO1xuICAgIGNvbnN0IHByZXBlbmRTZWNaZXJvID0gcm91bmRlZFNlY29uZHMudG9TdHJpbmcoKS5sZW5ndGggPT09IDEgPyAnMCcgOiAnJztcbiAgICBjb25zdCBtaW5TZWMgPSBgJHtwcmVwZW5kTWluWmVyb30ke21pbnV0ZXN9OiR7cHJlcGVuZFNlY1plcm99JHtyb3VuZGVkU2Vjb25kc31gO1xuXG4gICAgcmV0dXJuIGhvdXJzID8gYCR7cHJlcGVuZEhyc1plcm99JHtob3Vyc306YCArIG1pblNlYyA6IG1pblNlYztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RmlsZVNpemUoKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5hdHRhY2htZW50Py5maWxlX3NpemUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5hdHRhY2htZW50Py5maWxlX3NpemUgPT09IG51bGxcbiAgICApIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIHByZXR0eWJ5dGVzKE51bWJlcih0aGlzLmF0dGFjaG1lbnQuZmlsZV9zaXplIHx8IDApKTtcbiAgfVxuXG4gIHByaXZhdGUgZGl2TW9kKG51bTogbnVtYmVyLCBkaXZpc29yOiBudW1iZXIpIHtcbiAgICByZXR1cm4gW01hdGguZmxvb3IobnVtIC8gZGl2aXNvciksIG51bSAlIGRpdmlzb3JdO1xuICB9XG59XG4iLCI8ZGl2XG4gIGNsYXNzPVwic3RyLWNoYXRfX21lc3NhZ2UtYXR0YWNobWVudF9fdm9pY2UtcmVjb3JkaW5nLXdpZGdldFwiXG4gIFtjbGFzcy5zdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50X192b2ljZS1yZWNvcmRpbmctd2lkZ2V0LS1lcnJvcl09XCJpc0Vycm9yXCJcbiAgZGF0YS10ZXN0aWQ9XCJ2b2ljZS1yZWNvcmRpbmctd2lkZ2V0XCJcbj5cbiAgPCEtLSBFbXB0eSBldmVudCBoYW5kbGVycyB0byB0cmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb24gLS0+XG4gIDxhdWRpb1xuICAgICNhdWRpb0VsZW1lbnRcbiAgICAocGxheSk9XCIobnVsbClcIlxuICAgIChwYXVzZSk9XCIobnVsbClcIlxuICAgIChlbmRlZCk9XCIobnVsbClcIlxuICAgIChlcnJvcik9XCJpc0Vycm9yID0gdHJ1ZVwiXG4gICAgKGFib3J0KT1cImlzRXJyb3IgPSB0cnVlXCJcbiAgPlxuICAgIDxzb3VyY2VcbiAgICAgIGRhdGEtdGVzdGlkPVwiYXVkaW8tc291cmNlXCJcbiAgICAgIFtzcmNdPVwiYXR0YWNobWVudD8uYXNzZXRfdXJsXCJcbiAgICAgIFt0eXBlXT1cImF0dGFjaG1lbnQ/Lm1pbWVfdHlwZVwiXG4gICAgLz5cbiAgPC9hdWRpbz5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwic3RyLWNoYXRfX21lc3NhZ2UtYXR0YWNobWVudC1hdWRpby13aWRnZXQtLXBsYXktYnV0dG9uXCJcbiAgICBkYXRhLXRlc3RpZD1cInBsYXktYnV0dG9uXCJcbiAgICAoY2xpY2spPVwidG9nZ2xlUGxheSgpXCJcbiAgPlxuICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlclxuICAgICAgW2ljb25dPVwiYXVkaW9FbGVtZW50Py5wYXVzZWQgPyAncGxheScgOiAncGF1c2UnXCJcbiAgICA+PC9zdHJlYW0taWNvbi1wbGFjZWhvbGRlcj5cbiAgPC9idXR0b24+XG4gIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50X192b2ljZS1yZWNvcmRpbmctd2lkZ2V0X19tZXRhZGF0YVwiPlxuICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LXZvaWNlLXJlY29yZGluZy13aWRnZXQtLWZpcnN0LXJvd1wiPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnRfX3ZvaWNlLXJlY29yZGluZy13aWRnZXRfX3RpdGxlXCJcbiAgICAgICAgZGF0YS10ZXN0aWQ9XCJ2b2ljZS1yZWNvcmRpbmctdGl0bGVcIlxuICAgICAgICBbdGl0bGVdPVwiYXR0YWNobWVudD8udGl0bGVcIlxuICAgICAgPlxuICAgICAgICB7eyBhdHRhY2htZW50Py50aXRsZSB9fVxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXNFcnJvcjsgZWxzZSBzdGF0ZVwiPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cIlxuICAgICAgICAgIHN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnRfX3ZvaWNlLXJlY29yZGluZy13aWRnZXRfX2Vycm9yLW1lc3NhZ2VcbiAgICAgICAgXCJcbiAgICAgID5cbiAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyXG4gICAgICAgICAgW3NpemVdPVwiMjBcIlxuICAgICAgICAgIGljb249XCJlcnJvclwiXG4gICAgICAgID48L3N0cmVhbS1pY29uLXBsYWNlaG9sZGVyPlxuICAgICAgICA8c3BhbiBkYXRhLXRlc3RpZD1cImVycm9yLW1lc3NhZ2VcIj57e1xuICAgICAgICAgIFwic3RyZWFtQ2hhdC5FcnJvciBwbGF5aW5nIGF1ZGlvXCIgfCB0cmFuc2xhdGVcbiAgICAgICAgfX08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctdGVtcGxhdGUgI3N0YXRlPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cIlxuICAgICAgICAgIHN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnRfX3ZvaWNlLXJlY29yZGluZy13aWRnZXRfX2F1ZGlvLXN0YXRlXG4gICAgICAgIFwiXG4gICAgICA+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnRfX3ZvaWNlLXJlY29yZGluZy13aWRnZXRfX3RpbWVyXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICBkYXRhLXRlc3RpZD1cImR1cmF0aW9uXCJcbiAgICAgICAgICAgICpuZ0lmPVwiISFhdHRhY2htZW50Py5kdXJhdGlvbjsgZWxzZSBmaWxlU2l6ZVRlbXBsYXRlXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7e1xuICAgICAgICAgICAgICBzZWNvbmRzRWxhcHNlZCA+IDAgfHwgIWF1ZGlvRWxlbWVudC5wYXVzZWRcbiAgICAgICAgICAgICAgICA/IHNlY29uZHNFbGFwc2VkRm9ybWF0dGVkXG4gICAgICAgICAgICAgICAgOiBkdXJhdGlvbkZvcm1hdHRlZFxuICAgICAgICAgICAgfX08L3NwYW5cbiAgICAgICAgICA+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNmaWxlU2l6ZVRlbXBsYXRlPlxuICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWZpbGUtLWl0ZW0tc2l6ZVwiXG4gICAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwiZmlsZS1zaXplLWluZGljYXRvclwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IGZpbGVTaXplIH19XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxzdHJlYW0tdm9pY2UtcmVjb3JkaW5nLXdhdmViYXJcbiAgICAgICAgICAqbmdJZj1cImF0dGFjaG1lbnQ/LndhdmVmb3JtX2RhdGEgJiYgYXR0YWNobWVudD8uZHVyYXRpb25cIlxuICAgICAgICAgIFt3YXZlRm9ybURhdGFdPVwiYXR0YWNobWVudD8ud2F2ZWZvcm1fZGF0YSB8fCBbXVwiXG4gICAgICAgICAgW2R1cmF0aW9uXT1cImF0dGFjaG1lbnQ/LmR1cmF0aW9uXCJcbiAgICAgICAgICBbYXVkaW9FbGVtZW50XT1cImF1ZGlvRWxlbWVudFwiXG4gICAgICAgID48L3N0cmVhbS12b2ljZS1yZWNvcmRpbmctd2F2ZWJhcj5cbiAgICAgIDwvZGl2PlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvZGl2PlxuICA8ZGl2XG4gICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50X192b2ljZS1yZWNvcmRpbmctd2lkZ2V0X19yaWdodC1zZWN0aW9uXCJcbiAgPlxuICAgIDxidXR0b25cbiAgICAgICpuZ0lmPVwiIWF1ZGlvRWxlbWVudD8ucGF1c2VkOyBlbHNlIGZpbGVJY29uXCJcbiAgICAgIGNsYXNzPVwic3RyLWNoYXRfX21lc3NhZ2VfYXR0YWNobWVudF9fcGxheWJhY2stcmF0ZS1idXR0b25cIlxuICAgICAgZGF0YS10ZXN0aWQ9XCJwbGF5YmFjay1yYXRlLWJ1dHRvblwiXG4gICAgICAoY2xpY2spPVwic2V0UGxheWJhY2tSYXRlKClcIlxuICAgID5cbiAgICAgIHt7IGF1ZGlvRWxlbWVudD8ucGxheWJhY2tSYXRlIHwgbnVtYmVyOiBcIjEuMS0xXCIgfX14XG4gICAgPC9idXR0b24+XG4gICAgPG5nLXRlbXBsYXRlICNmaWxlSWNvbj5cbiAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlclxuICAgICAgICBpY29uPVwiYXVkaW8tZmlsZVwiXG4gICAgICAgIFtzaXplXT1cIjQwXCJcbiAgICAgID48L3N0cmVhbS1pY29uLXBsYWNlaG9sZGVyPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=