🔥(frontend) remove starred from here (#588)

The user was able to starred a thread from a message to act like a pointer but
this feature is too confusing so we prefer to remove it.
This commit is contained in:
Jean-Baptiste PENRATH
2026-03-12 10:00:06 +01:00
committed by GitHub
parent b1d455022c
commit b6e4ef2974
8 changed files with 16 additions and 110 deletions

View File

@@ -44,11 +44,6 @@ test.describe("Thread starred", () => {
// Star the thread
await starButton.click();
// Verify the starred marker appears in thread view
await expect(
page.getByText("This thread has been starred."),
).toBeVisible();
// Verify the button updates to "Unstar"
await expect(
page.getByRole("button", { name: "Unstar this thread" }),
@@ -87,11 +82,6 @@ test.describe("Thread starred", () => {
// Unstar the thread
await unstarButton.click();
// Verify the starred marker disappears
await expect(
page.getByText("This thread has been starred."),
).not.toBeVisible();
// Verify the button reverts to "Star this thread"
await expect(
page.getByRole("button", { name: "Star this thread" }),

View File

@@ -471,7 +471,6 @@
"Split thread from here": "Split thread from here",
"Star {{count}} threads_one": "Star {{count}} thread",
"Star {{count}} threads_other": "Star {{count}} threads",
"Star from here": "Star from here",
"Star this thread": "Star this thread",
"Starred": "Starred",
"Start typing...": "Start typing...",
@@ -525,7 +524,6 @@
"This signature is forced": "This signature is forced",
"This thread has been reported as spam.": "This thread has been reported as spam.",
"This thread has been reported as spam. For your security, downloading attachments has been disabled.": "This thread has been reported as spam. For your security, downloading attachments has been disabled.",
"This thread has been starred.": "This thread has been starred.",
"This will move this message and all following messages to a new thread. Continue?": "This will move this message and all following messages to a new thread. Continue?",
"Those message templates are linked to the mailbox \"{{mailbox}}\". In case of a shared mailbox, all other mailbox users will be able to use them.": "Those message templates are linked to the mailbox \"{{mailbox}}\". In case of a shared mailbox, all other mailbox users will be able to use them.",
"Those signatures are linked to the mailbox \"{{mailbox}}\". In case of a shared mailbox, all other mailbox users will be able to use them.": "Those signatures are linked to the mailbox \"{{mailbox}}\". In case of a shared mailbox, all other mailbox users will be able to use them.",

View File

@@ -520,7 +520,6 @@
"Star {{count}} threads_one": "Suivre {{count}} conversation",
"Star {{count}} threads_many": "Suivre {{count}} conversations",
"Star {{count}} threads_other": "Suivre {{count}} conversations",
"Star from here": "Suivre à partir d'ici",
"Star this thread": "Suivre cette conversation",
"Starred": "Suivi",
"Start typing...": "Commencez à écrire...",
@@ -575,7 +574,6 @@
"This signature is forced": "Cette signature est forcée",
"This thread has been reported as spam.": "Cette conversation a été signalée comme spam.",
"This thread has been reported as spam. For your security, downloading attachments has been disabled.": "Cette conversation a été signalée comme spam. Pour votre sécurité, le téléchargement des pièces jointes a été désactivé.",
"This thread has been starred.": "Cette conversation a été marquée pour suivi.",
"This will move this message and all following messages to a new thread. Continue?": "Cela déplacera ce message et tous les messages suivants dans une nouvelle conversation. Continuer ?",
"Those message templates are linked to the mailbox \"{{mailbox}}\". In case of a shared mailbox, all other mailbox users will be able to use them.": "Ces modèles de message sont liés à la boîte aux lettres \"{{mailbox}}\". Dans le cas d'une boîte aux lettres partagée, tous les autres utilisateurs de la boîte aux lettres pourront les utiliser.",
"Those signatures are linked to the mailbox \"{{mailbox}}\". In case of a shared mailbox, all other mailbox users will be able to use them.": "Ces signatures sont liées à la boîte aux lettres \"{{mailbox}}\". Dans le cas d'une boîte aux lettres partagée, tous les autres utilisateurs de la boîte aux lettres pourront les utiliser.",

View File

@@ -1,32 +0,0 @@
.starred-marker {
display: flex;
align-items: center;
gap: var(--c--globals--spacings--xs);
padding-block: var(--c--globals--spacings--xs);
padding-right: var(--c--globals--spacings--sm);
justify-content: flex-end;
}
.starred-marker::after {
display: block;
content: '';
height: 1px;
background-color: var(--c--contextuals--background--semantic--neutral--primary);
width: 8px;
}
.starred-marker__label {
display: flex;
align-items: center;
gap: var(--c--globals--spacings--3xs);
font-size: var(--c--globals--font--sizes--xs);
color: var(--c--contextuals--background--semantic--neutral--primary);
font-style: italic;
line-height: 1;
white-space: nowrap;
}
.starred-marker__icon {
font-size: var(--c--globals--font--sizes--sm);
color: var(--c--contextuals--background--semantic--neutral--primary);
}

View File

@@ -1,15 +0,0 @@
import { useTranslation } from "react-i18next"
import { Icon, IconType } from "@gouvfr-lasuite/ui-kit"
export const StarredMarker = () => {
const { t } = useTranslation()
return (
<div className="starred-marker">
<span className="starred-marker__label">
<Icon name="star" type={IconType.FILLED} className="starred-marker__icon" />
{t("This thread has been starred.")}
</span>
</div>
)
}

View File

@@ -7,7 +7,6 @@ import { getRequestUrl } from "@/features/api/utils";
import { useMailboxContext } from "@/features/providers/mailbox";
import usePrint from "@/features/message/use-print";
import useRead from "@/features/message/use-read";
import useStarred from "@/features/message/use-starred";
import useSplitThread from "@/features/message/use-split-thread";
import useTrash from "@/features/message/use-trash";
import { ThreadMessageActionsProps } from "./types";
@@ -25,9 +24,8 @@ const ThreadMessageActions = ({
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
// Hooks and state specific to actions
const { unselectThread, selectedThread, selectedMailbox } = useMailboxContext();
const { unselectThread, selectedThread } = useMailboxContext();
const { markAsReadAt } = useRead();
const { markAsStarred } = useStarred();
const { markAsTrashed } = useTrash();
const { splitThread } = useSplitThread();
const { print } = usePrint();
@@ -60,14 +58,6 @@ const ThreadMessageActions = ({
}
}, [message.id, message.created_at, unselectThread, selectedThread, markAsReadAt]);
const starredAt = selectedThread?.accesses.find(a => a.mailbox.id === selectedMailbox?.id)?.starred_at ?? null;
const isAlreadyStarredFromHere = starredAt === message.created_at;
const handleStarredFrom = useCallback(() => {
if (!selectedThread) return;
markAsStarred({ threadIds: [selectedThread.id], starredAt: message.created_at! });
}, [selectedThread, message.created_at, markAsStarred]);
const handleMarkAsTrashed = useCallback(() => {
markAsTrashed({ messageIds: [message.id] });
}, [markAsTrashed, message.id]);
@@ -115,11 +105,6 @@ const ThreadMessageActions = ({
icon: <Icon type={IconType.FILLED} name="mark_email_unread" />,
callback: () => toggleReadStateFrom(true)
}]),
...(!isAlreadyStarredFromHere && hasSiblingMessages ? [{
label: t('Star from here'),
icon: <Icon type={IconType.FILLED} name="star_border" />,
callback: handleStarredFrom,
}] : []),
...(canSplitThread ? [{
label: t('Split thread from here'),
icon: <Icon type={IconType.FILLED} name="call_split" />,

View File

@@ -12,7 +12,6 @@ import { SKIP_LINK_TARGET_ID } from "@/features/ui/components/skip-link"
import { useTranslation } from "react-i18next"
import { ThreadViewLabelsList } from "./components/thread-view-labels-list"
import { ThreadSummary } from "./components/thread-summary";
import { StarredMarker } from "./components/starred-marker";
import clsx from "clsx";
import ThreadViewProvider, { useThreadViewContext } from "./provider";
import useSpam from "@/features/message/use-spam";
@@ -58,18 +57,6 @@ const ThreadViewComponent = ({ messages, mailboxId, thread, showTrashedMessages,
}
return acc;
}, messages[0]);
const starredAt = thread.accesses.find(a => a.mailbox.id === mailboxId)?.starred_at ?? null;
const starredMarkerInsertIndex = useMemo(() => {
// Find insertion index: marker goes after the last message whose created_at <= starred_at
let starredInsertIndex = null;
if (starredAt) {
starredInsertIndex = messages.findLastIndex((message) => {
return message.created_at <= starredAt
});
return starredInsertIndex;
}
return starredInsertIndex;
}, [starredAt, messages]);
/**
* Setup an intersection observer to mark messages as read when they are
@@ -173,8 +160,11 @@ const ThreadViewComponent = ({ messages, mailboxId, thread, showTrashedMessages,
{stats.trashed > 0 && !showTrashedMessages && (
<Banner
icon={<Icon name="delete" type={IconType.OUTLINED} />}
type="info" actions={[{ label: t('Show'),
onClick: () => setShowTrashedMessages(!showTrashedMessages) }]}
type="info"
actions={[{
label: t('Show'),
onClick: () => setShowTrashedMessages(!showTrashedMessages)
}]}
>
{t(
'{{count}} messages of this thread have been deleted.',
@@ -186,26 +176,19 @@ const ThreadViewComponent = ({ messages, mailboxId, thread, showTrashedMessages,
</Banner>
)}
{(() => {
return messages.map((message, index) => {
return messages.map((message) => {
const isLatest = latestMessage?.id === message.id;
const isUnread = message.is_unread;
return (
<React.Fragment key={message.id}>
{starredMarkerInsertIndex === -1 && index === 0 && (
<StarredMarker />
)}
<ThreadMessage
message={message}
isLatest={isLatest}
ref={isUnread ? (el => { unreadRefs.current[message.id] = el; }) : undefined}
data-message-id={message.id}
data-created-at={message.created_at}
draftMessage={message.draft_message}
/>
{starredMarkerInsertIndex === index && (
<StarredMarker />
)}
</React.Fragment>
<ThreadMessage
key={message.id}
message={message}
isLatest={isLatest}
ref={isUnread ? (el => { unreadRefs.current[message.id] = el; }) : undefined}
data-message-id={message.id}
data-created-at={message.created_at}
draftMessage={message.draft_message}
/>
);
});
})()}

View File

@@ -43,7 +43,6 @@
@use "./../features/layouts/components/thread-view/components/calendar-invite";
@use "./../features/layouts/components/thread-view/components/thread-accesses-widget";
@use "./../features/layouts/components/thread-view/components/thread-labels-widget";
@use "./../features/layouts/components/thread-view/components/starred-marker";
@use "./../features/forms/components/message-form";
@use "./../features/forms/components/search-input";
@use "./../features/forms/components/search-filters-form";