diff --git a/package-lock.json b/package-lock.json index c1cf357a..d93c8f9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", "@popperjs/core": "^2.11.5", - "@stream-io/stream-chat-css": "4.7.4", + "@stream-io/stream-chat-css": "4.8.0", "@stream-io/transliterate": "^1.5.2", "angular-mentions": "^1.4.0", "dayjs": "^1.10.7", @@ -30,7 +30,7 @@ "ngx-popperjs": "^12.2.2", "pretty-bytes": "^5.6.0", "rxjs": "^7.1.0", - "stream-chat": "^8.15.0", + "stream-chat": "^8.20.0", "ts-node": "^10.2.1", "tslib": "^2.3.0", "uuidv4": "^6.2.12", @@ -4441,9 +4441,9 @@ "dev": true }, "node_modules/@stream-io/stream-chat-css": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/@stream-io/stream-chat-css/-/stream-chat-css-4.7.4.tgz", - "integrity": "sha512-mDOJupQ7vLCtaDBgkBP+jq1Zw/PCg+MKR5FPg/95GRp5KF4p/id6DYPZUZ0OIOnbraAFuyfs156vrd8qzMRwag==" + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@stream-io/stream-chat-css/-/stream-chat-css-4.8.0.tgz", + "integrity": "sha512-CdMiaPoL9XsFkYb9A7o5qEDr+uhmfGpXpDMH/nbiaWJjoceyY/otofKA3mJ7Tiqt0l83S3ZV2dBq1wJEHliJKQ==" }, "node_modules/@stream-io/transliterate": { "version": "1.5.2", @@ -21883,9 +21883,9 @@ } }, "node_modules/stream-chat": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/stream-chat/-/stream-chat-8.16.0.tgz", - "integrity": "sha512-j5GDgCmae4k59titjzePvihfVoVSlRW8NvP7uXfxbfMlsmGfcbYl08IaAwSsW6NC44doZyIjOt7v/v2QyCcP4A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/stream-chat/-/stream-chat-8.20.0.tgz", + "integrity": "sha512-7kcgyUf8MeHtmhZVHGfuPNLmjfDBc3hTqfkFf2fHpNLsFrEdKjBSoS83GQgbL/JgsJ/aU0fOAUWtIkH3Z2LZzA==", "dependencies": { "@babel/runtime": "^7.16.3", "@types/jsonwebtoken": "~9.0.0", @@ -27745,9 +27745,9 @@ "dev": true }, "@stream-io/stream-chat-css": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/@stream-io/stream-chat-css/-/stream-chat-css-4.7.4.tgz", - "integrity": "sha512-mDOJupQ7vLCtaDBgkBP+jq1Zw/PCg+MKR5FPg/95GRp5KF4p/id6DYPZUZ0OIOnbraAFuyfs156vrd8qzMRwag==" + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@stream-io/stream-chat-css/-/stream-chat-css-4.8.0.tgz", + "integrity": "sha512-CdMiaPoL9XsFkYb9A7o5qEDr+uhmfGpXpDMH/nbiaWJjoceyY/otofKA3mJ7Tiqt0l83S3ZV2dBq1wJEHliJKQ==" }, "@stream-io/transliterate": { "version": "1.5.2", @@ -40858,9 +40858,9 @@ "dev": true }, "stream-chat": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/stream-chat/-/stream-chat-8.16.0.tgz", - "integrity": "sha512-j5GDgCmae4k59titjzePvihfVoVSlRW8NvP7uXfxbfMlsmGfcbYl08IaAwSsW6NC44doZyIjOt7v/v2QyCcP4A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/stream-chat/-/stream-chat-8.20.0.tgz", + "integrity": "sha512-7kcgyUf8MeHtmhZVHGfuPNLmjfDBc3hTqfkFf2fHpNLsFrEdKjBSoS83GQgbL/JgsJ/aU0fOAUWtIkH3Z2LZzA==", "requires": { "@babel/runtime": "^7.16.3", "@types/jsonwebtoken": "~9.0.0", diff --git a/package.json b/package.json index 5883e07e..c4c0097a 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", "@popperjs/core": "^2.11.5", - "@stream-io/stream-chat-css": "4.7.4", + "@stream-io/stream-chat-css": "4.8.0", "@stream-io/transliterate": "^1.5.2", "angular-mentions": "^1.4.0", "dayjs": "^1.10.7", @@ -126,7 +126,7 @@ "ngx-popperjs": "^12.2.2", "pretty-bytes": "^5.6.0", "rxjs": "^7.1.0", - "stream-chat": "^8.15.0", + "stream-chat": "^8.20.0", "ts-node": "^10.2.1", "tslib": "^2.3.0", "uuidv4": "^6.2.12", diff --git a/projects/stream-chat-angular/package.json b/projects/stream-chat-angular/package.json index 2b674fac..c9cd0cfd 100644 --- a/projects/stream-chat-angular/package.json +++ b/projects/stream-chat-angular/package.json @@ -12,7 +12,7 @@ "@angular/common": "^12.2.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "@angular/core": "^12.2.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "@ngx-translate/core": "^13.0.0 || ^14.0.0 || ^15.0.0", - "stream-chat": "^8.15.0" + "stream-chat": "^8.20.0" }, "dependencies": { "angular-mentions": "^1.4.0", diff --git a/projects/stream-chat-angular/src/assets/i18n/en.ts b/projects/stream-chat-angular/src/assets/i18n/en.ts index 3edb7884..f4c5fea1 100644 --- a/projects/stream-chat-angular/src/assets/i18n/en.ts +++ b/projects/stream-chat-angular/src/assets/i18n/en.ts @@ -117,5 +117,6 @@ export const en = { 'This message did not meet our content guidelines': 'This message did not meet our content guidelines', 'Send Anyway': 'Send Anyway', + Edited: 'Edited', }, }; diff --git a/projects/stream-chat-angular/src/lib/message-list/group-styles.spec.ts b/projects/stream-chat-angular/src/lib/message-list/group-styles.spec.ts index d7267cb7..0b0fa541 100644 --- a/projects/stream-chat-angular/src/lib/message-list/group-styles.spec.ts +++ b/projects/stream-chat-angular/src/lib/message-list/group-styles.spec.ts @@ -131,4 +131,14 @@ describe('getGroupStyles', () => { ) ).toBe('top'); }); + + it('should end group if the message id edited', () => { + messages[1].message_text_updated_at = new Date().toISOString(); + + expect(getGroupStyles(messages[1], messages[0], messages[2])).toBe( + 'bottom' + ); + + expect(getGroupStyles(messages[2], messages[1], messages[3])).toBe('top'); + }); }); diff --git a/projects/stream-chat-angular/src/lib/message-list/group-styles.ts b/projects/stream-chat-angular/src/lib/message-list/group-styles.ts index 823d8827..3c1c9157 100644 --- a/projects/stream-chat-angular/src/lib/message-list/group-styles.ts +++ b/projects/stream-chat-angular/src/lib/message-list/group-styles.ts @@ -25,6 +25,7 @@ export const getGroupStyles = ( previousMessage.type === 'error' || previousMessage.deleted_at || previousMessage.id === lastReadMessageId || + previousMessage.message_text_updated_at || (message.reaction_counts && Object.keys(message.reaction_counts).length > 0); @@ -37,6 +38,7 @@ export const getGroupStyles = ( nextMessage.type === 'error' || nextMessage.deleted_at || message.id === lastReadMessageId || + message.message_text_updated_at || (nextMessage.reaction_counts && Object.keys(nextMessage.reaction_counts).length > 0); diff --git a/projects/stream-chat-angular/src/lib/message/message.component.html b/projects/stream-chat-angular/src/lib/message/message.component.html index 4113b88b..b59162bf 100644 --- a/projects/stream-chat-angular/src/lib/message/message.component.html +++ b/projects/stream-chat-angular/src/lib/message/message.component.html @@ -175,6 +175,15 @@ class="str-chat__message-text" tabindex="0" *ngIf="message?.text || (message?.quoted_message && hasAttachment)" + [class.str-chat__message-text--pointer-cursor]=" + (message?.status === 'failed' && + message?.errorStatusCode !== 403) || + (this.message?.type === 'error' && + this.message?.moderation_details) || + message?.message_text_updated_at + " + (click)="messageClicked()" + (keyup.enter)="messageClicked()" >
@@ -459,9 +466,36 @@ > {{ message?.user?.name ? message?.user?.name : message?.user?.id }} - + {{ parsedDate }} + + streamChat.Edited +
+ streamChat.Edited + +
+
diff --git a/projects/stream-chat-angular/src/lib/message/message.component.spec.ts b/projects/stream-chat-angular/src/lib/message/message.component.spec.ts index 4e58621b..12ebf590 100644 --- a/projects/stream-chat-angular/src/lib/message/message.component.spec.ts +++ b/projects/stream-chat-angular/src/lib/message/message.component.spec.ts @@ -1347,4 +1347,37 @@ describe('MessageComponent', () => { ' https://getstream.io/' ); }); + + it(`shouldn't display edited flag if message wasn't edited`, () => { + expect( + nativeElement.querySelector('[data-testid="edited-flag"]') + ).toBeNull(); + }); + + it(`should display edited flag if message was edited, edited info should be collapsed`, () => { + component.message!.message_text_updated_at = new Date().toISOString(); + component.ngOnChanges({ message: {} as SimpleChange }); + fixture.detectChanges(); + + expect( + nativeElement.querySelector('[data-testid="edited-flag"]') + ).not.toBeNull(); + + expect( + nativeElement.querySelector('[data-testid="edited-timestamp"]') + ).not.toBeNull(); + }); + + it(`should display edited flag if message was edited, display timestamp if clicked`, () => { + component.message!.message_text_updated_at = new Date().toISOString(); + component.ngOnChanges({ message: {} as SimpleChange }); + fixture.detectChanges(); + queryMessageInner()?.click(); + fixture.detectChanges(); + const timestamp = nativeElement.querySelector( + '[data-testid="edited-timestamp"]' + ); + + expect(timestamp?.innerHTML).toContain(component.pasedEditedDate); + }); }); diff --git a/projects/stream-chat-angular/src/lib/message/message.component.ts b/projects/stream-chat-angular/src/lib/message/message.component.ts index 8b40e09e..13c95220 100644 --- a/projects/stream-chat-angular/src/lib/message/message.component.ts +++ b/projects/stream-chat-angular/src/lib/message/message.component.ts @@ -91,6 +91,7 @@ export class MessageComponent canReceiveReadEvents: boolean | undefined; canReactToMessage: boolean | undefined; isActionBoxOpen = false; + isEditedFlagOpened = false; isReactionSelectorOpen = false; visibleMessageActionsCount = 0; messageTextParts: MessagePart[] | undefined = []; @@ -110,6 +111,7 @@ export class MessageComponent isReadByMultipleUsers = false; isMessageDeliveredAndRead = false; parsedDate = ''; + pasedEditedDate = ''; areOptionsVisible = false; hasAttachment = false; hasReactions = false; @@ -194,6 +196,13 @@ export class MessageComponent this.message.created_at && this.dateParser.parseDateTime(this.message.created_at)) || ''; + this.pasedEditedDate = + (this.message && + this.message.message_text_updated_at && + this.dateParser.parseDateTime( + new Date(this.message.message_text_updated_at) + )) || + ''; this.hasAttachment = !!this.message?.attachments && !!this.message.attachments.length; this.hasReactions = @@ -314,7 +323,7 @@ export class MessageComponent }; } - unsentMessageClicked() { + messageClicked() { if ( this.message?.status === 'failed' && this.message?.errorStatusCode !== 403 @@ -325,6 +334,8 @@ export class MessageComponent this.message?.moderation_details ) { this.openMessageBouncePrompt(); + } else { + this.isEditedFlagOpened = !this.isEditedFlagOpened; } }