1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-18 21:35:27 -04:00

Fixed: Truncating long text in the middle when it shouldn't be truncated

Closes #7413
This commit is contained in:
Mark McDowall
2024-11-24 17:40:15 -08:00
parent 417af2b915
commit 93c3f6d1d6
11 changed files with 78 additions and 61 deletions
@@ -1,8 +1,8 @@
import React, { useCallback } from 'react';
import MiddleTruncate from 'react-middle-truncate';
import Label, { LabelProps } from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import MiddleTruncate from 'Components/MiddleTruncate';
import { icons } from 'Helpers/Props';
import { TagBase } from './TagInput';
import styles from './TagInputTag.css';
@@ -58,7 +58,7 @@ function TagInputTag<T extends TagBase>({
tabIndex={-1}
onPress={handleDelete}
>
<MiddleTruncate text={String(tag.name)} start={10} end={10} />
<MiddleTruncate text={String(tag.name)} />
</Link>
{canEdit ? (
@@ -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;
@@ -1,9 +1,9 @@
import React, { useCallback } from 'react';
import MiddleTruncate from 'react-middle-truncate';
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';
@@ -13,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,
@@ -70,7 +70,7 @@ function ReleaseProfileRow(props: ReleaseProfileProps) {
return (
<Label key={item} className={styles.label} kind={kinds.SUCCESS}>
<MiddleTruncate text={item} start={10} end={10} />
<MiddleTruncate text={item} />
</Label>
);
})}
@@ -84,7 +84,7 @@ function ReleaseProfileRow(props: ReleaseProfileProps) {
return (
<Label key={item} className={styles.label} kind={kinds.DANGER}>
<MiddleTruncate text={item} start={10} end={10} />
<MiddleTruncate text={item} />
</Label>
);
})}
@@ -128,4 +128,4 @@ function ReleaseProfileRow(props: ReleaseProfileProps) {
);
}
export default ReleaseProfileRow;
export default ReleaseProfileItem;
@@ -4,7 +4,7 @@
}
.addReleaseProfile {
composes: releaseProfile from '~./ReleaseProfileRow.css';
composes: releaseProfile from '~./ReleaseProfileItem.css';
background-color: var(--cardAlternateBackgroundColor);
color: var(--gray);
@@ -14,7 +14,7 @@ import createClientSideCollectionSelector from 'Store/Selectors/createClientSide
import createTagsSelector from 'Store/Selectors/createTagsSelector';
import translate from 'Utilities/String/translate';
import EditReleaseProfileModal from './EditReleaseProfileModal';
import ReleaseProfileRow from './ReleaseProfileRow';
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}