stream-chat-angular 3.0.0-beta.9 → 3.0.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/README.md +44 -12
- package/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +71 -27
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/attachment-list/attachment-list.component.js +9 -2
- package/esm2015/lib/attachment-preview-list/attachment-preview-list.component.js +2 -2
- package/esm2015/lib/attachment.service.js +10 -1
- package/esm2015/lib/channel.service.js +42 -17
- package/esm2015/lib/message/message.component.js +7 -2
- package/esm2015/lib/types.js +1 -1
- package/fesm2015/stream-chat-angular.js +66 -20
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/attachment-list/attachment-list.component.d.ts +1 -0
- package/lib/channel.service.d.ts +28 -2
- package/lib/types.d.ts +1 -1
- package/package.json +2 -2
- package/src/assets/version.ts +1 -1
package/README.md
CHANGED
|
@@ -30,15 +30,38 @@ The best way to get started is to follow the [Angular Chat Tutorial](https://get
|
|
|
30
30
|
Stream is free for most side and hobby projects. To qualify, your project/company must have no more than 5 team members and earn less than $10k in monthly revenue.
|
|
31
31
|
For complete pricing and details visit our [Chat Pricing Page](https://getstream.io/chat/pricing/).
|
|
32
32
|
|
|
33
|
+
## Docs
|
|
34
|
+
|
|
35
|
+
The [docs](https://getstream.io/chat/docs/sdk/angular/) provide a brief description about the components and services in the library.
|
|
36
|
+
|
|
37
|
+
The Angular library is created using the [stream-chat-js](https://github.com/getstream/stream-chat-js) library. For the most common use cases our services should give a nice abstraction over this library, however you might need it for more advanced customization, the [documentation](https://getstream.io/chat/docs/js/) is on our website.
|
|
38
|
+
|
|
39
|
+
## Contributing
|
|
40
|
+
|
|
41
|
+
We welcome code changes that improve this library or fix a problem. Please make sure to follow all best practices and add tests, if applicable, before submitting a pull request on GitHub. We are pleased to merge your code into the official repository if it meets a need. Make sure to sign our [Contributor License Agreement (CLA)](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) first. See our license file for more details.
|
|
42
|
+
|
|
43
|
+
## We are hiring!
|
|
44
|
+
|
|
45
|
+
We recently closed a [$38 million Series B funding round](https://techcrunch.com/2021/03/04/stream-raises-38m-as-its-chat-and-activity-feed-apis-power-communications-for-1b-users/) and are actively growing.
|
|
46
|
+
Our APIs are used by more than a billion end-users, and by working at Stream, you have the chance to make a huge impact on a team of very strong engineers.
|
|
47
|
+
|
|
48
|
+
Check out our current openings and apply via [Stream's website](https://getstream.io/team/#jobs).
|
|
49
|
+
|
|
33
50
|
## Installation
|
|
34
51
|
|
|
35
52
|
### Install with NPM
|
|
36
53
|
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
Run the following command if you are using **Angular 13**:
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
npm install stream-chat-angular stream-chat @ngx-translate/core
|
|
39
58
|
```
|
|
40
59
|
|
|
41
|
-
|
|
60
|
+
Run this command if you are using **Angular 12**:
|
|
61
|
+
|
|
62
|
+
```shell
|
|
63
|
+
npm install stream-chat-angular stream-chat@5 @ngx-translate/core --legacy-peer-deps
|
|
64
|
+
```
|
|
42
65
|
|
|
43
66
|
## Sample App
|
|
44
67
|
|
|
@@ -56,19 +79,28 @@ STREAM_USER_TOKEN=<Your user token>
|
|
|
56
79
|
|
|
57
80
|
Run `npm start` and navigate to `http://localhost:4200/`.
|
|
58
81
|
|
|
59
|
-
##
|
|
82
|
+
## Customization examples
|
|
60
83
|
|
|
61
|
-
|
|
84
|
+
This repository includes a sample app that showcases how you can provide your own template for different components within the SDK:
|
|
62
85
|
|
|
63
|
-
|
|
86
|
+
To run the app:
|
|
64
87
|
|
|
65
|
-
|
|
88
|
+
Create a file named `.env` in the root directory with the following content:
|
|
66
89
|
|
|
67
|
-
|
|
90
|
+
```
|
|
91
|
+
STREAM_API_KEY=<Your API key>
|
|
92
|
+
STREAM_USER_ID=<Your user ID>
|
|
93
|
+
STREAM_USER_TOKEN=<Your user token>
|
|
94
|
+
```
|
|
68
95
|
|
|
69
|
-
|
|
96
|
+
Run `npm start:customizations-example` and navigate to `http://localhost:4200/`.
|
|
70
97
|
|
|
71
|
-
|
|
72
|
-
Our APIs are used by more than a billion end-users, and by working at Stream, you have the chance to make a huge impact on a team of very strong engineers.
|
|
98
|
+
## Local development
|
|
73
99
|
|
|
74
|
-
|
|
100
|
+
Run `npm install` in the root of the project. You can use the `npm run start:dev` command to start the SampleApp with automatic reloading.
|
|
101
|
+
|
|
102
|
+
A note about the documentation:
|
|
103
|
+
|
|
104
|
+
- Documentations for Angular services are generated from doc comments in the source files (not under source control)
|
|
105
|
+
- Documentations for inputs and outputs of Angular components are generated from doc comments in the source files (not under source control)
|
|
106
|
+
- Everything else in the documentation is written in `mdx` files located in the `docusaurus` folder
|
package/assets/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "3.0.0
|
|
1
|
+
export declare const version = "3.0.0";
|
|
@@ -354,7 +354,7 @@
|
|
|
354
354
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
var version = '3.0.0
|
|
357
|
+
var version = '3.0.0';
|
|
358
358
|
|
|
359
359
|
/**
|
|
360
360
|
* The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/NotificationListComponent.mdx) component displays the currently active notifications.
|
|
@@ -652,7 +652,7 @@
|
|
|
652
652
|
};
|
|
653
653
|
|
|
654
654
|
/**
|
|
655
|
-
* The `ChannelService` provides data and interaction for the channel list and message list.
|
|
655
|
+
* The `ChannelService` provides data and interaction for the channel list and message list.
|
|
656
656
|
*/
|
|
657
657
|
var ChannelService = /** @class */ (function () {
|
|
658
658
|
function ChannelService(chatClientService, ngZone) {
|
|
@@ -747,6 +747,21 @@
|
|
|
747
747
|
this.activeThreadMessagesSubject.next([]);
|
|
748
748
|
this.messageToQuoteSubject.next(undefined);
|
|
749
749
|
};
|
|
750
|
+
/**
|
|
751
|
+
* Deselects the currently active (if any) channel
|
|
752
|
+
*/
|
|
753
|
+
ChannelService.prototype.deselectActiveChannel = function () {
|
|
754
|
+
var activeChannel = this.activeChannelSubject.getValue();
|
|
755
|
+
if (!activeChannel) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
this.activeChannelMessagesSubject.next([]);
|
|
759
|
+
this.activeChannelSubject.next(undefined);
|
|
760
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
761
|
+
this.activeThreadMessagesSubject.next([]);
|
|
762
|
+
this.latestMessageDateByUserByChannelsSubject.next({});
|
|
763
|
+
this.selectMessageToQuote(undefined);
|
|
764
|
+
};
|
|
750
765
|
/**
|
|
751
766
|
* Sets the given `message` as an active parent message. If `undefined` is provided, it will deleselect the current parent message.
|
|
752
767
|
* @param message
|
|
@@ -842,9 +857,13 @@
|
|
|
842
857
|
* @param filters
|
|
843
858
|
* @param sort
|
|
844
859
|
* @param options
|
|
860
|
+
* @param shouldSetActiveChannel Decides if the first channel in the result should be made as an active channel, or no channel should be marked as active
|
|
861
|
+
* @returns the list of channels found by the query
|
|
845
862
|
*/
|
|
846
|
-
ChannelService.prototype.init = function (filters, sort, options) {
|
|
863
|
+
ChannelService.prototype.init = function (filters, sort, options, shouldSetActiveChannel) {
|
|
864
|
+
if (shouldSetActiveChannel === void 0) { shouldSetActiveChannel = true; }
|
|
847
865
|
return __awaiter(this, void 0, void 0, function () {
|
|
866
|
+
var result;
|
|
848
867
|
var _this = this;
|
|
849
868
|
return __generator(this, function (_h) {
|
|
850
869
|
switch (_h.label) {
|
|
@@ -859,11 +878,11 @@
|
|
|
859
878
|
message_limit: this.messagePageSize,
|
|
860
879
|
};
|
|
861
880
|
this.sort = sort || { last_message_at: -1, updated_at: -1 };
|
|
862
|
-
return [4 /*yield*/, this.queryChannels()];
|
|
881
|
+
return [4 /*yield*/, this.queryChannels(shouldSetActiveChannel)];
|
|
863
882
|
case 1:
|
|
864
|
-
_h.sent();
|
|
883
|
+
result = _h.sent();
|
|
865
884
|
this.chatClientService.events$.subscribe(function (notification) { return void _this.handleNotification(notification); });
|
|
866
|
-
return [2 /*return
|
|
885
|
+
return [2 /*return*/, result];
|
|
867
886
|
}
|
|
868
887
|
});
|
|
869
888
|
});
|
|
@@ -872,13 +891,8 @@
|
|
|
872
891
|
* Resets the `activeChannel$`, `channels$` and `activeChannelMessages$` Observables. Useful when disconnecting a chat user, use in combination with [`disconnectUser`](./ChatClientService.mdx/#disconnectuser).
|
|
873
892
|
*/
|
|
874
893
|
ChannelService.prototype.reset = function () {
|
|
875
|
-
this.
|
|
876
|
-
this.activeChannelSubject.next(undefined);
|
|
877
|
-
this.activeParentMessageIdSubject.next(undefined);
|
|
878
|
-
this.activeThreadMessagesSubject.next([]);
|
|
894
|
+
this.deselectActiveChannel();
|
|
879
895
|
this.channelsSubject.next(undefined);
|
|
880
|
-
this.latestMessageDateByUserByChannelsSubject.next({});
|
|
881
|
-
this.selectMessageToQuote(undefined);
|
|
882
896
|
};
|
|
883
897
|
/**
|
|
884
898
|
* Loads the next page of channels. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
@@ -889,7 +903,7 @@
|
|
|
889
903
|
switch (_h.label) {
|
|
890
904
|
case 0:
|
|
891
905
|
this.options.offset = this.channels.length;
|
|
892
|
-
return [4 /*yield*/, this.queryChannels()];
|
|
906
|
+
return [4 /*yield*/, this.queryChannels(false)];
|
|
893
907
|
case 1:
|
|
894
908
|
_h.sent();
|
|
895
909
|
return [2 /*return*/];
|
|
@@ -1027,14 +1041,19 @@
|
|
|
1027
1041
|
ChannelService.prototype.uploadAttachments = function (uploads) {
|
|
1028
1042
|
return __awaiter(this, void 0, void 0, function () {
|
|
1029
1043
|
var result, channel, uploadResults;
|
|
1044
|
+
var _this = this;
|
|
1030
1045
|
return __generator(this, function (_h) {
|
|
1031
1046
|
switch (_h.label) {
|
|
1032
1047
|
case 0:
|
|
1033
1048
|
result = [];
|
|
1034
1049
|
channel = this.activeChannelSubject.getValue();
|
|
1035
1050
|
return [4 /*yield*/, Promise.allSettled(uploads.map(function (upload) { return upload.type === 'image'
|
|
1036
|
-
?
|
|
1037
|
-
|
|
1051
|
+
? _this.customImageUploadRequest
|
|
1052
|
+
? _this.customImageUploadRequest(upload.file, channel)
|
|
1053
|
+
: channel.sendImage(upload.file)
|
|
1054
|
+
: _this.customFileUploadRequest
|
|
1055
|
+
? _this.customFileUploadRequest(upload.file, channel)
|
|
1056
|
+
: channel.sendFile(upload.file); }))];
|
|
1038
1057
|
case 1:
|
|
1039
1058
|
uploadResults = _h.sent();
|
|
1040
1059
|
uploadResults.forEach(function (uploadResult, i) {
|
|
@@ -1069,8 +1088,12 @@
|
|
|
1069
1088
|
case 0:
|
|
1070
1089
|
channel = this.activeChannelSubject.getValue();
|
|
1071
1090
|
return [4 /*yield*/, (attachmentUpload.type === 'image'
|
|
1072
|
-
?
|
|
1073
|
-
|
|
1091
|
+
? this.customImageDeleteRequest
|
|
1092
|
+
? this.customImageDeleteRequest(attachmentUpload.url, channel)
|
|
1093
|
+
: channel.deleteImage(attachmentUpload.url)
|
|
1094
|
+
: this.customFileDeleteRequest
|
|
1095
|
+
? this.customFileDeleteRequest(attachmentUpload.url, channel)
|
|
1096
|
+
: channel.deleteFile(attachmentUpload.url))];
|
|
1074
1097
|
case 1:
|
|
1075
1098
|
_h.sent();
|
|
1076
1099
|
return [2 /*return*/];
|
|
@@ -1413,7 +1436,7 @@
|
|
|
1413
1436
|
this.activeChannelSubscriptions.forEach(function (s) { return s.unsubscribe(); });
|
|
1414
1437
|
this.activeChannelSubscriptions = [];
|
|
1415
1438
|
};
|
|
1416
|
-
ChannelService.prototype.queryChannels = function () {
|
|
1439
|
+
ChannelService.prototype.queryChannels = function (shouldSetActiveChannel) {
|
|
1417
1440
|
return __awaiter(this, void 0, void 0, function () {
|
|
1418
1441
|
var channels, prevChannels, error_2;
|
|
1419
1442
|
var _this = this;
|
|
@@ -1427,15 +1450,17 @@
|
|
|
1427
1450
|
channels.forEach(function (c) { return _this.watchForChannelEvents(c); });
|
|
1428
1451
|
prevChannels = this.channelsSubject.getValue() || [];
|
|
1429
1452
|
this.channelsSubject.next(__spreadArray(__spreadArray([], __read(prevChannels)), __read(channels)));
|
|
1430
|
-
if (channels.length > 0 &&
|
|
1453
|
+
if (channels.length > 0 &&
|
|
1454
|
+
!this.activeChannelSubject.getValue() &&
|
|
1455
|
+
shouldSetActiveChannel) {
|
|
1431
1456
|
this.setAsActiveChannel(channels[0]);
|
|
1432
1457
|
}
|
|
1433
1458
|
this.hasMoreChannelsSubject.next(channels.length >= this.options.limit);
|
|
1434
|
-
return [
|
|
1459
|
+
return [2 /*return*/, channels];
|
|
1435
1460
|
case 2:
|
|
1436
1461
|
error_2 = _h.sent();
|
|
1437
1462
|
this.channelsSubject.error(error_2);
|
|
1438
|
-
|
|
1463
|
+
throw error_2;
|
|
1439
1464
|
case 3: return [2 /*return*/];
|
|
1440
1465
|
}
|
|
1441
1466
|
});
|
|
@@ -1819,7 +1844,7 @@
|
|
|
1819
1844
|
*/
|
|
1820
1845
|
AttachmentService.prototype.filesSelected = function (fileList) {
|
|
1821
1846
|
return __awaiter(this, void 0, void 0, function () {
|
|
1822
|
-
var imageFiles, dataFiles, newUploads;
|
|
1847
|
+
var imageFiles, dataFiles, videoFiles, newUploads;
|
|
1823
1848
|
var _this = this;
|
|
1824
1849
|
return __generator(this, function (_d) {
|
|
1825
1850
|
switch (_d.label) {
|
|
@@ -1829,19 +1854,27 @@
|
|
|
1829
1854
|
}
|
|
1830
1855
|
imageFiles = [];
|
|
1831
1856
|
dataFiles = [];
|
|
1857
|
+
videoFiles = [];
|
|
1832
1858
|
Array.from(fileList).forEach(function (file) {
|
|
1833
1859
|
if (isImageFile(file)) {
|
|
1834
1860
|
imageFiles.push(file);
|
|
1835
1861
|
}
|
|
1862
|
+
else if (file.type.startsWith('video/')) {
|
|
1863
|
+
videoFiles.push(file);
|
|
1864
|
+
}
|
|
1836
1865
|
else {
|
|
1837
1866
|
dataFiles.push(file);
|
|
1838
1867
|
}
|
|
1839
1868
|
});
|
|
1840
1869
|
imageFiles.forEach(function (f) { return _this.createPreview(f); });
|
|
1841
|
-
newUploads = __spreadArray(__spreadArray([], __read(imageFiles.map(function (file) { return ({
|
|
1870
|
+
newUploads = __spreadArray(__spreadArray(__spreadArray([], __read(imageFiles.map(function (file) { return ({
|
|
1842
1871
|
file: file,
|
|
1843
1872
|
state: 'uploading',
|
|
1844
1873
|
type: 'image',
|
|
1874
|
+
}); }))), __read(videoFiles.map(function (file) { return ({
|
|
1875
|
+
file: file,
|
|
1876
|
+
state: 'uploading',
|
|
1877
|
+
type: 'video',
|
|
1845
1878
|
}); }))), __read(dataFiles.map(function (file) { return ({
|
|
1846
1879
|
file: file,
|
|
1847
1880
|
state: 'uploading',
|
|
@@ -2735,7 +2768,7 @@
|
|
|
2735
2768
|
var _this = this;
|
|
2736
2769
|
var images = this.attachments.filter(this.isImage);
|
|
2737
2770
|
var containsGallery = images.length >= 2;
|
|
2738
|
-
this.orderedAttachments = __spreadArray(__spreadArray(__spreadArray([], __read((containsGallery ? this.createGallery(images) : images))), __read(this.attachments.filter(function (a) { return _this.isFile(a); }))), __read(this.attachments.filter(function (a) { return _this.isCard(a); })));
|
|
2771
|
+
this.orderedAttachments = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read((containsGallery ? this.createGallery(images) : images))), __read(this.attachments.filter(function (a) { return _this.isVideo(a); }))), __read(this.attachments.filter(function (a) { return _this.isFile(a); }))), __read(this.attachments.filter(function (a) { return _this.isCard(a); })));
|
|
2739
2772
|
};
|
|
2740
2773
|
AttachmentListComponent.prototype.trackById = function (index) {
|
|
2741
2774
|
return index;
|
|
@@ -2749,6 +2782,12 @@
|
|
|
2749
2782
|
AttachmentListComponent.prototype.isGallery = function (attachment) {
|
|
2750
2783
|
return attachment.type === 'gallery';
|
|
2751
2784
|
};
|
|
2785
|
+
AttachmentListComponent.prototype.isVideo = function (attachment) {
|
|
2786
|
+
return (attachment.type === 'video' &&
|
|
2787
|
+
attachment.asset_url &&
|
|
2788
|
+
!attachment.og_scrape_url // links from video share services (such as YouTube or Facebook) are can't be played
|
|
2789
|
+
);
|
|
2790
|
+
};
|
|
2752
2791
|
AttachmentListComponent.prototype.isCard = function (attachment) {
|
|
2753
2792
|
return (!attachment.type ||
|
|
2754
2793
|
(attachment.type === 'image' && !this.isImage(attachment)) ||
|
|
@@ -2828,7 +2867,7 @@
|
|
|
2828
2867
|
return AttachmentListComponent;
|
|
2829
2868
|
}());
|
|
2830
2869
|
AttachmentListComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AttachmentListComponent, deps: [{ token: CustomTemplatesService }, { token: ImageLoadService }, { token: ChannelService }], target: i0__namespace.ɵɵFactoryTarget.Component });
|
|
2831
|
-
AttachmentListComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", attachments: "attachments" }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0__namespace, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n (click)=\"openImageModal([attachment])\"\n (keyup.enter)=\"openImageModal([attachment])\"\n />\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n *ngIf=\"isGallery(attachment)\"\n [class.str-chat__gallery--square]=\"(attachment?.images)!.length > 3\"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachment.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n >\n <img\n [src]=\"\n galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url\n \"\n [alt]=\"galleryImage.fallback\"\n (load)=\"imageLoaded()\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n (galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url) +\n ')'\n }\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate: { imageCount: attachment!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon-placeholder\n icon=\"file\"\n [size]=\"30\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n <div\n class=\"str-chat__message-attachment-actions\"\n *ngIf=\"attachment.actions && attachment.actions.length > 0\"\n >\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"let action of attachment.actions; trackBy: trackByActionValue\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n data-testclass=\"attachment-action\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n</ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n [isOpen]=\"isOpen\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n [content]=\"content\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal\">\n <button\n class=\"stream-chat-angular__image-modal-stepper\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <img\n class=\"stream-chat-angular__image-modal-image\"\n data-testid=\"modal-image\"\n [src]=\"\n imagesToView[imagesToViewCurrentIndex].img_url ||\n imagesToView[imagesToViewCurrentIndex].thumb_url ||\n imagesToView[imagesToViewCurrentIndex].image_url\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n />\n <button\n class=\"stream-chat-angular__image-modal-stepper\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n data-testid=\"image-modal-next\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }], directives: [{ type: i3__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3__namespace.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i3__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i2__namespace.TranslatePipe, "async": i3__namespace.AsyncPipe } });
|
|
2870
|
+
AttachmentListComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", attachments: "attachments" }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0__namespace, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n (click)=\"openImageModal([attachment])\"\n (keyup.enter)=\"openImageModal([attachment])\"\n />\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n *ngIf=\"isGallery(attachment)\"\n [class.str-chat__gallery--square]=\"(attachment?.images)!.length > 3\"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachment.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n >\n <img\n [src]=\"\n galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url\n \"\n [alt]=\"galleryImage.fallback\"\n (load)=\"imageLoaded()\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n (galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url) +\n ')'\n }\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate: { imageCount: attachment!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n <video\n *ngIf=\"isVideo(attachment)\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"attachment.asset_url\"\n style=\"\n width: 100%;\n max-width: 400px;\n height: 300px;\n border-radius: inherit;\n \"\n ></video>\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon-placeholder\n icon=\"file\"\n [size]=\"30\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n <div\n class=\"str-chat__message-attachment-actions\"\n *ngIf=\"attachment.actions && attachment.actions.length > 0\"\n >\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"let action of attachment.actions; trackBy: trackByActionValue\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n data-testclass=\"attachment-action\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n</ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n [isOpen]=\"isOpen\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n [content]=\"content\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal\">\n <button\n class=\"stream-chat-angular__image-modal-stepper\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <img\n class=\"stream-chat-angular__image-modal-image\"\n data-testid=\"modal-image\"\n [src]=\"\n imagesToView[imagesToViewCurrentIndex].img_url ||\n imagesToView[imagesToViewCurrentIndex].thumb_url ||\n imagesToView[imagesToViewCurrentIndex].image_url\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n />\n <button\n class=\"stream-chat-angular__image-modal-stepper\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n data-testid=\"image-modal-next\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }], directives: [{ type: i3__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3__namespace.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i3__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i2__namespace.TranslatePipe, "async": i3__namespace.AsyncPipe } });
|
|
2832
2871
|
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AttachmentListComponent, decorators: [{
|
|
2833
2872
|
type: i0.Component,
|
|
2834
2873
|
args: [{
|
|
@@ -2871,7 +2910,7 @@
|
|
|
2871
2910
|
return AttachmentPreviewListComponent;
|
|
2872
2911
|
}());
|
|
2873
2912
|
AttachmentPreviewListComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AttachmentPreviewListComponent, deps: [], target: i0__namespace.ɵɵFactoryTarget.Component });
|
|
2874
|
-
AttachmentPreviewListComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: { attachmentUploads$: "attachmentUploads$" }, outputs: { retryAttachmentUpload: "retryAttachmentUpload", deleteAttachment: "deleteAttachment" }, ngImport: i0__namespace, template: "<div class=\"rfu-image-previewer\" *ngIf=\"(attachmentUploads$ | async)?.length\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon-placeholder icon=\"retry\"></stream-icon-placeholder>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator-placeholder>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"attachmentUpload.type === 'file'\"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon-placeholder icon=\"file\"></stream-icon-placeholder>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"attachmentUpload.url ? null : $event.preventDefault()\"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator-placeholder></stream-loading-indicator-placeholder>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i3__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2__namespace.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i3__namespace.AsyncPipe } });
|
|
2913
|
+
AttachmentPreviewListComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: { attachmentUploads$: "attachmentUploads$" }, outputs: { retryAttachmentUpload: "retryAttachmentUpload", deleteAttachment: "deleteAttachment" }, ngImport: i0__namespace, template: "<div class=\"rfu-image-previewer\" *ngIf=\"(attachmentUploads$ | async)?.length\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon-placeholder icon=\"retry\"></stream-icon-placeholder>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator-placeholder>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"\n attachmentUpload.type === 'file' || attachmentUpload.type === 'video'\n \"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon-placeholder icon=\"file\"></stream-icon-placeholder>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"attachmentUpload.url ? null : $event.preventDefault()\"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator-placeholder></stream-loading-indicator-placeholder>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i3__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2__namespace.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i3__namespace.AsyncPipe } });
|
|
2875
2914
|
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AttachmentPreviewListComponent, decorators: [{
|
|
2876
2915
|
type: i0.Component,
|
|
2877
2916
|
args: [{
|
|
@@ -4369,7 +4408,12 @@
|
|
|
4369
4408
|
this.message.mentioned_users.length === 0) {
|
|
4370
4409
|
// Wrap emojis in span to display emojis correctly in Chrome https://bugs.chromium.org/p/chromium/issues/detail?id=596223
|
|
4371
4410
|
var regex = new RegExp(emojiRegex__default['default'](), 'g');
|
|
4372
|
-
|
|
4411
|
+
// Based on this: https://stackoverflow.com/questions/4565112/javascript-how-to-find-out-if-the-user-browser-is-chrome
|
|
4412
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
4413
|
+
var isChrome_1 = !!window.chrome &&
|
|
4414
|
+
typeof window.opr === 'undefined';
|
|
4415
|
+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
4416
|
+
content = content.replace(regex, function (match) { return "<span " + (isChrome_1 ? 'class="str-chat__emoji-display-fix"' : '') + ">" + match + "</span>"; });
|
|
4373
4417
|
this.messageTextParts = [{ content: content, type: 'text' }];
|
|
4374
4418
|
}
|
|
4375
4419
|
else {
|