mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-04 09:58:57 +00:00
* Add failing regression test for MM-66467 missing messages A deleted post received via RECEIVED_IN_CHANNEL (e.g. from the cold-start deferred unread-channel fetch, since GetPostsSince returns deleted posts) currently creates a separate, empty PostsInChannel interval. That interval has the newest `latest`, becomes postsInChannel[0], renders zero rows, and blanks the channel. This operator-level test seeds a real [1000,1000] interval, then handles a deleted post at create_at 5000 and asserts no empty orphan interval is created. It is intentionally RED on current code (after.length is 2, not 1) and will pass once the creation-site fix (build the interval from delete_at===0 posts / skip when none survive) lands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add "Reset cached messages" channel recovery option (MM-66467) Adds a "Reset cached messages" option at the bottom of the Channel Info options list (directly above "Leave channel"), visible to every channel member. It clears the channel's local posts + PostsInChannel intervals and resets lastFetchedAt via deletePostsForChannel, then re-fetches a clean page from the server via fetchPostsForChannel. This recovers a channel that renders blank due to an empty/orphaned PostsInChannel interval (e.g. the deleted-root + deferred-fetch path), and is robust to any future cause of a bad interval state, without requiring a full logout/login. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Navigate to the channel after resetting cached messages After confirming "Reset cached messages", dismiss the Channel Info screen via navigateBack() so the user lands back on the now-repopulated channel instead of staying in Channel Info. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Show distinct errors for reset delete vs fetch failures Split the single try/catch in the reset action into two checks against the returned error: - if deletePostsForChannel fails, show a generic "couldn't reset" message and stop (nothing was changed). - if fetchPostsForChannel fails, tell the user the cached messages were cleared but couldn't be downloaded again and to check their internet connection. Only navigate back to the channel when both steps succeed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix MM-66467: don't create PostsInChannel interval from deleted posts handleReceivedPostsInChannel built the channel interval from the raw posts array, including posts with delete_at > 0. Those posts are dropped before persistence (handlePosts), so a deleted post newer than the existing interval produced an empty, orphaned chunk that became postsInChannel[0] and rendered the whole channel blank. Filter to delete_at === 0 posts before computing the interval edges, and skip interval creation entirely when none survive. This is the creation- site fix: it prevents the orphan rather than cleaning it up afterwards, so it does not mask genuine gaps the way an aggressive chunk merge would. Makes the previously-failing operator regression test pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Extend chunk on deferred since-fetch instead of orphaning (MM-66467) processChannelPostsByTeam (the cold-start "fetch posts for unread channels" pass) stored its results with a hardcoded RECEIVED_IN_CHANNEL, ignoring the action type fetchPostsForChannel resolved. A since-fetch is a contiguous continuation of the channel's existing interval, so storing it as RECEIVED_IN_CHANNEL created a disjoint interval for any post newer than the chunk instead of extending it — an orphan that can become postsInChannel[0] and hide the channel. Use the resolved action type (RECEIVED_SINCE for a since-fetch, which extends the existing chunk; RECEIVED_IN_CHANNEL only for an initial page fetch with no chunk yet). This matches what fetchPostsForChannel does when it stores its own results. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Await server database teardown in post.auxiliary test afterEach called DatabaseManager.destroyServerDatabase without awaiting it, so teardown could race the next test's beforeEach/init. Await it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import React from 'react';
|
|
|
|
import CopyChannelLinkOption from '@components/channel_actions/copy_channel_link_option';
|
|
import {General} from '@constants';
|
|
import PlaybookRunsOption from '@playbooks/components/channel_actions/playbook_runs_option';
|
|
import {isTypeDMorGM} from '@utils/channel';
|
|
|
|
import AddMembers from './add_members';
|
|
import AutoFollowThreads from './auto_follow_threads';
|
|
import ChannelFiles from './channel_files';
|
|
import ChannelSettings from './channel_settings';
|
|
import IgnoreMentions from './ignore_mentions';
|
|
import Members from './members';
|
|
import MyAutotranslation from './my_autotranslation';
|
|
import NotificationPreference from './notification_preference';
|
|
import PinnedMessages from './pinned_messages';
|
|
import ResetChannelPosts from './reset_channel_posts';
|
|
|
|
type Props = {
|
|
channelId: string;
|
|
type?: ChannelType;
|
|
callsEnabled: boolean;
|
|
canManageMembers: boolean;
|
|
isCRTEnabled: boolean;
|
|
isPlaybooksEnabled: boolean;
|
|
hasChannelSettingsActions: boolean;
|
|
isAutotranslationEnabledForThisChannel: boolean;
|
|
channelDisplayName: string;
|
|
}
|
|
|
|
const Options = ({
|
|
channelId,
|
|
type,
|
|
callsEnabled,
|
|
canManageMembers,
|
|
isCRTEnabled,
|
|
isPlaybooksEnabled,
|
|
hasChannelSettingsActions,
|
|
isAutotranslationEnabledForThisChannel,
|
|
channelDisplayName,
|
|
}: Props) => {
|
|
const isDMorGM = isTypeDMorGM(type);
|
|
|
|
return (
|
|
<>
|
|
{hasChannelSettingsActions && (
|
|
<ChannelSettings
|
|
channelId={channelId}
|
|
channelDisplayName={channelDisplayName}
|
|
/>
|
|
)}
|
|
{type !== General.DM_CHANNEL && (
|
|
<>
|
|
{isCRTEnabled && (
|
|
<AutoFollowThreads channelId={channelId}/>
|
|
)}
|
|
<IgnoreMentions channelId={channelId}/>
|
|
</>
|
|
)}
|
|
<NotificationPreference channelId={channelId}/>
|
|
{isAutotranslationEnabledForThisChannel && (
|
|
<MyAutotranslation channelId={channelId}/>
|
|
)}
|
|
<PinnedMessages channelId={channelId}/>
|
|
<ChannelFiles channelId={channelId}/>
|
|
{isPlaybooksEnabled && !isDMorGM &&
|
|
<PlaybookRunsOption
|
|
channelId={channelId}
|
|
location='channel_actions'
|
|
/>
|
|
}
|
|
{type !== General.DM_CHANNEL &&
|
|
<Members channelId={channelId}/>
|
|
}
|
|
{canManageMembers &&
|
|
<AddMembers channelId={channelId}/>
|
|
}
|
|
{callsEnabled && !isDMorGM && // if calls is not enabled, copy link will show in the channel actions
|
|
<CopyChannelLinkOption
|
|
channelId={channelId}
|
|
testID='channel_info.options.copy_channel_link.option'
|
|
/>
|
|
}
|
|
<ResetChannelPosts channelId={channelId}/>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Options;
|