resolve optimization problems, fix admin UX
Some checks failed
pl-api CI / Test for pl-api formatting (22.x) (push) Has been cancelled
pl-fe CI / Test and upload artifacts (22.x) (push) Has been cancelled
pl-fe CI / deploy (push) Has been cancelled
pl-hooks CI / Test for a successful build (22.x) (push) Has been cancelled

This commit is contained in:
2026-02-14 16:47:44 +00:00
parent 7c87edc28a
commit 389f060080
7 changed files with 29 additions and 19 deletions

View File

@ -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<IStatusReactionsBar> = ({ 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<IStatusReactionsBar> = ({ 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 (
<div className='⁂-status-reactions-bar'>
{sortedReactions.map((reaction) => reaction.count ? (

View File

@ -11,8 +11,10 @@ interface IAccountContainer extends Omit<IAccount, 'account'> {
const AccountContainer: React.FC<IAccountContainer> = ({ id, withRelationship, ...props }) => {
const { account } = useAccount(id, { withRelationship });
if (!account) return null;
return (
<Account account={account!} withRelationship={withRelationship} {...props} />
<Account account={account} withRelationship={withRelationship} {...props} />
);
};

View File

@ -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<IChatProvider> = ({ 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,

View File

@ -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 = <TEntity extends Entity>(
return ids.filter((id) => !cache.store[id]);
});
const entityMap = useAppSelector((state) => selectEntityMap<TEntity>(state, path, ids));
const entityMap = useAppSelector((state) => selectEntityMap<TEntity>(state, path, ids), shallowEqual);
const fetchEntities = async () => {
const isFetching = selectListState(getState(), path, 'fetching');

View File

@ -17,15 +17,14 @@ const Conversation: React.FC<IConversation> = ({ 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) {

View File

@ -169,6 +169,11 @@ const Dashboard: React.FC = () => {
</DashCounters>
<List>
<ListItem
to='/pl-fe/admin/users'
label={<FormattedMessage id='admin.latest_accounts_panel.title' defaultMessage='Latest accounts' />}
/>
{features.pleromaAdminAccounts && account.is_admin && (
<ListItem
to='/pl-fe/config'

View File

@ -131,6 +131,6 @@ const useModalsStore = create<State>()(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 };