Skip to content

Conversation

@e-maad
Copy link
Contributor

@e-maad e-maad commented Mar 12, 2025

StoryWPB-15758 [Web] Start a channel

Description

Added conversation creation flow

Checklist

  • mentions the JIRA issue in the PR name (Ex. [WPB-XXXX])
  • PR has been self reviewed by the author;
  • Hard-to-understand areas of the code have been commented;
  • If it is a core feature, unit tests have been added;

@e-maad e-maad changed the title feat: add conversation creation flow [WPB-15758] feat: add channels [WPB-15758] Mar 25, 2025
@e-maad e-maad marked this pull request as ready for review March 26, 2025 11:29
@e-maad e-maad requested review from a team and otto-the-bot as code owners March 26, 2025 11:29
Comment on lines +180 to +181
{isChannel &&
(isChannelsEnabled ? (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an edgecase we need to worry about where channels exist but are not enabled on the client?

Copy link
Contributor Author

@e-maad e-maad Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, including both sides (BE and FE) feature flags.

@@ -0,0 +1,55 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@@ -0,0 +1,49 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@@ -17,8 +17,6 @@
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@@ -19,16 +19,19 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@@ -439,7 +439,7 @@ export const Conversation = ({
if (conversationEntity.is1to1()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@@ -0,0 +1,89 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@@ -0,0 +1,72 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@e-maad e-maad requested a review from V-Gira April 2, 2025 06:52
Comment on lines +187 to +195
/** Feature to enable channels */
FEATURE_ENABLE_CHANNELS: string;

/** Feature to enable channels history sharing */
FEATURE_ENABLE_CHANNELS_HISTORY_SHARING: string;

/** Feature to enable channels public channels */
FEATURE_ENABLE_PUBLIC_CHANNELS: string;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different feature flag for each feature to follow the rollout strategy.

Comment on lines +276 to +279
this.isGroupOrChannel = ko.pureComputed(() => {
return this.isGroup() || this.isChannel();
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole app was designed to support group conversations before, Channel is also a group conversation.
But now we treat Channels separately, we introduced another property isGroupOrChannel to refer all types of group conversations.

Comment on lines +20 to +135
import {create} from 'zustand';

import {User} from 'src/script/entity/User';

import {
ConversationAccess,
ConversationModerator,
ChatHistory,
ConversationType,
ConversationCreationStep,
HistorySharingUnit,
} from '../types';

/**
* Type representing the state of the Create Conversation Modal.
*/
type CreateConversationModalState = {
isOpen?: boolean;
conversationName: string;
access: ConversationAccess;
moderator: ConversationModerator;
chatHistory: ChatHistory;
conversationType: ConversationType;
conversationCreationStep: ConversationCreationStep;
error: string;
isReadReceiptsEnabled: boolean;
isGuestsEnabled: boolean;
selectedContacts: User[];
historySharingQuantity: number;
historySharingUnit: HistorySharingUnit;
isCustomHistoryModalOpen: boolean;
isConfirmConversationTypeModalOpen: boolean;
isCreateTeamModalOpen: boolean;
isUpgradeTeamModalOpen: boolean;
isServicesEnabled: boolean;

showModal: () => void;
hideModal: () => void;
setConversationName: (name: string) => void;
setAccess: (access: ConversationAccess) => void;
setModerator: (access: ConversationModerator) => void;
setChatHistory: (history: ChatHistory) => void;
setConversationType: (type: ConversationType) => void;
setConversationCreationStep: (step: ConversationCreationStep) => void;
gotoNextStep: () => void;
gotoPreviousStep: () => void;
setError: (error: string) => void;
setIsReadReceiptsEnabled: (isReadReceiptsEnabled: boolean) => void;
setIsGuestsEnabled: (isGuestsEnabled: boolean) => void;
setSelectedContacts: (contacts: User[]) => void;
setHistorySharingQuantity: (quantity: number) => void;
setHistorySharingUnit: (unit: HistorySharingUnit) => void;
setIsCustomHistoryModalOpen: (isOpen: boolean) => void;
setIsConfirmConversationTypeModalOpen: (isOpen: boolean) => void;
setIsCreateTeamModalOpen: (isOpen: boolean) => void;
setIsUpgradeTeamModalOpen: (isOpen: boolean) => void;
gotoLastStep: () => void;
setIsServicesEnabled: (isServicesEnabled: boolean) => void;
};

/**
* Initial state of the Create Conversation Modal.
*/
const initialState = {
isOpen: false,
conversationName: '',
access: ConversationAccess.Private,
moderator: ConversationModerator.AdminsAndMembers,
chatHistory: ChatHistory.Off,
conversationType: ConversationType.Channel,
conversationCreationStep: ConversationCreationStep.ConversationDetails,
error: '',
isReadReceiptsEnabled: true,
isServicesEnabled: true,
isGuestsEnabled: true,
selectedContacts: [] as User[],
historySharingUnit: HistorySharingUnit.Days,
historySharingQuantity: 1,
isCustomHistoryModalOpen: false,
isConfirmConversationTypeModalOpen: false,
isCreateTeamModalOpen: false,
isUpgradeTeamModalOpen: false,
};

/**
* Hook to manage the state of the Create Conversation Modal.
*/
export const useCreateConversationModal = create<CreateConversationModalState>(set => ({
...initialState,
showModal: () => set(state => ({...state, isOpen: true})),
hideModal: () => set({...initialState}),
setConversationName: (name: string) => set({conversationName: name}),
setAccess: (access: ConversationAccess) =>
set(state => ({
access,
manager: access === ConversationAccess.Public ? ConversationModerator.AdminsAndMembers : state.moderator,
})),
setModerator: (moderator: ConversationModerator) => set({moderator}),
setChatHistory: (history?: ChatHistory) => set({chatHistory: history || ChatHistory.Off}),
setConversationType: (type: ConversationType) => set({conversationType: type}),
setConversationCreationStep: (step: ConversationCreationStep) => set({conversationCreationStep: step}),
gotoNextStep: () => set(state => ({...state, conversationCreationStep: state.conversationCreationStep + 1})),
gotoLastStep: () => set({conversationCreationStep: ConversationCreationStep.ParticipantsSelection}),
gotoPreviousStep: () => set(state => ({...state, conversationCreationStep: state.conversationCreationStep - 1})),
setError: (error: string) => set({error}),
setIsReadReceiptsEnabled: (isReadReceiptsEnabled: boolean) => set({isReadReceiptsEnabled}),
setIsGuestsEnabled: (isGuestsEnabled: boolean) => set({isGuestsEnabled}),
setSelectedContacts: (contacts: User[]) => set({selectedContacts: contacts}),
setHistorySharingQuantity: (quantity: number) => set({historySharingQuantity: quantity}),
setHistorySharingUnit: (unit: HistorySharingUnit) => set({historySharingUnit: unit}),
setIsCustomHistoryModalOpen: (isOpen: boolean) => set({isCustomHistoryModalOpen: isOpen}),
setIsConfirmConversationTypeModalOpen: (isOpen: boolean) => set({isConfirmConversationTypeModalOpen: isOpen}),
setIsCreateTeamModalOpen: (isOpen: boolean) => set({isCreateTeamModalOpen: isOpen}),
setIsUpgradeTeamModalOpen: (isOpen: boolean) => set({isUpgradeTeamModalOpen: isOpen}),
setIsServicesEnabled: (isServicesEnabled: boolean) => set({isServicesEnabled}),
}));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an encapsulated state of CreateConversationModal, including all the inputs taken during the flow.

return access;
};

const onSubmit = async (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: there's a lot logic in here, I would consider splitting it to multiple functions

Copy link
Contributor Author

@e-maad e-maad Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just moved this functionality, will look into it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have a look.

@e-maad e-maad requested a review from olafsulich April 2, 2025 10:20
@sonarqubecloud
Copy link

sonarqubecloud bot commented Apr 2, 2025

@e-maad e-maad merged commit 9615f57 into dev Apr 2, 2025
14 of 15 checks passed
@e-maad e-maad deleted the feat/channels branch April 2, 2025 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants