Ensured BoR post actions matches those in webapp (#9362)
* Ensured VBoR post actions matches those in webapp * Updated tests * Fixed a value * Review fixes
This commit is contained in:
parent
8732cb9430
commit
a9258543bb
6 changed files with 63 additions and 22 deletions
|
|
@ -102,7 +102,7 @@ const Header = (props: HeaderProps) => {
|
|||
const usernameOverride = ensureString(post.props?.override_username);
|
||||
|
||||
const isUnrevealedPost = useMemo(() => isUnrevealedBoRPost(post), [post, post.metadata?.expire_at]);
|
||||
const ownBoRPost = useMemo(() => isOwnBoRPost(post, currentUser), [currentUser, post]);
|
||||
const ownBoRPost = useMemo(() => isOwnBoRPost(post, currentUser?.id), [currentUser?.id, post]);
|
||||
const showBoRIcon = isUnrevealedPost || ownBoRPost;
|
||||
const borExpireAt = post.metadata?.expire_at;
|
||||
const serverUrl = useServerUrl();
|
||||
|
|
|
|||
|
|
@ -28,7 +28,38 @@ describe('PostOptions', () => {
|
|||
database = server.database;
|
||||
});
|
||||
|
||||
it('should show limited options for unrevealed BoR post', async () => {
|
||||
it('should show limited options for own BoR post', async () => {
|
||||
const unrevealedBoRPost = TestHelper.fakePostModel({
|
||||
type: PostTypes.BURN_ON_READ,
|
||||
channelId: TestHelper.basicChannel!.id,
|
||||
userId: TestHelper.basicUser!.id,
|
||||
});
|
||||
|
||||
renderWithEverything(
|
||||
<PostOptions
|
||||
post={unrevealedBoRPost}
|
||||
serverUrl={serverUrl}
|
||||
showAddReaction={true}
|
||||
sourceScreen={'DraftScheduledPostOptions'}
|
||||
componentId={'DraftScheduledPostOptions'}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('Save')).toBeVisible();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Copy Link')).toBeVisible();
|
||||
|
||||
expect(screen.queryByText('Pin to Channel')).not.toBeVisible();
|
||||
expect(screen.queryByText('Copy Text')).not.toBeVisible();
|
||||
expect(screen.queryByText('Edit')).not.toBeVisible();
|
||||
expect(screen.queryByText('Reply')).not.toBeVisible();
|
||||
expect(screen.queryByText('Follow Message')).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('should show limited options for received unrevealed BoR post', async () => {
|
||||
const unrevealedBoRPost = TestHelper.fakePostModel({
|
||||
type: PostTypes.BURN_ON_READ,
|
||||
channelId: TestHelper.basicChannel!.id,
|
||||
|
|
@ -54,9 +85,8 @@ describe('PostOptions', () => {
|
|||
expect(screen.getByText('Mark as Unread')).toBeVisible();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Copy Link')).toBeVisible();
|
||||
expect(screen.queryByText('Save')).toBeVisible();
|
||||
|
||||
expect(screen.queryByText('Copy Link')).not.toBeVisible();
|
||||
expect(screen.queryByText('Save')).not.toBeVisible();
|
||||
expect(screen.queryByText('Pin to Channel')).not.toBeVisible();
|
||||
expect(screen.queryByText('Copy Text')).not.toBeVisible();
|
||||
expect(screen.queryByText('Edit')).not.toBeVisible();
|
||||
|
|
@ -64,7 +94,7 @@ describe('PostOptions', () => {
|
|||
expect(screen.queryByText('Follow Message')).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('should show limited options for revealed BoR post', async () => {
|
||||
it('should show limited options for someone else\'s revealed BoR post', async () => {
|
||||
const unrevealedBoRPost = TestHelper.fakePostModel({
|
||||
type: PostTypes.BURN_ON_READ,
|
||||
channelId: TestHelper.basicChannel!.id,
|
||||
|
|
@ -91,11 +121,10 @@ describe('PostOptions', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Mark as Unread')).toBeVisible();
|
||||
expect(screen.queryByText('Save')).toBeVisible();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Copy Link')).toBeVisible();
|
||||
expect(screen.queryByText('Save')).toBeVisible();
|
||||
|
||||
expect(screen.queryByText('Copy Link')).not.toBeVisible();
|
||||
expect(screen.queryByText('Copy Text')).not.toBeVisible();
|
||||
expect(screen.queryByText('Pin to Channel')).not.toBeVisible();
|
||||
expect(screen.queryByText('Edit')).not.toBeVisible();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import {withDatabase, withObservables} from '@nozbe/watermelondb/react';
|
||||
import {combineLatest, of as of$, Observable} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {distinctUntilChanged, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {Permissions, Post, Screens} from '@constants';
|
||||
import {AppBindingLocations} from '@constants/apps';
|
||||
|
|
@ -146,14 +146,20 @@ const enhanced = withObservables([], ({combinedPost, post, showAddReaction, sour
|
|||
}),
|
||||
);
|
||||
|
||||
const canDelete = combineLatest([canDeletePostPermission, channelIsArchived, channelIsReadOnly, canPostPermission]).pipe(switchMap(([permission, isArchived, isReadOnly, canPost]) => {
|
||||
return of$(permission && !isArchived && !isReadOnly && canPost);
|
||||
const canDelete = combineLatest([canDeletePostPermission, channelIsArchived, channelIsReadOnly, canPostPermission, currentUser]).pipe(switchMap(([permission, isArchived, isReadOnly, canPost, user]) => {
|
||||
const canDeleteBoRPost = borPost ? post.userId === user?.id : true;
|
||||
return of$(permission && !isArchived && !isReadOnly && canPost && canDeleteBoRPost);
|
||||
}));
|
||||
|
||||
const thread = observeIsCRTEnabled(database).pipe(
|
||||
switchMap((enabled) => (enabled ? observeThreadById(database, post.id) : of$(undefined))),
|
||||
);
|
||||
|
||||
const currentUserId = currentUser.pipe(
|
||||
switchMap((u) => of$(u?.id)),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
|
||||
return {
|
||||
canMarkAsUnread,
|
||||
canAddReaction,
|
||||
|
|
@ -167,6 +173,7 @@ const enhanced = withObservables([], ({combinedPost, post, showAddReaction, sour
|
|||
thread,
|
||||
bindings,
|
||||
isBoRPost: of$(borPost),
|
||||
currentUserId,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {useIsTablet} from '@hooks/device';
|
|||
import useNavButtonPressed from '@hooks/navigation_button_pressed';
|
||||
import BottomSheet from '@screens/bottom_sheet';
|
||||
import {dismissBottomSheet} from '@screens/navigation';
|
||||
import {isOwnBoRPost, isUnrevealedBoRPost} from '@utils/bor';
|
||||
import {bottomSheetSnapPoint} from '@utils/helpers';
|
||||
import {isSystemMessage} from '@utils/post';
|
||||
|
||||
|
|
@ -48,13 +49,14 @@ type PostOptionsProps = {
|
|||
bindings: AppBinding[];
|
||||
serverUrl: string;
|
||||
isBoRPost?: boolean;
|
||||
currentUserId?: string;
|
||||
};
|
||||
const PostOptions = ({
|
||||
canAddReaction, canDelete, canEdit,
|
||||
canMarkAsUnread, canPin, canReply,
|
||||
combinedPost, componentId, isSaved,
|
||||
sourceScreen, post, thread, bindings, serverUrl,
|
||||
isBoRPost,
|
||||
isBoRPost, currentUserId,
|
||||
}: PostOptionsProps) => {
|
||||
const managedConfig = useManagedConfig<ManagedConfig>();
|
||||
const isTablet = useIsTablet();
|
||||
|
|
@ -69,9 +71,12 @@ const PostOptions = ({
|
|||
|
||||
const isSystemPost = isSystemMessage(post);
|
||||
|
||||
const canCopyPermalink = !isSystemPost && managedConfig?.copyAndPasteProtection !== 'true';
|
||||
const canCopyBoRPostPermalink = isBoRPost ? post.userId === currentUserId : true;
|
||||
const canCopyPermalink = !isSystemPost && managedConfig?.copyAndPasteProtection !== 'true' && canCopyBoRPostPermalink;
|
||||
const canCopyText = canCopyPermalink && post.message && !isBoRPost;
|
||||
|
||||
const canSavePost = !isSystemPost && (!isUnrevealedBoRPost(post) || isOwnBoRPost(post, currentUserId));
|
||||
|
||||
const shouldRenderFollow = !(sourceScreen !== Screens.CHANNEL || !thread);
|
||||
const shouldShowBindings = bindings.length > 0 && !isSystemPost;
|
||||
|
||||
|
|
@ -79,7 +84,7 @@ const PostOptions = ({
|
|||
const items: Array<string | number> = [1];
|
||||
const optionsCount = [
|
||||
canCopyPermalink, canCopyText, canDelete, canEdit,
|
||||
canMarkAsUnread, canPin, canReply, !isSystemPost, shouldRenderFollow,
|
||||
canMarkAsUnread, canPin, canReply, canSavePost, shouldRenderFollow,
|
||||
].reduce((acc, v) => {
|
||||
return v ? acc + 1 : acc;
|
||||
}, 0) + (shouldShowBindings ? 0.5 : 0);
|
||||
|
|
@ -94,7 +99,7 @@ const PostOptions = ({
|
|||
}, [
|
||||
canAddReaction, canCopyPermalink, canCopyText,
|
||||
canDelete, canEdit, shouldRenderFollow, shouldShowBindings,
|
||||
canMarkAsUnread, canPin, canReply, isSystemPost,
|
||||
canMarkAsUnread, canPin, canReply, canSavePost,
|
||||
]);
|
||||
|
||||
const renderContent = () => {
|
||||
|
|
@ -136,7 +141,7 @@ const PostOptions = ({
|
|||
sourceScreen={sourceScreen}
|
||||
/>
|
||||
}
|
||||
{!isSystemPost &&
|
||||
{canSavePost &&
|
||||
<SaveOption
|
||||
bottomSheetId={Screens.POST_OPTIONS}
|
||||
isSaved={isSaved}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ describe('BoR utility functions', () => {
|
|||
userId: 'user123',
|
||||
} as PostModel;
|
||||
|
||||
expect(isOwnBoRPost(ownBorPost, mockUser)).toBe(true);
|
||||
expect(isOwnBoRPost(ownBorPost, mockUser.id)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BoR posts not owned by current user', () => {
|
||||
|
|
@ -109,7 +109,7 @@ describe('BoR utility functions', () => {
|
|||
userId: 'user456',
|
||||
} as PostModel;
|
||||
|
||||
expect(isOwnBoRPost(othersBorPost, mockUser)).toBe(false);
|
||||
expect(isOwnBoRPost(othersBorPost, mockUser.id)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for non-BoR posts', () => {
|
||||
|
|
@ -118,7 +118,7 @@ describe('BoR utility functions', () => {
|
|||
userId: 'user123',
|
||||
} as PostModel;
|
||||
|
||||
expect(isOwnBoRPost(ownRegularPost, mockUser)).toBe(false);
|
||||
expect(isOwnBoRPost(ownRegularPost, mockUser.id)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when no current user is provided', () => {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ export function isUnrevealedBoRPost(post: Post | PostModel): boolean {
|
|||
return isBoRPost(post) && Boolean(!post.metadata?.expire_at);
|
||||
}
|
||||
|
||||
export function isOwnBoRPost(post: PostModel, currentUser?: UserModel): boolean {
|
||||
return isBoRPost(post) && Boolean(currentUser && post.userId === currentUser.id);
|
||||
export function isOwnBoRPost(post: PostModel, currentUserId?: UserModel['id']): boolean {
|
||||
return isBoRPost(post) && post.userId === currentUserId;
|
||||
}
|
||||
|
||||
function isBoRPostExpiredForMe(post: PostModel): boolean {
|
||||
|
|
|
|||
Loading…
Reference in a new issue