chore: Enable Participating tab for conversations (#11714)

## Summary

This PR enables the **Participating** conversation view in the main
sidebar and keeps the behavior aligned with existing conversation views.

## What changed

- Added **Participating** under Conversations in the new sidebar.
- Added a guard in conversation realtime `addConversation` flow so
generic `conversation.created` events are not injected while the user is
on Participating view.
- Added participating route mapping in conversation-list redirect helper
so list redirects resolve correctly to `/participating/conversations`.

## Scope notes

- Kept changes minimal and consistent with current `develop` behavior.
- No additional update-event filtering was added beyond what existing
views already do.

---------


Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
This commit is contained in:
Sojan Jose
2026-04-15 17:03:39 +05:30
committed by GitHub
parent 3f9f054c43
commit b96bf41234
13 changed files with 216 additions and 9 deletions

View File

@@ -6,6 +6,7 @@ import { createPendingMessage } from 'dashboard/helper/commons';
import {
buildConversationList,
isOnMentionsView,
isOnParticipatingView,
isOnUnattendedView,
isOnFoldersView,
} from './helpers/actionHelpers';
@@ -371,6 +372,7 @@ const actions = {
!hasAppliedFilters &&
!isOnFoldersView(rootState) &&
!isOnMentionsView(rootState) &&
!isOnParticipatingView(rootState) &&
!isOnUnattendedView(rootState) &&
isMatchingInboxFilter
) {
@@ -395,6 +397,7 @@ const actions = {
const {
meta: { sender },
} = conversation;
commit(types.UPDATE_CONVERSATION, conversation);
dispatch('conversationLabels/setConversationLabel', {

View File

@@ -102,6 +102,19 @@ const getters = {
return isUnAssigned && shouldFilter;
});
},
getParticipatingChats: (_state, _, __, rootGetters) => activeFilters => {
const currentUserId = rootGetters.getCurrentUser?.id;
const getWatchers = rootGetters['conversationWatchers/getByConversationId'];
return _state.allConversations.filter(conversation => {
const watchers = getWatchers(conversation.id);
// Watchers are only loaded for the conversation open in the detail
// panel. If loaded and current user is not in them, filter it out.
if (watchers && !watchers.some(w => w.id === currentUserId)) {
return false;
}
return applyPageFilters(conversation, activeFilters);
});
},
getAllStatusChats: (_state, _, __, rootGetters) => activeFilters => {
const currentUser = rootGetters.getCurrentUser;
const currentUserId = rootGetters.getCurrentUser.id;

View File

@@ -30,6 +30,14 @@ export const isOnUnattendedView = ({ route: { name: routeName } }) => {
return UNATTENDED_ROUTES.includes(routeName);
};
export const isOnParticipatingView = ({ route: { name: routeName } }) => {
const PARTICIPATING_ROUTES = [
'conversation_participating',
'conversation_through_participating',
];
return PARTICIPATING_ROUTES.includes(routeName);
};
export const isOnFoldersView = ({ route: { name: routeName } }) => {
const FOLDER_ROUTES = [
'folder_conversations',

View File

@@ -1,4 +1,8 @@
import { isOnMentionsView, isOnFoldersView } from '../actionHelpers';
import {
isOnMentionsView,
isOnFoldersView,
isOnParticipatingView,
} from '../actionHelpers';
describe('#isOnMentionsView', () => {
it('return valid responses when passing the state', () => {
@@ -24,3 +28,19 @@ describe('#isOnFoldersView', () => {
);
});
});
describe('#isOnParticipatingView', () => {
it('return valid responses when passing the state', () => {
expect(
isOnParticipatingView({ route: { name: 'conversation_participating' } })
).toBe(true);
expect(
isOnParticipatingView({
route: { name: 'conversation_through_participating' },
})
).toBe(true);
expect(
isOnParticipatingView({ route: { name: 'conversation_messages' } })
).toBe(false);
});
});

View File

@@ -258,7 +258,11 @@ export const mutations = {
emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE);
}
} else {
_state.allConversations.push(conversation);
const { conversationType } = _state.conversationFilters || {};
const { MENTION, PARTICIPATING } = wootConstants.CONVERSATION_TYPE;
if (![MENTION, PARTICIPATING].includes(conversationType)) {
_state.allConversations.push(conversation);
}
}
},