fix ui freezing due to images in feed changes (#17703)

* fix ui freezing due to images in feed changes

* minor fixes

* change the method to old as there may be case where only updatedValue will be there and we need to show in prettify way rather the showing default message

* fixes around typography styling

* reduce feed size to 25 to get better performance in case of large image feed in the first 25 feeds

(cherry picked from commit 5201a0dcaf0ff62b3f5c364d7a31fd0228800abd)
This commit is contained in:
Ashish Gupta 2024-09-05 18:16:30 +05:30
parent 892e53ade0
commit 50ebdcbf12
6 changed files with 87 additions and 57 deletions

View File

@ -12,7 +12,7 @@
*/ */
import { Typography } from 'antd'; import { Typography } from 'antd';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import React, { ReactNode, useEffect, useState } from 'react'; import React, { ReactNode, useEffect, useMemo, useState } from 'react';
import { ReactComponent as FeedEmptyIcon } from '../../../assets/svg/activity-feed-no-data-placeholder.svg'; import { ReactComponent as FeedEmptyIcon } from '../../../assets/svg/activity-feed-no-data-placeholder.svg';
import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder'; import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { ERROR_PLACEHOLDER_TYPE, SIZE } from '../../../enums/common.enum'; import { ERROR_PLACEHOLDER_TYPE, SIZE } from '../../../enums/common.enum';
@ -68,11 +68,36 @@ const ActivityFeedListV1 = ({
} }
}, [entityThread, selectedThread, onFeedClick]); }, [entityThread, selectedThread, onFeedClick]);
const feeds = useMemo(
() =>
entityThread.map((feed) => (
<FeedPanelBodyV1
componentsVisibility={componentsVisibility}
feed={feed}
hidePopover={hidePopover}
isActive={activeFeedId === feed.id}
isForFeedTab={isForFeedTab}
key={feed.id}
showThread={showThread}
onFeedClick={onFeedClick}
/>
)),
[
entityThread,
activeFeedId,
componentsVisibility,
hidePopover,
isForFeedTab,
showThread,
]
);
if (isLoading) { if (isLoading) {
return <Loader />; return <Loader />;
} }
return isEmpty(entityThread) ? ( if (isEmpty(entityThread)) {
return (
<div <div
className="h-full p-x-md" className="h-full p-x-md"
data-testid="no-data-placeholder-container" data-testid="no-data-placeholder-container"
@ -87,20 +112,12 @@ const ActivityFeedListV1 = ({
</Typography.Paragraph> </Typography.Paragraph>
</ErrorPlaceHolder> </ErrorPlaceHolder>
</div> </div>
) : ( );
}
return (
<div className="feed-list-container p-md" id="feedData"> <div className="feed-list-container p-md" id="feedData">
{entityThread.map((feed) => ( {feeds}
<FeedPanelBodyV1
componentsVisibility={componentsVisibility}
feed={feed}
hidePopover={hidePopover}
isActive={activeFeedId === feed.id}
isForFeedTab={isForFeedTab}
key={feed.id}
showThread={showThread}
onFeedClick={onFeedClick}
/>
))}
</div> </div>
); );
}; };

View File

@ -74,6 +74,11 @@ import {
ActivityFeedTabs, ActivityFeedTabs,
} from './ActivityFeedTab.interface'; } from './ActivityFeedTab.interface';
const componentsVisibility = {
showThreadIcon: false,
showRepliesContainer: true,
};
export const ActivityFeedTab = ({ export const ActivityFeedTab = ({
fqn, fqn,
owners = [], owners = [],
@ -429,10 +434,7 @@ export const ActivityFeedTab = ({
<ActivityFeedListV1 <ActivityFeedListV1
hidePopover hidePopover
activeFeedId={selectedThread?.id} activeFeedId={selectedThread?.id}
componentsVisibility={{ componentsVisibility={componentsVisibility}
showThreadIcon: false,
showRepliesContainer: true,
}}
emptyPlaceholderText={placeholderText} emptyPlaceholderText={placeholderText}
feedList={entityThread} feedList={entityThread}
isForFeedTab={isForFeedTab} isForFeedTab={isForFeedTab}

View File

@ -17,7 +17,7 @@ import { isUndefined } from 'lodash';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link, useHistory } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import { PAGE_SIZE_LARGE, ROUTES } from '../../../../constants/constants'; import { PAGE_SIZE_MEDIUM, ROUTES } from '../../../../constants/constants';
import { FEED_COUNT_INITIAL_DATA } from '../../../../constants/entity.constants'; import { FEED_COUNT_INITIAL_DATA } from '../../../../constants/entity.constants';
import { mockFeedData } from '../../../../constants/mockTourData.constants'; import { mockFeedData } from '../../../../constants/mockTourData.constants';
import { useTourProvider } from '../../../../context/TourProvider/TourProvider'; import { useTourProvider } from '../../../../context/TourProvider/TourProvider';
@ -70,7 +70,7 @@ const FeedsWidget = ({
undefined, undefined,
undefined, undefined,
undefined, undefined,
PAGE_SIZE_LARGE PAGE_SIZE_MEDIUM
); );
} else if (activeTab === ActivityFeedTabs.MENTIONS) { } else if (activeTab === ActivityFeedTabs.MENTIONS) {
getFeedData(FeedFilter.MENTIONS); getFeedData(FeedFilter.MENTIONS);
@ -175,6 +175,21 @@ const FeedsWidget = ({
!isUndefined(handleRemoveWidget) && handleRemoveWidget(widgetKey); !isUndefined(handleRemoveWidget) && handleRemoveWidget(widgetKey);
}, [widgetKey]); }, [widgetKey]);
const emptyPlaceholderText = useMemo(
() => (
<Transi18next
i18nKey="message.no-activity-feed"
renderElement={
<Link rel="noreferrer" to={{ pathname: ROUTES.EXPLORE }} />
}
values={{
explored: t('message.have-not-explored-yet'),
}}
/>
),
[]
);
return ( return (
<div <div
className="feeds-widget-container h-full" className="feeds-widget-container h-full"
@ -189,20 +204,7 @@ const FeedsWidget = ({
children: ( children: (
<> <>
<ActivityFeedListV1 <ActivityFeedListV1
emptyPlaceholderText={ emptyPlaceholderText={emptyPlaceholderText}
<Transi18next
i18nKey="message.no-activity-feed"
renderElement={
<Link
rel="noreferrer"
to={{ pathname: ROUTES.EXPLORE }}
/>
}
values={{
explored: t('message.have-not-explored-yet'),
}}
/>
}
feedList={isTourOpen ? mockFeedData : threads} feedList={isTourOpen ? mockFeedData : threads}
hidePopover={isEditView} hidePopover={isEditView}
isLoading={loading && !isTourOpen} isLoading={loading && !isTourOpen}

View File

@ -12,7 +12,7 @@
*/ */
import { act, fireEvent, render, screen } from '@testing-library/react'; import { act, fireEvent, render, screen } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { PAGE_SIZE_LARGE } from '../../../../constants/constants'; import { PAGE_SIZE_MEDIUM } from '../../../../constants/constants';
import { useApplicationStore } from '../../../../hooks/useApplicationStore'; import { useApplicationStore } from '../../../../hooks/useApplicationStore';
import { mockUserData } from '../../../Settings/Users/mocks/User.mocks'; import { mockUserData } from '../../../Settings/Users/mocks/User.mocks';
import FeedsWidget from './FeedsWidget.component'; import FeedsWidget from './FeedsWidget.component';
@ -134,7 +134,7 @@ describe('FeedsWidget', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
PAGE_SIZE_LARGE PAGE_SIZE_MEDIUM
); );
}); });
@ -154,7 +154,7 @@ describe('FeedsWidget', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
PAGE_SIZE_LARGE PAGE_SIZE_MEDIUM
); );
}); });

View File

@ -154,6 +154,9 @@ a[href].link-text-grey,
.text-underline { .text-underline {
text-decoration: underline; text-decoration: underline;
} }
.text-line-through {
text-decoration: line-through;
}
// image property // image property

View File

@ -137,33 +137,31 @@ export const getDiffValue = (oldValue: string, newValue: string) => {
export const getAddedDiffElement = (text: string) => { export const getAddedDiffElement = (text: string) => {
return ( return (
<Typography.Text <span
underline className="diff-added text-underline"
className="diff-added"
data-testid="diff-added" data-testid="diff-added"
key={uniqueId()}> key={uniqueId()}>
{text} {text}
</Typography.Text> </span>
); );
}; };
export const getRemovedDiffElement = (text: string) => { export const getRemovedDiffElement = (text: string) => {
return ( return (
<Typography.Text <span
delete className="text-grey-muted text-line-through"
className="text-grey-muted"
data-testid="diff-removed" data-testid="diff-removed"
key={uniqueId()}> key={uniqueId()}>
{text} {text}
</Typography.Text> </span>
); );
}; };
export const getNormalDiffElement = (text: string) => { export const getNormalDiffElement = (text: string) => {
return ( return (
<Typography.Text data-testid="diff-normal" key={uniqueId()}> <span data-testid="diff-normal" key={uniqueId()}>
{text} {text}
</Typography.Text> </span>
); );
}; };
@ -172,10 +170,18 @@ export const getTextDiff = (
newText: string, newText: string,
latestText?: string latestText?: string
) => { ) => {
const imagePlaceholder = 'data:image';
if (isEmpty(oldText) && isEmpty(newText)) { if (isEmpty(oldText) && isEmpty(newText)) {
return latestText ?? ''; return latestText ?? '';
} }
if (
newText.includes(imagePlaceholder) ||
oldText.includes(imagePlaceholder)
) {
return newText;
}
const diffArr = diffWords(toString(oldText), toString(newText)); const diffArr = diffWords(toString(oldText), toString(newText));
const result = diffArr.map((diff) => { const result = diffArr.map((diff) => {