Forum: Saving the state of the "View as Messages" option (#4091)
This commit is contained in:
parent
2edd680802
commit
93aa65cd72
@ -96,7 +96,7 @@ export function buildApiChatFromDialog(
|
||||
const {
|
||||
peer, folderId, unreadMark, unreadCount, unreadMentionsCount, unreadReactionsCount,
|
||||
notifySettings: { silent, muteUntil },
|
||||
readOutboxMaxId, readInboxMaxId, draft,
|
||||
readOutboxMaxId, readInboxMaxId, draft, viewForumAsMessages,
|
||||
} = dialog;
|
||||
const isMuted = silent || (typeof muteUntil === 'number' && getServerTime() < muteUntil);
|
||||
|
||||
@ -114,6 +114,7 @@ export function buildApiChatFromDialog(
|
||||
muteUntil,
|
||||
...(unreadMark && { hasUnreadMark: true }),
|
||||
...(draft instanceof GramJs.DraftMessage && { draftDate: draft.date }),
|
||||
...(viewForumAsMessages && { isForumAsMessages: true }),
|
||||
...buildApiChatFieldsFromPeerEntity(peerEntity),
|
||||
};
|
||||
}
|
||||
|
||||
@ -81,6 +81,7 @@ type FullChatData = {
|
||||
userStatusesById: { [userId: string]: ApiUserStatus };
|
||||
groupCall?: Partial<ApiGroupCall>;
|
||||
membersCount?: number;
|
||||
isForumAsMessages?: true;
|
||||
};
|
||||
|
||||
let onUpdate: OnApiUpdate;
|
||||
@ -483,6 +484,7 @@ async function getFullChannelInfo(
|
||||
participantsHidden,
|
||||
translationsDisabled,
|
||||
storiesPinnedAvailable,
|
||||
viewForumAsMessages,
|
||||
} = result.fullChat;
|
||||
|
||||
if (chatPhoto instanceof GramJs.Photo) {
|
||||
@ -572,6 +574,7 @@ async function getFullChannelInfo(
|
||||
connectionState: 'disconnected',
|
||||
} : undefined,
|
||||
membersCount: participantsCount,
|
||||
...(viewForumAsMessages && { isForumAsMessages: true }),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1880,6 +1883,18 @@ export function togglePeerTranslations({
|
||||
}));
|
||||
}
|
||||
|
||||
export function setViewForumAsMessages({ chat, isEnabled }: { chat: ApiChat; isEnabled: boolean }) {
|
||||
const { id, accessHash } = chat;
|
||||
const channel = buildInputEntity(id, accessHash);
|
||||
|
||||
return invokeRequest(new GramJs.channels.ToggleViewForumAsMessages({
|
||||
channel: channel as GramJs.InputChannel,
|
||||
enabled: Boolean(isEnabled),
|
||||
}), {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
}
|
||||
|
||||
function handleUserPrivacyRestrictedUpdates(updates: GramJs.TypeUpdates) {
|
||||
if (!(updates instanceof GramJs.Updates) && !(updates instanceof GramJs.UpdatesCombined)) {
|
||||
return undefined;
|
||||
|
||||
@ -23,7 +23,7 @@ export {
|
||||
getChatByPhoneNumber, toggleJoinToSend, toggleJoinRequest, fetchTopics, deleteTopic, togglePinnedTopic,
|
||||
editTopic, toggleForum, fetchTopicById, createTopic, toggleParticipantsHidden, checkChatlistInvite,
|
||||
joinChatlistInvite, createChalistInvite, editChatlistInvite, deleteChatlistInvite, fetchChatlistInvites,
|
||||
fetchLeaveChatlistSuggestions, leaveChatlist, togglePeerTranslations,
|
||||
fetchLeaveChatlistSuggestions, leaveChatlist, togglePeerTranslations, setViewForumAsMessages,
|
||||
} from './chats';
|
||||
|
||||
export {
|
||||
|
||||
@ -1131,6 +1131,12 @@ export function updater(update: Update) {
|
||||
location: update.location,
|
||||
isUnconfirmed: update.unconfirmed,
|
||||
});
|
||||
} else if (update instanceof GramJs.UpdateChannelViewForumAsMessages) {
|
||||
onUpdate({
|
||||
'@type': 'updateViewForumAsMessages',
|
||||
chatId: buildApiPeerId(update.channelId, 'channel'),
|
||||
isEnabled: update.enabled ? true : undefined,
|
||||
});
|
||||
} else if (DEBUG) {
|
||||
const params = typeof update === 'object' && 'className' in update ? update.className : update;
|
||||
log('UNEXPECTED UPDATE', params);
|
||||
|
||||
@ -44,6 +44,7 @@ export interface ApiChat {
|
||||
fakeType?: ApiFakeType;
|
||||
color?: ApiPeerColor;
|
||||
isForum?: boolean;
|
||||
isForumAsMessages?: true;
|
||||
topics?: Record<number, ApiTopic>;
|
||||
listedTopicIds?: number[];
|
||||
topicsCount?: number;
|
||||
|
||||
@ -609,6 +609,12 @@ export type ApiUpdateTopics = {
|
||||
chatId: string;
|
||||
};
|
||||
|
||||
export type ApiUpdateViewForumAsMessages = {
|
||||
'@type': 'updateViewForumAsMessages';
|
||||
chatId: string;
|
||||
isEnabled?: true;
|
||||
};
|
||||
|
||||
export type ApiUpdateMessageTranslations = {
|
||||
'@type': 'updateMessageTranslations';
|
||||
chatId: string;
|
||||
@ -706,7 +712,8 @@ export type ApiUpdate = (
|
||||
ApiUpdatePinnedTopicsOrder | ApiUpdateTopic | ApiUpdateTopics | ApiUpdateRecentEmojiStatuses |
|
||||
ApiUpdateRecentReactions | ApiUpdateStory | ApiUpdateReadStories | ApiUpdateDeleteStory | ApiUpdateSentStoryReaction |
|
||||
ApiRequestReconnectApi | ApiRequestSync | ApiUpdateFetchingDifference | ApiUpdateChannelMessages |
|
||||
ApiUpdateStealthMode | ApiUpdateAttachMenuBots | ApiUpdateNewAuthorization | ApiUpdateGroupInvitePrivacyForbidden
|
||||
ApiUpdateStealthMode | ApiUpdateAttachMenuBots | ApiUpdateNewAuthorization | ApiUpdateGroupInvitePrivacyForbidden |
|
||||
ApiUpdateViewForumAsMessages
|
||||
);
|
||||
|
||||
export type OnApiUpdate = (update: ApiUpdate) => void;
|
||||
|
||||
@ -62,7 +62,7 @@ const ChatForumLastMessage: FC<OwnProps> = ({
|
||||
handleClick: handleOpenTopicClick,
|
||||
handleMouseDown: handleOpenTopicMouseDown,
|
||||
} = useFastClick((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (lastActiveTopic.unreadCount === 0) return;
|
||||
if (lastActiveTopic.unreadCount === 0 || chat.isForumAsMessages) return;
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
@ -22,6 +22,7 @@ import type {
|
||||
ApiReaction,
|
||||
ApiStealthMode,
|
||||
ApiSticker,
|
||||
ApiTopic,
|
||||
ApiUser,
|
||||
ApiVideo,
|
||||
} from '../../api/types';
|
||||
@ -30,6 +31,7 @@ import type {
|
||||
MessageListType, TabState,
|
||||
} from '../../global/types';
|
||||
import type { IAnchorPosition, InlineBotSettings, ISettings } from '../../types';
|
||||
import { MAIN_THREAD_ID } from '../../api/types';
|
||||
|
||||
import {
|
||||
BASE_EMOJI_KEYWORD_LANG,
|
||||
@ -75,6 +77,7 @@ import {
|
||||
selectScheduledIds,
|
||||
selectTabState,
|
||||
selectTheme,
|
||||
selectTopicFromMessage,
|
||||
selectUser,
|
||||
selectUserFullInfo,
|
||||
} from '../../global/selectors';
|
||||
@ -184,6 +187,7 @@ type StateProps =
|
||||
editingMessage?: ApiMessage;
|
||||
chat?: ApiChat;
|
||||
draft?: ApiDraft;
|
||||
replyToTopic?: ApiTopic;
|
||||
currentMessageList?: MessageList;
|
||||
isChatWithBot?: boolean;
|
||||
isChatWithSelf?: boolean;
|
||||
@ -282,6 +286,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
messageListType,
|
||||
draft,
|
||||
chat,
|
||||
replyToTopic,
|
||||
isForCurrentMessageList,
|
||||
isCurrentUserPremium,
|
||||
canSendVoiceByPrivacy,
|
||||
@ -1292,6 +1297,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
|| isCustomSendMenuOpen || Boolean(activeVoiceRecording) || attachments.length > 0 || isInputHasFocus;
|
||||
const isReactionSelectorOpen = isComposerHasFocus && !isReactionPickerOpen && isInStoryViewer && !isAttachMenuOpen
|
||||
&& !isSymbolMenuOpen;
|
||||
const placeholderForForumAsMessages = chat?.isForum && chat?.isForumAsMessages && threadId === MAIN_THREAD_ID
|
||||
? (replyToTopic
|
||||
? lang('Chat.InputPlaceholderReplyInTopic', replyToTopic.title)
|
||||
: lang('Message.Placeholder.MessageInGeneral'))
|
||||
: undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (isComposerHasFocus) {
|
||||
@ -1680,7 +1690,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
activeVoiceRecording && windowWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER
|
||||
? ''
|
||||
: (!isComposerBlocked
|
||||
? (botKeyboardPlaceholder || inputPlaceholder || lang('Message'))
|
||||
? (botKeyboardPlaceholder || inputPlaceholder || lang(placeholderForForumAsMessages || 'Message'))
|
||||
: lang('Chat.PlaceholderTextNotAllowed'))
|
||||
}
|
||||
timedPlaceholderDate={timedPlaceholderDate}
|
||||
@ -1932,13 +1942,20 @@ export default memo(withGlobal<OwnProps>(
|
||||
|
||||
const story = storyId && selectPeerStory(global, chatId, storyId);
|
||||
const sentStoryReaction = story && 'sentReaction' in story ? story.sentReaction : undefined;
|
||||
const draft = selectDraft(global, chatId, threadId);
|
||||
const replyToMessage = draft?.replyInfo
|
||||
? selectChatMessage(global, chatId, draft.replyInfo.replyToMsgId)
|
||||
: undefined;
|
||||
const replyToTopic = chat?.isForum && chat.isForumAsMessages && threadId === MAIN_THREAD_ID && replyToMessage
|
||||
? selectTopicFromMessage(global, replyToMessage)
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
availableReactions: type === 'story' ? global.availableReactions : undefined,
|
||||
topReactions: type === 'story' ? global.topReactions : undefined,
|
||||
isOnActiveTab: !tabState.isBlurred,
|
||||
editingMessage: selectEditingMessage(global, chatId, threadId, messageListType),
|
||||
draft: selectDraft(global, chatId, threadId),
|
||||
draft,
|
||||
chat,
|
||||
isChatWithBot,
|
||||
isChatWithSelf,
|
||||
@ -1996,6 +2013,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
shouldCollectDebugLogs: global.settings.byKey.shouldCollectDebugLogs,
|
||||
sentStoryReaction,
|
||||
stealthMode: global.stories.stealthMode,
|
||||
replyToTopic,
|
||||
};
|
||||
},
|
||||
)(Composer));
|
||||
|
||||
@ -173,12 +173,13 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
||||
}
|
||||
|
||||
const isChatSender = senderChat?.id === sender?.id;
|
||||
const isReplyToQuote = isInComposer && Boolean(replyInfo && 'quoteText' in replyInfo && replyInfo?.quoteText);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isChatSender && (
|
||||
<span className="embedded-sender">
|
||||
{renderText(isInComposer ? lang('ReplyToQuote', senderTitle) : senderTitle)}
|
||||
{renderText(isReplyToQuote ? lang('ReplyToQuote', senderTitle) : senderTitle)}
|
||||
</span>
|
||||
)}
|
||||
{icon && <Icon name={icon} className="embedded-chat-icon" />}
|
||||
|
||||
@ -147,7 +147,7 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
const [shouldRenderChatFolderModal, markRenderChatFolderModal, unmarkRenderChatFolderModal] = useFlag();
|
||||
const [shouldRenderReportModal, markRenderReportModal, unmarkRenderReportModal] = useFlag();
|
||||
|
||||
const { lastMessage, isForum } = chat || {};
|
||||
const { lastMessage, isForum, isForumAsMessages } = chat || {};
|
||||
|
||||
const { renderSubtitle, ref } = useChatListEntry({
|
||||
chat,
|
||||
@ -169,17 +169,23 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
const getIsForumPanelClosed = useSelectorSignal(selectIsForumPanelClosed);
|
||||
|
||||
const handleClick = useLastCallback(() => {
|
||||
const noForumTopicPanel = isMobile && isForumAsMessages;
|
||||
|
||||
if (isForum) {
|
||||
if (isForumPanelOpen) {
|
||||
closeForumPanel(undefined, { forceOnHeavyAnimation: true });
|
||||
} else {
|
||||
openForumPanel({ chatId }, { forceOnHeavyAnimation: true });
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
} else {
|
||||
if (!noForumTopicPanel) {
|
||||
openForumPanel({ chatId }, { forceOnHeavyAnimation: true });
|
||||
}
|
||||
|
||||
if (!isForumAsMessages) return;
|
||||
}
|
||||
}
|
||||
|
||||
openChat({ id: chatId, shouldReplaceHistory: true }, { forceOnHeavyAnimation: true });
|
||||
openChat({ id: chatId, noForumTopicPanel, shouldReplaceHistory: true }, { forceOnHeavyAnimation: true });
|
||||
|
||||
if (isSelected && canScrollDown) {
|
||||
focusLastMessage();
|
||||
|
||||
@ -92,7 +92,12 @@ const Topic: FC<OwnProps & StateProps> = ({
|
||||
draft,
|
||||
wasTopicOpened,
|
||||
}) => {
|
||||
const { openThread, deleteTopic, focusLastMessage } = getActions();
|
||||
const {
|
||||
openThread,
|
||||
deleteTopic,
|
||||
focusLastMessage,
|
||||
setViewForumAsMessages,
|
||||
} = getActions();
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
@ -141,6 +146,7 @@ const Topic: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const handleOpenTopic = useLastCallback(() => {
|
||||
openThread({ chatId, threadId: topic.id, shouldReplaceHistory: true });
|
||||
setViewForumAsMessages({ chatId, isEnabled: false });
|
||||
|
||||
if (canScrollDown) {
|
||||
focusLastMessage();
|
||||
|
||||
@ -130,6 +130,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
||||
openChatLanguageModal,
|
||||
setSettingOption,
|
||||
unblockUser,
|
||||
setViewForumAsMessages,
|
||||
} = getActions();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const menuButtonRef = useRef<HTMLButtonElement>(null);
|
||||
@ -209,6 +210,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const handleAsMessagesClick = useLastCallback(() => {
|
||||
openChat({ id: chatId });
|
||||
setViewForumAsMessages({ chatId, isEnabled: true });
|
||||
});
|
||||
|
||||
function handleRequestCall() {
|
||||
|
||||
@ -104,6 +104,7 @@ type StateProps = {
|
||||
isMuted?: boolean;
|
||||
isTopic?: boolean;
|
||||
isForum?: boolean;
|
||||
isForumAsMessages?: true;
|
||||
canAddContact?: boolean;
|
||||
canReportChat?: boolean;
|
||||
canDeleteChat?: boolean;
|
||||
@ -133,6 +134,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
withForumActions,
|
||||
isTopic,
|
||||
isForum,
|
||||
isForumAsMessages,
|
||||
isChatInfoShown,
|
||||
canStartBot,
|
||||
canSubscribe,
|
||||
@ -189,6 +191,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
togglePeerTranslations,
|
||||
blockUser,
|
||||
unblockUser,
|
||||
setViewForumAsMessages,
|
||||
} = getActions();
|
||||
|
||||
const { isMobile } = useAppLayout();
|
||||
@ -280,6 +283,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const handleViewAsTopicsClick = useLastCallback(() => {
|
||||
openChat({ id: undefined });
|
||||
setViewForumAsMessages({ chatId, isEnabled: false });
|
||||
closeMenu();
|
||||
});
|
||||
|
||||
@ -469,7 +473,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
<div className="right-badge">{pendingJoinRequests}</div>
|
||||
</MenuItem>
|
||||
)}
|
||||
{withForumActions && !isTopic && (
|
||||
{withForumActions && !isTopic && !isForumAsMessages && (
|
||||
<MenuItem
|
||||
icon="message"
|
||||
onClick={handleOpenAsMessages}
|
||||
@ -696,6 +700,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isPrivate,
|
||||
isTopic: chat?.isForum && !isMainThread,
|
||||
isForum: chat?.isForum,
|
||||
isForumAsMessages: chat?.isForumAsMessages,
|
||||
canAddContact,
|
||||
canReportChat,
|
||||
canDeleteChat: getCanDeleteChat(chat),
|
||||
|
||||
@ -327,6 +327,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
|
||||
const draft = selectDraft(global, chatId, threadId);
|
||||
const replyInfo = draft?.replyInfo;
|
||||
|
||||
let message: ApiMessage | undefined;
|
||||
if (replyInfo && !shouldForceShowEditing) {
|
||||
message = selectChatMessage(global, replyInfo.replyToPeerId || chatId, replyInfo.replyToMsgId);
|
||||
|
||||
@ -2503,6 +2503,20 @@ addActionHandler('togglePeerTranslations', async (global, actions, payload): Pro
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
addActionHandler('setViewForumAsMessages', (global, actions, payload): ActionReturnType => {
|
||||
const { chatId, isEnabled } = payload;
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat?.isForum || chat.isForumAsMessages === isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
global = updateChat(global, chatId, { isForumAsMessages: isEnabled || undefined });
|
||||
setGlobal(global);
|
||||
|
||||
void callApi('setViewForumAsMessages', { chat, isEnabled });
|
||||
});
|
||||
|
||||
async function loadChats(
|
||||
listType: 'active' | 'archived',
|
||||
offsetId?: string,
|
||||
@ -2638,7 +2652,7 @@ export async function loadFullChat<T extends GlobalState>(
|
||||
}
|
||||
|
||||
const {
|
||||
users, userStatusesById, fullInfo, groupCall, membersCount,
|
||||
users, userStatusesById, fullInfo, groupCall, membersCount, isForumAsMessages,
|
||||
} = result;
|
||||
|
||||
global = getGlobal();
|
||||
@ -2664,6 +2678,9 @@ export async function loadFullChat<T extends GlobalState>(
|
||||
if (membersCount !== undefined) {
|
||||
global = updateChat(global, chat.id, { membersCount });
|
||||
}
|
||||
if (chat.isForum) {
|
||||
global = updateChat(global, chat.id, { isForumAsMessages });
|
||||
}
|
||||
global = replaceChatFullInfo(global, chat.id, fullInfo);
|
||||
setGlobal(global);
|
||||
|
||||
|
||||
@ -469,6 +469,18 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
case 'updateViewForumAsMessages': {
|
||||
const { chatId, isEnabled } = update;
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat?.isForum) return undefined;
|
||||
|
||||
global = updateChat(global, chatId, {
|
||||
isForumAsMessages: isEnabled,
|
||||
});
|
||||
setGlobal(global);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@ -2819,6 +2819,10 @@ export interface ActionPayloads {
|
||||
isMuted?: boolean;
|
||||
muteUntil?: number;
|
||||
};
|
||||
setViewForumAsMessages: {
|
||||
chatId: string;
|
||||
isEnabled: boolean;
|
||||
};
|
||||
|
||||
openCreateTopicPanel: {
|
||||
chatId: string;
|
||||
|
||||
@ -1442,6 +1442,7 @@ channels.updatePinnedForumTopic#6c2d9026 channel:InputChannel topic_id:int pinne
|
||||
channels.deleteTopicHistory#34435f2d channel:InputChannel top_msg_id:int = messages.AffectedHistory;
|
||||
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
|
||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
||||
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
|
||||
bots.invokeWebViewCustomMethod#87fc5e7 bot:InputUser custom_method:string params:DataJSON = DataJSON;
|
||||
|
||||
@ -289,6 +289,7 @@
|
||||
"channels.deleteTopicHistory",
|
||||
"channels.toggleParticipantsHidden",
|
||||
"channels.clickSponsoredMessage",
|
||||
"channels.toggleViewForumAsMessages",
|
||||
"photos.uploadContactProfilePhoto",
|
||||
"messages.getMessagesViews",
|
||||
"chatlists.exportChatlistInvite",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user