/* * Wire * Copyright (C) 2024 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import {useMemo} from 'react'; import cx from 'classnames'; import * as Icons from 'Components/Icon'; import {Config} from 'src/script/Config'; import {createLabel, LabelType} from 'src/script/conversation/ConversationLabelRepository'; import {ConversationRepository} from 'src/script/conversation/ConversationRepository'; import {Conversation} from 'src/script/entity/Conversation'; import {useFolderStore} from 'src/script/page/LeftSidebar/panels/Conversations/useFoldersStore'; import { SidebarStatus, SidebarTabs, useSidebarStore, } from 'src/script/page/LeftSidebar/panels/Conversations/useSidebarStore'; import {ContextMenuEntry, showContextMenu} from 'src/script/ui/ContextMenu'; import {useKoSubscribableChildren} from 'Util/ComponentUtil'; import {t} from 'Util/LocalizerUtil'; interface ConversationFolderTabProps { title: string; label?: string; type: SidebarTabs; conversationTabIndex: number; onChangeTab: (tab: SidebarTabs, folderId?: string) => void; Icon: JSX.Element; dataUieName: string; unreadConversations: Conversation[]; conversationRepository: ConversationRepository; isActive?: boolean; } export const ConversationFolderTab = ({ title, label, type, conversationTabIndex, onChangeTab, Icon, conversationRepository, unreadConversations = [], dataUieName, }: ConversationFolderTabProps) => { const {status: sidebarStatus} = useSidebarStore(); const {openFolder, isFoldersTabOpen, toggleFoldersTab, expandedFolder} = useFolderStore(); const {conversationLabelRepository} = conversationRepository; const isSideBarOpen = sidebarStatus === SidebarStatus.OPEN; function toggleFolder(folderId: string) { openFolder(folderId); onChangeTab(type, folderId); } const {labels} = useKoSubscribableChildren(conversationLabelRepository, ['labels']); const folders = labels .filter(label => label.type !== LabelType.Favorite) .map(label => createLabel(label.name, conversationLabelRepository.getLabelConversations(label), label.id)) .filter(({conversations, name}) => !!conversations().length && !!name); const placeholder = useMemo( () => (
{t('conversationFoldersEmptyText')} {t('conversationFoldersEmptyTextLearnMore')}
), [], ); function openFoldersContextMenu(event: React.MouseEvent) { const entries: ContextMenuEntry[] = folders.map(folder => ({ click: () => { openFolder(folder.id); onChangeTab(type, folder.id); }, identifier: `folder-${folder.id}`, label: folder.name, })); const boundingRect = event.currentTarget.getBoundingClientRect(); event.clientX = boundingRect.right + 4; event.clientY = boundingRect.top; showContextMenu({event, entries, identifier: 'navigation-folders-menu', placeholder}); } function handleToggleFoldersTab(event: React.MouseEvent) { if (isSideBarOpen) { toggleFoldersTab(); return; } openFoldersContextMenu(event); } function getTotalUnreadConversationMessages(conversations: Conversation[]) { let total = 0; conversations.forEach(conversation => { const exists = unreadConversations.some(conv => conv.id === conversation.id); if (exists) { total += 1; } }); return total; } return (
{folders.length === 0 && placeholder} {folders.map(folder => { const unreadCount = getTotalUnreadConversationMessages(folder.conversations()); const isActive = folder.id === expandedFolder; return ( ); })}
); };