From 389f0600805b29e560417f996f4d5953e9a5aa18 Mon Sep 17 00:00:00 2001 From: matty Date: Sat, 14 Feb 2026 16:47:44 +0000 Subject: [PATCH] resolve optimization problems, fix admin UX --- .../src/components/status-reactions-bar.tsx | 9 ++++++--- .../pl-fe/src/containers/account-container.tsx | 4 +++- packages/pl-fe/src/contexts/chat-context.tsx | 8 ++++---- .../entity-store/hooks/use-batched-entities.ts | 3 ++- .../conversations/components/conversation.tsx | 17 ++++++++--------- .../pl-fe/src/pages/dashboard/dashboard.tsx | 5 +++++ packages/pl-fe/src/stores/modals.ts | 2 +- 7 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packages/pl-fe/src/components/status-reactions-bar.tsx b/packages/pl-fe/src/components/status-reactions-bar.tsx index b74a091bb..1e11d0d9a 100644 --- a/packages/pl-fe/src/components/status-reactions-bar.tsx +++ b/packages/pl-fe/src/components/status-reactions-bar.tsx @@ -1,5 +1,5 @@ import clsx from 'clsx'; -import React from 'react'; +import React, { useMemo } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { emojiReact, unEmojiReact } from '@/actions/emoji-reacts'; @@ -105,6 +105,11 @@ const StatusReactionsBar: React.FC = ({ status, collapsed } const { demetricator } = useSettings(); const features = useFeatures(); + const sortedReactions = useMemo( + () => status.emoji_reactions.toSorted((a, b) => (b.count || 0) - (a.count || 0)), + [status.emoji_reactions], + ); + const handlePickEmoji = (emoji: EmojiType) => { dispatch(emojiReact(status.id, emoji.custom ? emoji.id : emoji.native, emoji.custom ? emoji.imageUrl : undefined, intl)); }; @@ -112,8 +117,6 @@ const StatusReactionsBar: React.FC = ({ status, collapsed } if ((demetricator || status.emoji_reactions.length === 0) && collapsed) return null; if (status.emoji_reactions.length === 0 && !features.emojiReacts) return null; - const sortedReactions = status.emoji_reactions.toSorted((a, b) => (b.count || 0) - (a.count || 0)); - return (
{sortedReactions.map((reaction) => reaction.count ? ( diff --git a/packages/pl-fe/src/containers/account-container.tsx b/packages/pl-fe/src/containers/account-container.tsx index 44457820b..35e3344c3 100644 --- a/packages/pl-fe/src/containers/account-container.tsx +++ b/packages/pl-fe/src/containers/account-container.tsx @@ -11,8 +11,10 @@ interface IAccountContainer extends Omit { const AccountContainer: React.FC = ({ id, withRelationship, ...props }) => { const { account } = useAccount(id, { withRelationship }); + if (!account) return null; + return ( - + ); }; diff --git a/packages/pl-fe/src/contexts/chat-context.tsx b/packages/pl-fe/src/contexts/chat-context.tsx index adf92d5ec..9e4485228 100644 --- a/packages/pl-fe/src/contexts/chat-context.tsx +++ b/packages/pl-fe/src/contexts/chat-context.tsx @@ -1,5 +1,5 @@ import { useMatch } from '@tanstack/react-router'; -import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; +import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { toggleChatPane } from '@/actions/chats'; import { chatRoute, layouts } from '@/features/ui/router'; @@ -40,12 +40,12 @@ const ChatProvider: React.FC = ({ children }) => { const isOpen = chats.mainWindow === 'open'; - const changeScreen = (screen: ChatWidgetScreens, currentChatId?: string | null) => { + const changeScreen = useCallback((screen: ChatWidgetScreens, currentChatId?: string | null) => { setCurrentChatId(currentChatId || null); setScreen(screen); - }; + }, []); - const handleChatPaneToggle = () => dispatch(toggleChatPane()); + const handleChatPaneToggle = useCallback(() => dispatch(toggleChatPane()), []); const value = useMemo(() => ({ chat, diff --git a/packages/pl-fe/src/entity-store/hooks/use-batched-entities.ts b/packages/pl-fe/src/entity-store/hooks/use-batched-entities.ts index 0415cf7db..8f6ceeec0 100644 --- a/packages/pl-fe/src/entity-store/hooks/use-batched-entities.ts +++ b/packages/pl-fe/src/entity-store/hooks/use-batched-entities.ts @@ -1,4 +1,5 @@ import { useEffect } from 'react'; +import { shallowEqual } from 'react-redux'; import * as v from 'valibot'; import { useAppDispatch } from '@/hooks/use-app-dispatch'; @@ -45,7 +46,7 @@ const useBatchedEntities = ( return ids.filter((id) => !cache.store[id]); }); - const entityMap = useAppSelector((state) => selectEntityMap(state, path, ids)); + const entityMap = useAppSelector((state) => selectEntityMap(state, path, ids), shallowEqual); const fetchEntities = async () => { const isFetching = selectListState(getState(), path, 'fetching'); diff --git a/packages/pl-fe/src/features/conversations/components/conversation.tsx b/packages/pl-fe/src/features/conversations/components/conversation.tsx index ec85fc158..ffc04d700 100644 --- a/packages/pl-fe/src/features/conversations/components/conversation.tsx +++ b/packages/pl-fe/src/features/conversations/components/conversation.tsx @@ -17,15 +17,14 @@ const Conversation: React.FC = ({ conversationId, onMoveUp, onMov const dispatch = useAppDispatch(); const navigate = useNavigate(); - const { accounts, unread, lastStatusId } = useAppSelector((state) => { - const conversation = state.conversations.items.find(x => x.id === conversationId)!; - - return { - accounts: conversation.accounts.map((accountId: string) => selectAccount(state, accountId)!), - unread: conversation.unread, - lastStatusId: conversation.last_status, - }; - }); + const conversation = useAppSelector((state) => + state.conversations.items.find(x => x.id === conversationId)!, + ); + const accounts = useAppSelector((state) => + conversation.accounts.map((accountId: string) => selectAccount(state, accountId)!), + ); + const unread = conversation.unread; + const lastStatusId = conversation.last_status; const handleClick = () => { if (unread) { diff --git a/packages/pl-fe/src/pages/dashboard/dashboard.tsx b/packages/pl-fe/src/pages/dashboard/dashboard.tsx index fed281449..e3a35af16 100644 --- a/packages/pl-fe/src/pages/dashboard/dashboard.tsx +++ b/packages/pl-fe/src/pages/dashboard/dashboard.tsx @@ -169,6 +169,11 @@ const Dashboard: React.FC = () => { + } + /> + {features.pleromaAdminAccounts && account.is_admin && ( ()(mutative((set) => ({ const useModalsActions = () => useModalsStore((state) => state.actions); const useModals = () => useModalsStore((state) => state.modals); -const useHasModals = () => useModals().length > 0; +const useHasModals = () => useModalsStore((state) => state.modals.length > 0); export { useModalsStore, useModalsActions, useModals, useHasModals };