Fixed: Truncate long text in tag values

(cherry picked from commit 93c3f6d1d6b50a7ae06aca083aba5297d8d8b6e8)
This commit is contained in:
Mark McDowall 2024-11-24 17:40:15 -08:00 committed by Bogdan
parent a9bbe06966
commit efd2b80e10
6 changed files with 72 additions and 8 deletions

View file

@ -0,0 +1,63 @@
import React, { useEffect, useRef, useState } from 'react';
import useMeasure from 'Helpers/Hooks/useMeasure';
interface MiddleTruncateProps {
text: string;
}
function getTruncatedText(text: string, length: number) {
return `${text.slice(0, length)}...${text.slice(text.length - length)}`;
}
function MiddleTruncate({ text }: MiddleTruncateProps) {
const [containerRef, { width: containerWidth }] = useMeasure();
const [textRef, { width: textWidth }] = useMeasure();
const [truncatedText, setTruncatedText] = useState(text);
const truncatedTextRef = useRef(text);
useEffect(() => {
setTruncatedText(text);
}, [text]);
useEffect(() => {
if (!containerWidth || !textWidth) {
return;
}
if (textWidth <= containerWidth) {
return;
}
const characterLength = textWidth / text.length;
const charactersToRemove =
Math.ceil(text.length - containerWidth / characterLength) + 3;
let length = Math.ceil(text.length / 2 - charactersToRemove / 2);
let updatedText = getTruncatedText(text, length);
// Make sure if the text is still too long, we keep reducing the length
// each time we re-run this.
while (
updatedText.length >= truncatedTextRef.current.length &&
length > 10
) {
length--;
updatedText = getTruncatedText(text, length);
}
// Store the value in the ref so we can compare it in the next render,
// without triggering this effect every time we change the text.
truncatedTextRef.current = updatedText;
setTruncatedText(updatedText);
}, [text, truncatedTextRef, containerWidth, textWidth]);
return (
<div ref={containerRef} style={{ whiteSpace: 'nowrap' }}>
<div ref={textRef} style={{ display: 'inline-block' }}>
{truncatedText}
</div>
</div>
);
}
export default MiddleTruncate;

View file

@ -3,6 +3,7 @@ import { useDispatch } from 'react-redux';
import { Tag } from 'App/State/TagsAppState';
import Card from 'Components/Card';
import Label from 'Components/Label';
import MiddleTruncate from 'Components/MiddleTruncate';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import TagList from 'Components/TagList';
import useModalOpenState from 'Helpers/Hooks/useModalOpenState';
@ -12,14 +13,14 @@ import Indexer from 'typings/Indexer';
import ReleaseProfile from 'typings/Settings/ReleaseProfile';
import translate from 'Utilities/String/translate';
import EditReleaseProfileModal from './EditReleaseProfileModal';
import styles from './ReleaseProfileRow.css';
import styles from './ReleaseProfileItem.css';
interface ReleaseProfileProps extends ReleaseProfile {
tagList: Tag[];
indexerList: Indexer[];
}
function ReleaseProfileRow(props: ReleaseProfileProps) {
function ReleaseProfileItem(props: ReleaseProfileProps) {
const {
id,
name,
@ -69,7 +70,7 @@ function ReleaseProfileRow(props: ReleaseProfileProps) {
return (
<Label key={item} className={styles.label} kind={kinds.SUCCESS}>
{item}
<MiddleTruncate text={item} />
</Label>
);
})}
@ -83,7 +84,7 @@ function ReleaseProfileRow(props: ReleaseProfileProps) {
return (
<Label key={item} className={styles.label} kind={kinds.DANGER}>
{item}
<MiddleTruncate text={item} />
</Label>
);
})}
@ -127,4 +128,4 @@ function ReleaseProfileRow(props: ReleaseProfileProps) {
);
}
export default ReleaseProfileRow;
export default ReleaseProfileItem;

View file

@ -4,7 +4,7 @@
}
.addReleaseProfile {
composes: releaseProfile from '~./ReleaseProfileRow.css';
composes: releaseProfile from '~./ReleaseProfileItem.css';
background-color: var(--cardAlternateBackgroundColor);
color: var(--gray);

View file

@ -8,13 +8,13 @@ import Icon from 'Components/Icon';
import PageSectionContent from 'Components/Page/PageSectionContent';
import useModalOpenState from 'Helpers/Hooks/useModalOpenState';
import { icons } from 'Helpers/Props';
import ReleaseProfileRow from 'Settings/Profiles/Release/ReleaseProfileRow';
import { fetchIndexers } from 'Store/Actions/Settings/indexers';
import { fetchReleaseProfiles } from 'Store/Actions/Settings/releaseProfiles';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import createTagsSelector from 'Store/Selectors/createTagsSelector';
import translate from 'Utilities/String/translate';
import EditReleaseProfileModal from './EditReleaseProfileModal';
import ReleaseProfileItem from './ReleaseProfileItem';
import styles from './ReleaseProfiles.css';
function ReleaseProfiles() {
@ -59,7 +59,7 @@ function ReleaseProfiles() {
{items.map((item) => {
return (
<ReleaseProfileRow
<ReleaseProfileItem
key={item.id}
tagList={tagList}
indexerList={indexerList}