From 64f8c8d4185d2a450d333121a4e7ed1c70db5ba9 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Thu, 24 Mar 2022 09:50:57 +0100 Subject: [PATCH] feat: Remove custom action names and mute action **BREAKING CHANGE** see our documentation on how to upgrade --- docusaurus/docs/Angular/basics/upgrade-v2.mdx | 14 ++++ .../message-action.component.ts | 3 +- .../message-actions-box.component.spec.ts | 80 +++++++++---------- .../message-actions-box.component.ts | 22 +---- .../src/lib/message/message.component.spec.ts | 8 +- projects/stream-chat-angular/src/lib/types.ts | 4 +- 6 files changed, 63 insertions(+), 68 deletions(-) diff --git a/docusaurus/docs/Angular/basics/upgrade-v2.mdx b/docusaurus/docs/Angular/basics/upgrade-v2.mdx index d3d704e3..82ee8f1b 100644 --- a/docusaurus/docs/Angular/basics/upgrade-v2.mdx +++ b/docusaurus/docs/Angular/basics/upgrade-v2.mdx @@ -63,3 +63,17 @@ The `notification$` stream on the [`ChatClientService`](../services/ChatClientSe The `events$` stream emits the received [client, notification and user presence events](https://getstream.io/chat/docs/javascript/event_object/?language=javascript). The payload of this Observable was renamed from `Notification` to `ClientEvent`. + +## Custom action names removed + +Use our [permission framework](https://getstream.io/chat/docs/javascript/chat_permission_policies/?language=javascript&q=slow%20mode) to control the authorization of the following message actions: + +| Custom action name | Channel capability | Comment | +| ------------------ | -------------------- | -------------------------------------------- | +| `quote` | `quote-message` | | +| `pin` | `pin-message` | Currently turned off because not implemented | +| `flag` | `flag-message` | | +| `edit` | `update-own-message` | | +| `edit-any` | `update-any-message` | | + +The `mute` action is removed. diff --git a/projects/customizations-example/src/app/message-action/message-action.component.ts b/projects/customizations-example/src/app/message-action/message-action.component.ts index e8a28d12..2b085615 100644 --- a/projects/customizations-example/src/app/message-action/message-action.component.ts +++ b/projects/customizations-example/src/app/message-action/message-action.component.ts @@ -6,7 +6,7 @@ import { Component, Input } from '@angular/core'; styleUrls: ['./message-action.component.scss'], }) export class MessageActionComponent { - @Input() actionName!: 'quote' | 'pin' | 'flag' | 'mute' | 'edit' | 'delete'; + @Input() actionName!: 'quote' | 'pin' | 'flag' | 'edit' | 'delete'; @Input() actionLabelOrTranslationKey!: (() => string) | string; @Input() actionHandler!: () => any; @@ -19,7 +19,6 @@ export class MessageActionComponent { delete: 'delete', flag: 'flag', pin: 'push_pin', - mute: 'volume_mute', }; return iconMapping[this.actionName]; } diff --git a/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.spec.ts b/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.spec.ts index 65c64e9f..a0dfc024 100644 --- a/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.spec.ts +++ b/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.spec.ts @@ -154,19 +154,23 @@ describe('MessageActionsBoxComponent', () => { expect(queryFlagAction()).toBeNull(); expect(queryQuoteAction()).toBeNull(); - component.enabledActions = ['pin', 'edit-any', 'delete-any']; + component.enabledActions = [ + 'pin-message', + 'update-any-message', + 'delete-any', + ]; component.ngOnChanges({ enabledActions: {} as SimpleChange }); fixture.detectChanges(); expect(queryDeleteAction()).not.toBeNull(); expect(queryEditAction()).not.toBeNull(); - expect(queryPinAction()).not.toBeNull(); + expect(queryPinAction()).toBeNull(); expect(queryMuteAction()).toBeNull(); expect(queryFlagAction()).toBeNull(); expect(queryQuoteAction()).toBeNull(); }); - it(`should only display 'flag' action for other user's messages`, () => { + it(`should only display 'flag-message' action for other user's messages`, () => { component.enabledActions = ['flag-message']; component.isMine = false; component.ngOnChanges({ @@ -187,7 +191,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should handle quote action', () => { - component.enabledActions = ['quote']; + component.enabledActions = ['quote-message']; component.ngOnChanges({ enabledActions: {} as SimpleChange }); fixture.detectChanges(); const spy = TestBed.inject(ChannelService).selectMessageToQuote; @@ -211,7 +215,7 @@ describe('MessageActionsBoxComponent', () => { ...component.message!, quoted_message: mockMessage() as any as MessageResponseBase, }; - component.enabledActions = ['quote']; + component.enabledActions = ['quote-message']; component.ngOnChanges({ message: {} as SimpleChange, enabledActions: {} as SimpleChange, @@ -221,9 +225,10 @@ describe('MessageActionsBoxComponent', () => { expect(queryQuoteAction()).toBeNull(); }); - it('should display the pin action label correctly', () => { + // eslint-disable-next-line jasmine/no-disabled-tests + xit('should display the pin action label correctly', () => { component.message = { ...message, ...{ pinned: false } }; - component.enabledActions = ['pin']; + component.enabledActions = ['pin-message']; component.ngOnChanges({ message: {} as SimpleChange, enabledActions: {} as SimpleChange, @@ -240,8 +245,9 @@ describe('MessageActionsBoxComponent', () => { expect(pinAction?.textContent).toContain('Unpin'); }); - it('should handle pin action', () => { - component.enabledActions = ['pin']; + // eslint-disable-next-line jasmine/no-disabled-tests + xit('should handle pin action', () => { + component.enabledActions = ['pin-message']; component.ngOnChanges({ enabledActions: {} as SimpleChange }); fixture.detectChanges(); spyOn(window, 'alert').and.callThrough(); @@ -252,24 +258,10 @@ describe('MessageActionsBoxComponent', () => { expect(window.alert).toHaveBeenCalledWith(jasmine.anything()); }); - it('should handle mute action', () => { - component.enabledActions = ['mute']; - component.ngOnChanges({ - enabledActions: {} as SimpleChange, - }); - fixture.detectChanges(); - spyOn(window, 'alert').and.callThrough(); - const action = queryMuteAction(); - action?.click(); - fixture.detectChanges(); - - expect(window.alert).toHaveBeenCalledWith(jasmine.anything()); - }); - it('should handle flag action', async () => { const notificationService = TestBed.inject(NotificationService); spyOn(notificationService, 'addTemporaryNotification'); - component.enabledActions = ['flag']; + component.enabledActions = ['flag-message']; component.ngOnChanges({ enabledActions: {} as SimpleChange }); fixture.detectChanges(); const action = queryFlagAction(); @@ -288,7 +280,7 @@ describe('MessageActionsBoxComponent', () => { const notificationService = TestBed.inject(NotificationService); spyOn(notificationService, 'addTemporaryNotification'); mockChatClient.flagMessage.and.rejectWith(); - component.enabledActions = ['flag']; + component.enabledActions = ['flag-message']; component.ngOnChanges({ enabledActions: {} as SimpleChange }); fixture.detectChanges(); const action = queryFlagAction(); @@ -304,10 +296,10 @@ describe('MessageActionsBoxComponent', () => { it('should emit the number of displayed actions', () => { component.enabledActions = [ - 'pin', + 'pin-message', 'update-own-message', 'delete-own-message', - 'flag', + 'flag-message', ]; component.isMine = true; const spy = jasmine.createSpy(); @@ -318,16 +310,15 @@ describe('MessageActionsBoxComponent', () => { }); fixture.detectChanges(); - expect(spy).toHaveBeenCalledWith(3); + expect(spy).toHaveBeenCalledWith(2); spy.calls.reset(); component.enabledActions = [ - 'pin', + 'pin-message', 'update-any-message', 'delete', - 'flag', - 'quote', - 'mute', + 'flag-message', + 'quote-message', ]; component.isMine = false; component.ngOnChanges({ @@ -336,12 +327,12 @@ describe('MessageActionsBoxComponent', () => { }); fixture.detectChanges(); - expect(spy).toHaveBeenCalledWith(5); + expect(spy).toHaveBeenCalledWith(3); }); describe('should display edit action', () => { it('if #enabledActions contains "edit" and #isMine', () => { - component.enabledActions = ['edit']; + component.enabledActions = ['update-own-message']; component.isMine = false; component.ngOnChanges({ enabledActions: {} as SimpleChange, @@ -359,7 +350,7 @@ describe('MessageActionsBoxComponent', () => { }); it('if #enabledActions contains "edit-any"', () => { - component.enabledActions = ['edit-any']; + component.enabledActions = ['update-any-message']; component.isMine = false; component.ngOnChanges({ enabledActions: {} as SimpleChange, @@ -408,7 +399,12 @@ describe('MessageActionsBoxComponent', () => { it('should emit #isEditing if user starts to edit', () => { const spy = jasmine.createSpy(); component.isEditing.subscribe(spy); - component.enabledActions = ['pin', 'edit-any', 'delete', 'flag']; + component.enabledActions = [ + 'pin-message', + 'update-any-message', + 'delete', + 'flag-message', + ]; component.ngOnChanges({ enabledActions: {} as SimpleChange, }); @@ -420,7 +416,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should open modal if user starts to edit', () => { - component.enabledActions = ['edit']; + component.enabledActions = ['update-own-message']; component.isMine = true; component.ngOnChanges({ enabledActions: {} as SimpleChange, @@ -434,7 +430,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should display message input if user starts to edit', () => { - component.enabledActions = ['edit-any']; + component.enabledActions = ['update-any-message']; component.ngOnChanges({ enabledActions: {} as SimpleChange, }); @@ -446,7 +442,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should call update message if "Send" button is clicked', () => { - component.enabledActions = ['edit-any']; + component.enabledActions = ['update-any-message']; component.isEditModalOpen = true; component.ngOnChanges({ enabledActions: {} as SimpleChange, @@ -463,7 +459,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should close modal with "Cancel" button', () => { - component.enabledActions = ['edit']; + component.enabledActions = ['update-own-message']; component.isMine = true; component.ngOnChanges({ enabledActions: {} as SimpleChange, @@ -482,7 +478,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should update #isEditModalOpen if modal is closed', () => { - component.enabledActions = ['edit']; + component.enabledActions = ['update-own-message']; component.isMine = true; component.isEditModalOpen = true; component.ngOnChanges({ @@ -502,7 +498,7 @@ describe('MessageActionsBoxComponent', () => { }); it('should close modal if message was updated successfully', () => { - component.enabledActions = ['edit']; + component.enabledActions = ['update-own-message']; component.isMine = true; component.ngOnChanges({ enabledActions: {} as SimpleChange, diff --git a/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.ts b/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.ts index 1cf14594..4b7e8c6b 100644 --- a/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.ts +++ b/projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.ts @@ -101,8 +101,7 @@ export class MessageActionsBoxComponent implements OnChanges, OnDestroy { isMine: boolean, message: StreamMessage ) => - (enabledActions.indexOf('quote') !== -1 || - enabledActions.indexOf('quote-message') !== -1) && + enabledActions.indexOf('quote-message') !== -1 && !message?.quoted_message, }, { @@ -110,8 +109,7 @@ export class MessageActionsBoxComponent implements OnChanges, OnDestroy { actionLabelOrTranslationKey: () => this.message?.pinned ? 'streamChat.Unpin' : 'streamChat.Pin', actionHandler: () => alert('Feature not yet implemented'), - isVisible: (enabledActions: string[]) => - enabledActions.indexOf('pin') !== -1, + isVisible: () => false, }, { actionName: 'flag', @@ -130,16 +128,7 @@ export class MessageActionsBoxComponent implements OnChanges, OnDestroy { } }, isVisible: (enabledActions: string[], isMine: boolean) => - (enabledActions.indexOf('flag') !== -1 || - enabledActions.indexOf('flag-message') !== -1) && - !isMine, - }, - { - actionName: 'mute', - actionLabelOrTranslationKey: 'streamChat.Mute', - actionHandler: () => alert('Feature not yet implemented'), - isVisible: (enabledActions: string[]) => - enabledActions.indexOf('mute') !== -1, + enabledActions.indexOf('flag-message') !== -1 && !isMine, }, { actionName: 'edit', @@ -149,10 +138,7 @@ export class MessageActionsBoxComponent implements OnChanges, OnDestroy { this.isEditModalOpen = true; }, isVisible: (enabledActions: string[], isMine: boolean) => - ((enabledActions.indexOf('edit') !== -1 || - enabledActions.indexOf('update-own-message') !== -1) && - isMine) || - enabledActions.indexOf('edit-any') !== -1 || + (enabledActions.indexOf('update-own-message') !== -1 && isMine) || enabledActions.indexOf('update-any-message') !== -1, }, { 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 2851fefe..6b68ed67 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 @@ -456,14 +456,14 @@ describe('MessageComponent', () => { }); it(`shouldn't display message actions if there is no visible message action`, () => { - component.enabledMessageActions = ['flag']; + component.enabledMessageActions = ['flag-message']; fixture.detectChanges(); expect(queryActionIcon()).toBeNull(); }); it('should open and close message actions box', () => { - component.enabledMessageActions = ['edit', 'flag']; + component.enabledMessageActions = ['update-own-message', 'flag-message']; fixture.detectChanges(); expect(messageActionsBoxComponent.isOpen).toBeFalse(); @@ -475,7 +475,7 @@ describe('MessageComponent', () => { }); it('should close message actions box on mouseleave event', () => { - component.enabledMessageActions = ['edit', 'flag']; + component.enabledMessageActions = ['update-own-message', 'flag-message']; component.isActionBoxOpen = true; fixture.detectChanges(); @@ -906,7 +906,7 @@ describe('MessageComponent', () => { describe('in thread mode', () => { beforeEach(() => { component.mode = 'thread'; - component.enabledMessageActions = ['edit', 'delete']; + component.enabledMessageActions = ['update-own-message', 'delete']; component.ngOnChanges({ enabledMessageActions: {} as SimpleChange, }); diff --git a/projects/stream-chat-angular/src/lib/types.ts b/projects/stream-chat-angular/src/lib/types.ts index 02a7b668..f5747fb2 100644 --- a/projects/stream-chat-angular/src/lib/types.ts +++ b/projects/stream-chat-angular/src/lib/types.ts @@ -192,13 +192,13 @@ export type MessageActionsBoxContext = { }; export type MessageActionBoxItemContext = { - actionName: 'quote' | 'pin' | 'flag' | 'mute' | 'edit' | 'delete'; + actionName: 'quote' | 'pin' | 'flag' | 'edit' | 'delete'; actionLabelOrTranslationKey: (() => string) | string; actionHandler: () => any; }; export type MessageActionItem = { - actionName: 'quote' | 'pin' | 'flag' | 'mute' | 'edit' | 'delete'; + actionName: 'quote' | 'pin' | 'flag' | 'edit' | 'delete'; actionLabelOrTranslationKey: (() => string) | string; isVisible: ( enabledActions: string[],