Navigation for permalink and Tablet fixes (#9116)

* typescript and view component for permalink with user and message

* Old post edited handling in permalink

* Added test and update flag value to EnablePermalinkPreview

* Added test for permalink_preview component

* Added test for content/index.tsx for permalink

* Addressed review comments

* Unit test for missing file and review comments

* Added test to check handlePostEdited permalink sync only calls one time only

* Change TouchableOpacity to Pressable

* When user not found fetch the user from the server

* Removed the redundant test in the test for permalink_preview/index?

* ts to tsx

* Removed the circular dependency

* Address review comments

* displayname fallback

* remove permalink when permalink post is deleted

* UX review comments

* Linter fixes

* Test fixes

* File attachment in permalink preview component

* Fix the width and height of the image in permalink

* Added gredient when exceeds height of permalink container

* Minor

* Updated tests

* Minor

* Review comments

* Minor review comments

* type fixes

* Review comments

* Minor

* Mention ability in permalink preview

* Support for external link in permalink

* Handle device not connected update permalink post

* test fixes

* Address review comments

* Minor

* Merge fixes

* Addressed review comments

* Fix content.test.tsx after permalink branch merge

- Updated test expectations to use embedData prop instead of post prop
- Fixed assertions to match the new PermalinkPreview API
- All content tests now pass

* review comments

* Review comments

* Some more review comments

* Minor

* Fixed the undefined issue for opengraph component metadata

* More fixes

* Navigation for permalink

* Tablet fixes

* type chech for site name

* linter fixes

* UX review and remove show more height not require

* Fix tests

* Fixed the navigation issue for DM's

* Minor fixes due to merge main

---------

Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
This commit is contained in:
Rajat Dabade 2025-09-12 17:46:39 +05:30 committed by GitHub
parent a5d7bf7db4
commit 4e95364344
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 75 additions and 4 deletions

View file

@ -48,6 +48,9 @@ const styles = StyleSheet.create({
marginTop: {
marginTop: 10,
},
rowPermalinkPreview: {
marginTop: 0,
},
});
const Files = ({

View file

@ -4,6 +4,7 @@
import {fireEvent} from '@testing-library/react-native';
import React from 'react';
import {showPermalink} from '@actions/remote/permalink';
import Markdown from '@components/markdown';
import {Screens} from '@constants';
import DatabaseManager from '@database/manager';
@ -15,6 +16,10 @@ import PermalinkPreview from './permalink_preview';
import type ServerDataOperator from '@database/operator/server_data_operator';
import type {Database} from '@nozbe/watermelondb';
jest.mock('@actions/remote/permalink', () => ({
showPermalink: jest.fn(),
}));
jest.mock('@components/markdown', () => ({
__esModule: true,
default: jest.fn(),
@ -29,6 +34,8 @@ describe('components/post_list/post/body/content/permalink_preview/PermalinkPrev
const serverUrl = 'http://localhost:8065';
beforeEach(async () => {
jest.clearAllMocks();
await DatabaseManager.init([serverUrl]);
const serverDatabaseAndOperator = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = serverDatabaseAndOperator.database;
@ -152,6 +159,43 @@ describe('components/post_list/post/body/content/permalink_preview/PermalinkPrev
expect(getByTestId('permalink-preview-container')).toBeTruthy();
});
it('should call showPermalink with correct parameters when container is pressed', () => {
const mockShowPermalink = jest.mocked(showPermalink);
const {getByTestId} = renderPermalinkPreview(baseProps);
const permalinkContainer = getByTestId('permalink-preview-container');
fireEvent.press(permalinkContainer);
expect(mockShowPermalink).toHaveBeenCalledWith(
serverUrl,
baseProps.embedData.team_name,
baseProps.embedData.post_id,
);
});
it('should call showPermalink even when team_name is empty for DM posts', () => {
const mockShowPermalink = jest.mocked(showPermalink);
const dmProps = {
...baseProps,
embedData: {
...baseProps.embedData,
team_name: '',
channel_type: 'D',
channel_display_name: 'testuser',
},
};
const {getByTestId} = renderPermalinkPreview(dmProps);
const permalinkContainer = getByTestId('permalink-preview-container');
fireEvent.press(permalinkContainer);
expect(mockShowPermalink).toHaveBeenCalledWith(
serverUrl,
'',
baseProps.embedData.post_id,
);
});
it('should display author name from user model', () => {
const {getByText} = renderPermalinkPreview(baseProps);

View file

@ -5,16 +5,18 @@ import {LinearGradient} from 'expo-linear-gradient';
import React, {useMemo, useCallback, useEffect, useState} from 'react';
import {Text, View, Pressable, type LayoutChangeEvent} from 'react-native';
import {showPermalink} from '@actions/remote/permalink';
import {fetchUsersByIds} from '@actions/remote/user';
import EditedIndicator from '@components/edited_indicator';
import FormattedText from '@components/formatted_text';
import FormattedTime from '@components/formatted_time';
import Markdown from '@components/markdown';
import ProfilePicture from '@components/profile_picture';
import {View as ViewConstants} from '@constants';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import {useUserLocale} from '@context/user_locale';
import {useWindowDimensions} from '@hooks/device';
import {useIsTablet, useWindowDimensions} from '@hooks/device';
import {usePreventDoubleTap} from '@hooks/utils';
import {getMarkdownTextStyles, getMarkdownBlockStyles} from '@utils/markdown';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -33,6 +35,8 @@ import type {AvailableScreens} from '@typings/screens/navigation';
const MAX_PERMALINK_PREVIEW_CHARACTERS = 150;
const EDITED_INDICATOR_CONTEXT = ['paragraph'];
const EMPTY_MENTION_KEYS: UserMentionKey[] = [];
const MIN_PERMALINK_WIDTH = 340;
const TABLET_PADDING_OFFSET = 40;
type PermalinkPreviewProps = {
embedData: PermalinkEmbedData;
@ -134,9 +138,21 @@ const PermalinkPreview = ({
const serverUrl = useServerUrl();
const locale = useUserLocale();
const dimensions = useWindowDimensions();
const isTablet = useIsTablet();
const styles = getStyleSheet(theme);
const [showGradient, setShowGradient] = useState(false);
const maxWidth = useMemo(() => {
if (!isTablet) {
return undefined;
}
const deviceSize = Math.min(dimensions.width, dimensions.height);
const availableWidth = deviceSize - ViewConstants.TABLET_SIDEBAR_WIDTH;
return Math.max(availableWidth - TABLET_PADDING_OFFSET, MIN_PERMALINK_WIDTH);
}, [dimensions.width, dimensions.height, isTablet]);
const maxPermalinkHeight = Math.round(dimensions.height * 0.5);
const textStyles = getMarkdownTextStyles(theme);
const blockStyles = getMarkdownBlockStyles(theme);
@ -192,8 +208,13 @@ const PermalinkPreview = ({
const hasFiles = filesInfo.length > 0;
const handlePress = usePreventDoubleTap(useCallback(() => {
// Navigation will be implemented in Task 5
}, []));
const teamName = embedData.team_name;
const postId = embedData.post_id;
if (postId) {
showPermalink(serverUrl, teamName, postId);
}
}, [embedData.team_name, embedData.post_id, serverUrl]));
const handleContentLayout = useCallback((event: LayoutChangeEvent) => {
const {height} = event.nativeEvent.layout;
@ -208,7 +229,10 @@ const PermalinkPreview = ({
<Pressable
style={({pressed}) => [
styles.container,
{opacity: pressed ? 0.8 : 1},
{
opacity: pressed ? 0.8 : 1,
maxWidth,
},
]}
onPress={handlePress}
testID='permalink-preview-container'