From 709a35cb02b42ae6302340e8c0c2740199e792ef Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 13 Jan 2023 19:24:51 +0100 Subject: [PATCH] Forums: Various fixes 6 (#2273) --- src/api/gramjs/apiBuilders/messages.ts | 7 +++- src/api/gramjs/methods/chats.ts | 3 +- src/api/types/messages.ts | 1 + .../helpers/renderActionMessageText.tsx | 28 ++++++++++++--- .../left/main/hooks/useTopicContextActions.ts | 6 ++-- src/components/right/EditTopic.tsx | 3 +- src/global/actions/api/chats.ts | 34 +++++++++++-------- 7 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index 12b39124d..c5e6dfa58 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -879,6 +879,7 @@ function buildAction( let photo: ApiPhoto | undefined; let score: number | undefined; let months: number | undefined; + let topicEmojiIconId: string | undefined; const targetUserIds = 'users' in action ? action.users && action.users.map((id) => buildApiPeerId(id, 'user')) @@ -1036,8 +1037,11 @@ function buildAction( } else if (action.title) { text = 'TopicRenamedTo'; translationValues.push('%action_origin%', action.title); + } else if (action.iconEmojiId) { + text = 'TopicWasIconChangedToAction'; + translationValues.push('%action_origin%', '%action_topic_icon%'); + topicEmojiIconId = action.iconEmojiId.toString(); } else { - // TODO[forums] Support icon changed action text = 'ChatList.UnsupportedMessage'; } } else { @@ -1062,6 +1066,7 @@ function buildAction( phoneCall, score, months, + topicEmojiIconId, }; } diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index 5cfc4e292..4078ec653 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -26,6 +26,7 @@ import { ALL_FOLDER_ID, MAX_INT_32, TOPICS_SLICE, + GENERAL_TOPIC_ID, } from '../../../config'; import { invokeRequest, uploadFile } from './client'; import { @@ -1516,7 +1517,7 @@ export function editTopic({ channel: buildInputPeer(id, accessHash), topicId, title, - iconEmojiId: BigInt(iconEmojiId || '0'), + iconEmojiId: topicId !== GENERAL_TOPIC_ID && iconEmojiId ? BigInt(iconEmojiId) : undefined, closed: isClosed, hidden: isHidden, }), true); diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index 493489244..4d943d2ce 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -268,6 +268,7 @@ export interface ApiAction { phoneCall?: PhoneCallAction; score?: number; months?: number; + topicEmojiIconId?: string; } export interface ApiWebPage { diff --git a/src/components/common/helpers/renderActionMessageText.tsx b/src/components/common/helpers/renderActionMessageText.tsx index a2cfb550c..29413c831 100644 --- a/src/components/common/helpers/renderActionMessageText.tsx +++ b/src/components/common/helpers/renderActionMessageText.tsx @@ -21,6 +21,8 @@ import MessageLink from '../MessageLink'; import ChatLink from '../ChatLink'; import GroupCallLink from '../GroupCallLink'; import MessageSummary from '../MessageSummary'; +import CustomEmoji from '../CustomEmoji'; +import TopicDefaultIcon from '../TopicDefaultIcon'; interface RenderOptions { asPlainText?: boolean; @@ -48,7 +50,7 @@ export function renderActionMessageText( } const { - text, translationValues, amount, currency, call, score, + text, translationValues, amount, currency, call, score, topicEmojiIconId, } = message.content.action; const content: TextPart[] = []; const noLinks = options.asPlainText || options.isEmbedded; @@ -95,10 +97,26 @@ export function renderActionMessageText( content.push(...processed); if (unprocessed.includes('%action_topic%')) { + const topicEmoji = topic?.iconEmojiId ? : ''; + const topicString = topic ? `${topic.title}` : 'a topic'; processed = processPlaceholder( unprocessed, '%action_topic%', - topic ? topic.title : 'a topic', + [topicEmoji, topicString], + '', + ); + unprocessed = processed.pop() as string; + content.push(...processed); + } + + if (unprocessed.includes('%action_topic_icon%')) { + const topicIcon = topicEmojiIconId || topic?.iconEmojiId; + const hasIcon = topicIcon && topicIcon !== '0'; + processed = processPlaceholder( + unprocessed, + '%action_topic_icon%', + hasIcon ? + : topic ? : '...', ); unprocessed = processed.pop() as string; content.push(...processed); @@ -256,7 +274,9 @@ function renderMigratedContent(chatId: string, noLinks?: boolean): string | Text return {text}; } -function processPlaceholder(text: string, placeholder: string, replaceValue?: TextPart | TextPart[]): TextPart[] { +function processPlaceholder( + text: string, placeholder: string, replaceValue?: TextPart | TextPart[], separator = ',', +): TextPart[] { const placeholderPosition = text.indexOf(placeholder); if (placeholderPosition < 0 || !replaceValue) { return [text]; @@ -268,7 +288,7 @@ function processPlaceholder(text: string, placeholder: string, replaceValue?: Te replaceValue.forEach((value, index) => { content.push(value); if (index + 1 < replaceValue.length) { - content.push(', '); + content.push(`${separator} `); } }); } else { diff --git a/src/components/left/main/hooks/useTopicContextActions.ts b/src/components/left/main/hooks/useTopicContextActions.ts index 8feadd5f4..c21d3536b 100644 --- a/src/components/left/main/hooks/useTopicContextActions.ts +++ b/src/components/left/main/hooks/useTopicContextActions.ts @@ -3,7 +3,7 @@ import { getActions } from '../../../../global'; import type { ApiChat, ApiTopic } from '../../../../api/types'; import { compact } from '../../../../util/iteratees'; -import { getHasAdminRight } from '../../../../global/helpers'; +import { getCanManageTopic, getHasAdminRight } from '../../../../global/helpers'; import useLang from '../../../../hooks/useLang'; import { useMemo } from '../../../../lib/teact/teact'; @@ -19,7 +19,7 @@ export default function useTopicContextActions( return useMemo(() => { const { - isPinned, isMuted, isClosed, isOwner, id: topicId, + isPinned, isMuted, isClosed, id: topicId, } = topic; const chatId = chat.id; @@ -31,7 +31,7 @@ export default function useTopicContextActions( updateTopicMutedState, } = getActions(); - const canToggleClosed = isOwner || chat.isCreator || getHasAdminRight(chat, 'manageTopics'); + const canToggleClosed = getCanManageTopic(chat, topic); const canTogglePinned = chat.isCreator || getHasAdminRight(chat, 'manageTopics'); const actionUnreadMark = topic.unreadCount || !wasOpened diff --git a/src/components/right/EditTopic.tsx b/src/components/right/EditTopic.tsx index 5c620a4cd..960a17450 100644 --- a/src/components/right/EditTopic.tsx +++ b/src/components/right/EditTopic.tsx @@ -26,6 +26,7 @@ import Transition from '../ui/Transition'; import styles from './ManageTopic.module.scss'; const ICON_SIZE = 5 * REM; +const RESET_ICON_ID = '0'; export type OwnProps = { isActive: boolean; @@ -92,7 +93,7 @@ const EditTopic: FC = ({ } if (emoji.id === DEFAULT_TOPIC_ICON_STICKER_ID) { - setIconEmojiId(undefined); + setIconEmojiId(RESET_ICON_ID); return; } diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index 4f433054e..718809fc3 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -1427,13 +1427,15 @@ addActionHandler('createTopic', async (global, actions, payload) => { const chat = selectChat(global, chatId); if (!chat) return; - setGlobal({ - ...global, - createTopicPanel: { - chatId, - isLoading: true, - }, - }); + if (global.createTopicPanel) { + setGlobal({ + ...global, + createTopicPanel: { + chatId, + isLoading: true, + }, + }); + } const topicId = await callApi('createTopic', { chat, title, iconColor, iconEmojiId, @@ -1464,14 +1466,16 @@ addActionHandler('editTopic', async (global, actions, payload) => { const topic = chat?.topics?.[topicId]; if (!chat || !topic) return; - setGlobal({ - ...global, - editTopicPanel: { - chatId, - topicId, - isLoading: true, - }, - }); + if (global.editTopicPanel) { + setGlobal({ + ...global, + editTopicPanel: { + chatId, + topicId, + isLoading: true, + }, + }); + } const result = await callApi('editTopic', { chat, topicId, ...rest }); if (!result) return;