From 368b6d62829b3e4f9ae2bc46d06852139d6dd67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 15:19:25 +0100 Subject: [PATCH] pl-fe: fix chats in mobile view and clean some of the chats routing fuckery up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../src/components/sidebar-navigation.tsx | 2 +- .../src/components/status-action-bar.tsx | 2 +- .../pl-fe/src/components/thumb-navigation.tsx | 2 +- .../features/account/components/header.tsx | 2 +- .../chats/components/chat-list-item.tsx | 2 +- .../chats/components/chat-page/chat-page.tsx | 12 +- .../chat-page/components/chat-page-chat.tsx | 156 +++++++++++++++++ .../chat-page/components/chat-page-main.tsx | 160 +----------------- .../chat-page/components/chat-page-new.tsx | 2 +- .../components/chat-page-settings.tsx | 2 +- .../components/chat-page-shoutbox.tsx | 2 +- .../components/chat-page-sidebar.tsx | 2 +- .../components/chat-search/chat-search.tsx | 2 +- .../event/components/event-header.tsx | 2 +- .../pl-fe/src/features/ui/router/index.tsx | 10 +- 15 files changed, 186 insertions(+), 174 deletions(-) create mode 100644 packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-chat.tsx diff --git a/packages/pl-fe/src/components/sidebar-navigation.tsx b/packages/pl-fe/src/components/sidebar-navigation.tsx index 9df14e472..a4eed97fb 100644 --- a/packages/pl-fe/src/components/sidebar-navigation.tsx +++ b/packages/pl-fe/src/components/sidebar-navigation.tsx @@ -272,7 +272,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) {features.chats && ( = ({ const account = status.account; getOrCreateChatByAccountId(account.id) - .then((chat) => navigate({ to: '/chats/{-$chatId}', params: { chatId: chat.id } })) + .then((chat) => navigate({ to: '/chats/$chatId', params: { chatId: chat.id } })) .catch(() => {}); }; diff --git a/packages/pl-fe/src/components/thumb-navigation.tsx b/packages/pl-fe/src/components/thumb-navigation.tsx index f700662db..4808abd0b 100644 --- a/packages/pl-fe/src/components/thumb-navigation.tsx +++ b/packages/pl-fe/src/components/thumb-navigation.tsx @@ -120,7 +120,7 @@ const ThumbNavigation: React.FC = React.memo((): JSX.Element => { src={require('@phosphor-icons/core/regular/chats-teardrop.svg')} activeSrc={require('@phosphor-icons/core/fill/chats-teardrop-fill.svg')} text={intl.formatMessage(messages.chats)} - to='/chats/{-$chatId}' + to='/chats' exact count={unreadChatsCount} countMax={9} diff --git a/packages/pl-fe/src/features/account/components/header.tsx b/packages/pl-fe/src/features/account/components/header.tsx index d810308f8..fc3658500 100644 --- a/packages/pl-fe/src/features/account/components/header.tsx +++ b/packages/pl-fe/src/features/account/components/header.tsx @@ -166,7 +166,7 @@ const Header: React.FC = ({ account }) => { toast.error(data?.error); }, onSuccess: (response) => { - navigate({ to: '/chats/{-$chatId}', params: { chatId: response.id } }); + navigate({ to: '/chats/$chatId', params: { chatId: response.id } }); queryClient.invalidateQueries({ queryKey: ['chats', 'search'], }); diff --git a/packages/pl-fe/src/features/chats/components/chat-list-item.tsx b/packages/pl-fe/src/features/chats/components/chat-list-item.tsx index 8451ab7ad..74c324e0b 100644 --- a/packages/pl-fe/src/features/chats/components/chat-list-item.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-list-item.tsx @@ -59,7 +59,7 @@ const ChatListItem: React.FC = ({ chat, onClick }) => { deleteChat.mutate(undefined, { onSuccess() { if (isUsingMainChatPage) { - navigate({ to: '/chats/{-$chatId}' }); + navigate({ to: '/chats' }); } }, }); diff --git a/packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx b/packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx index 0840c5615..39ce0223d 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx @@ -1,17 +1,17 @@ -import { Outlet, useMatches } from '@tanstack/react-router'; +import { Outlet, useMatch } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import Stack from 'pl-fe/components/ui/stack'; +import { chatsEmptyRoute } from 'pl-fe/features/ui/router'; +import { useChats } from 'pl-fe/queries/chats'; import ChatPageSidebar from './components/chat-page-sidebar'; -const SIDEBAR_HIDDEN_PATHS = ['/chats/settings', '/chats/new', '/chats/:chatId', '/chats/shoutbox']; - const ChatPage: React.FC = () => { - const isSidebarHidden = useMatches({ - select: (matches) => SIDEBAR_HIDDEN_PATHS.some((path) => matches.some(match => match.pathname === path)), - }); + const { chatsQuery: { data: chats } } = useChats(); + + const isSidebarHidden = !useMatch({ from: chatsEmptyRoute.id, shouldThrow: false }) || chats?.length === 0; const containerRef = useRef(null); const [height, setHeight] = useState('100%'); diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-chat.tsx b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-chat.tsx new file mode 100644 index 000000000..875a9d70d --- /dev/null +++ b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-chat.tsx @@ -0,0 +1,156 @@ +import { Link, useNavigate } from '@tanstack/react-router'; +import React, { useRef } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import DropdownMenu, { type Menu } from 'pl-fe/components/dropdown-menu'; +import Avatar from 'pl-fe/components/ui/avatar'; +import HStack from 'pl-fe/components/ui/hstack'; +import IconButton from 'pl-fe/components/ui/icon-button'; +import Stack from 'pl-fe/components/ui/stack'; +import Text from 'pl-fe/components/ui/text'; +import VerificationBadge from 'pl-fe/components/verification-badge'; +import { chatRoute } from 'pl-fe/features/ui/router'; +import { useFeatures } from 'pl-fe/hooks/use-features'; +import { useUnblockAccountMutation, useRelationshipQuery } from 'pl-fe/queries/accounts/use-relationship'; +import { useChat, useChatActions } from 'pl-fe/queries/chats'; +import { useModalsActions } from 'pl-fe/stores/modals'; + +import Chat from '../../chat'; + +const messages = defineMessages({ + blockMessage: { id: 'chat_settings.block.message', defaultMessage: 'Blocking will prevent this profile from direct messaging you and viewing your content. You can unblock later.' }, + blockHeading: { id: 'chat_settings.block.heading', defaultMessage: 'Block @{acct}' }, + blockConfirm: { id: 'chat_settings.block.confirm', defaultMessage: 'Block' }, + unblockMessage: { id: 'chat_settings.unblock.message', defaultMessage: 'Unblocking will allow this profile to direct message you and view your content.' }, + unblockHeading: { id: 'chat_settings.unblock.heading', defaultMessage: 'Unblock @{acct}' }, + unblockConfirm: { id: 'chat_settings.unblock.confirm', defaultMessage: 'Unblock' }, + leaveMessage: { id: 'chat_settings.leave.message', defaultMessage: 'Are you sure you want to leave this chat? Messages will be deleted for you and this chat will be removed from your inbox.' }, + leaveHeading: { id: 'chat_settings.leave.heading', defaultMessage: 'Leave chat' }, + leaveConfirm: { id: 'chat_settings.leave.confirm', defaultMessage: 'Leave chat' }, + blockUser: { id: 'chat_settings.options.block_user', defaultMessage: 'Block @{acct}' }, + unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' }, + leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave chat' }, +}); + +const ChatPageMain = () => { + const intl = useIntl(); + const features = useFeatures(); + const navigate = useNavigate(); + + const { chatId } = chatRoute.useParams(); + + const { openModal } = useModalsActions(); + const { data: chat } = useChat(chatId); + + const { mutate: unblockAccount } = useUnblockAccountMutation(chat?.account.id!); + + const inputRef = useRef(null); + + const { deleteChat } = useChatActions(chat?.id as string); + + const isBlocked = !!useRelationshipQuery(chat?.account.id).data?.blocked_by; + + const handleBlockUser = () => { + openModal('BLOCK_MUTE', { + accountId: chat!.account.id, + action: 'BLOCK', + }); + }; + + const handleUnblockUser = () => { + openModal('CONFIRM', { + heading: intl.formatMessage(messages.unblockHeading, { acct: chat?.account.acct }), + message: intl.formatMessage(messages.unblockMessage), + confirm: intl.formatMessage(messages.unblockConfirm), + onConfirm: () => unblockAccount(), + }); + }; + + const handleLeaveChat = () => { + openModal('CONFIRM', { + heading: intl.formatMessage(messages.leaveHeading), + message: intl.formatMessage(messages.leaveMessage), + confirm: intl.formatMessage(messages.leaveConfirm), + onConfirm: () => { + deleteChat.mutate(undefined, { + onSuccess() { + navigate({ to: '/chats' }); + }, + }); + }, + }); + }; + + if (!chat) { + return null; + } + + const menuItems: Menu = [ + { + icon: require('@phosphor-icons/core/regular/prohibit.svg'), + text: intl.formatMessage(isBlocked ? messages.unblockUser : messages.blockUser, { acct: chat.account.acct }), + action: isBlocked ? handleUnblockUser : handleBlockUser, + }, + ]; + + if (features.chatsDelete) menuItems.push({ + icon: require('@phosphor-icons/core/regular/sign-out.svg'), + text: intl.formatMessage(messages.leaveChat), + action: handleLeaveChat, + }); + + return ( + + + + + navigate({ to: '/chats/$chatId' })} + /> + + + + + + + +
+ + + {chat.account.display_name || `@${chat.account.username}`} + + + {chat.account.verified && } +
+
+
+ + ( + + + + {chat.account.display_name} + @{chat.account.acct} + + + )} + items={menuItems} + /> +
+ +
+ +
+
+ ); +}; + +export { ChatPageMain as default }; diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-main.tsx b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-main.tsx index babe9abbf..deebd725b 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-main.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-main.tsx @@ -1,174 +1,22 @@ -import { Link, useNavigate } from '@tanstack/react-router'; -import React, { useRef } from 'react'; -import { defineMessages, useIntl } from 'react-intl'; +import React from 'react'; -import DropdownMenu, { type Menu } from 'pl-fe/components/dropdown-menu'; -import Avatar from 'pl-fe/components/ui/avatar'; -import HStack from 'pl-fe/components/ui/hstack'; -import IconButton from 'pl-fe/components/ui/icon-button'; -import Stack from 'pl-fe/components/ui/stack'; -import Text from 'pl-fe/components/ui/text'; -import VerificationBadge from 'pl-fe/components/verification-badge'; -import { useChatContext } from 'pl-fe/contexts/chat-context'; -import { chatRoute } from 'pl-fe/features/ui/router'; -import { useFeatures } from 'pl-fe/hooks/use-features'; -import { useUnblockAccountMutation, useRelationshipQuery } from 'pl-fe/queries/accounts/use-relationship'; -import { useChat, useChatActions, useChats } from 'pl-fe/queries/chats'; -import { useModalsActions } from 'pl-fe/stores/modals'; - -import Chat from '../../chat'; +import { useChats } from 'pl-fe/queries/chats'; import BlankslateEmpty from './blankslate-empty'; import BlankslateWithChats from './blankslate-with-chats'; -const messages = defineMessages({ - blockMessage: { id: 'chat_settings.block.message', defaultMessage: 'Blocking will prevent this profile from direct messaging you and viewing your content. You can unblock later.' }, - blockHeading: { id: 'chat_settings.block.heading', defaultMessage: 'Block @{acct}' }, - blockConfirm: { id: 'chat_settings.block.confirm', defaultMessage: 'Block' }, - unblockMessage: { id: 'chat_settings.unblock.message', defaultMessage: 'Unblocking will allow this profile to direct message you and view your content.' }, - unblockHeading: { id: 'chat_settings.unblock.heading', defaultMessage: 'Unblock @{acct}' }, - unblockConfirm: { id: 'chat_settings.unblock.confirm', defaultMessage: 'Unblock' }, - leaveMessage: { id: 'chat_settings.leave.message', defaultMessage: 'Are you sure you want to leave this chat? Messages will be deleted for you and this chat will be removed from your inbox.' }, - leaveHeading: { id: 'chat_settings.leave.heading', defaultMessage: 'Leave chat' }, - leaveConfirm: { id: 'chat_settings.leave.confirm', defaultMessage: 'Leave chat' }, - blockUser: { id: 'chat_settings.options.block_user', defaultMessage: 'Block @{acct}' }, - unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' }, - leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave chat' }, -}); - const ChatPageMain = () => { - const intl = useIntl(); - const features = useFeatures(); - const navigate = useNavigate(); - - const { chatId } = chatRoute.useParams(); - - const { openModal } = useModalsActions(); - const { data: chat } = useChat(chatId); - const { currentChatId } = useChatContext(); const { chatsQuery: { data: chats, isLoading } } = useChats(); - const { mutate: unblockAccount } = useUnblockAccountMutation(chat?.account.id!); - - const inputRef = useRef(null); - - const { deleteChat } = useChatActions(chat?.id as string); - - const isBlocked = !!useRelationshipQuery(chat?.account.id).data?.blocked_by; - - const handleBlockUser = () => { - openModal('BLOCK_MUTE', { - accountId: chat!.account.id, - action: 'BLOCK', - }); - }; - - const handleUnblockUser = () => { - openModal('CONFIRM', { - heading: intl.formatMessage(messages.unblockHeading, { acct: chat?.account.acct }), - message: intl.formatMessage(messages.unblockMessage), - confirm: intl.formatMessage(messages.unblockConfirm), - onConfirm: () => unblockAccount(), - }); - }; - - const handleLeaveChat = () => { - openModal('CONFIRM', { - heading: intl.formatMessage(messages.leaveHeading), - message: intl.formatMessage(messages.leaveMessage), - confirm: intl.formatMessage(messages.leaveConfirm), - onConfirm: () => { - deleteChat.mutate(undefined, { - onSuccess() { - navigate({ to: '/chats/{-$chatId}' }); - }, - }); - }, - }); - }; - if (isLoading) { return null; } - if (!currentChatId && chats && chats.length > 0) { + if (chats && chats.length > 0) { return ; } - if (!currentChatId) { - return ; - } - - if (!chat) { - return null; - } - - const menuItems: Menu = [ - { - icon: require('@phosphor-icons/core/regular/prohibit.svg'), - text: intl.formatMessage(isBlocked ? messages.unblockUser : messages.blockUser, { acct: chat.account.acct }), - action: isBlocked ? handleUnblockUser : handleBlockUser, - }, - ]; - - if (features.chatsDelete) menuItems.push({ - icon: require('@phosphor-icons/core/regular/sign-out.svg'), - text: intl.formatMessage(messages.leaveChat), - action: handleLeaveChat, - }); - - return ( - - - - - navigate({ to: '/chats/{-$chatId}' })} - /> - - - - - - - -
- - - {chat.account.display_name || `@${chat.account.username}`} - - - {chat.account.verified && } -
-
-
- - ( - - - - {chat.account.display_name} - @{chat.account.acct} - - - )} - items={menuItems} - /> -
- -
- -
-
- ); + return ; }; export { ChatPageMain as default }; diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-new.tsx b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-new.tsx index 3681f1867..68e4a7988 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-new.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-new.tsx @@ -28,7 +28,7 @@ const ChatPageNew: React.FC = () => { navigate({ to: '/chats/{-$chatId}' })} + onClick={() => navigate({ to: '/chats' })} /> diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-settings.tsx b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-settings.tsx index 08c35f1de..c74e83b0e 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-settings.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-settings.tsx @@ -58,7 +58,7 @@ const ChatPageSettings = () => { navigate({ to: '/chats/{-$chatId}' })} + onClick={() => navigate({ to: '/chats' })} /> diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-shoutbox.tsx b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-shoutbox.tsx index 67d6fe7c6..417701f63 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-shoutbox.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-shoutbox.tsx @@ -25,7 +25,7 @@ const ChatPageShoutbox = () => { navigate({ to: '/chats/{-$chatId}' })} + onClick={() => navigate({ to: '/chats' })} /> diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-sidebar.tsx b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-sidebar.tsx index 6b397e9f7..918d6244f 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-sidebar.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-sidebar.tsx @@ -23,7 +23,7 @@ const ChatPageSidebar = () => { if (chat === 'shoutbox') { navigate({ to: '/chats/shoutbox' }); } else { - navigate({ to: '/chats/{-$chatId}', params: { chatId: chat.id } }); + navigate({ to: '/chats/$chatId', params: { chatId: chat.id } }); } }; diff --git a/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx b/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx index 8762527e2..a8a004db8 100644 --- a/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx @@ -53,7 +53,7 @@ const ChatSearch: React.FC = ({ isMainPage = false }) => { }, onSuccess: (response) => { if (isMainPage) { - navigate({ to: '/chats/{-$chatId}', params: { chatId: response.id } }); + navigate({ to: '/chats/$chatId', params: { chatId: response.id } }); } else { changeScreen(ChatWidgetScreens.CHAT, response.id); } diff --git a/packages/pl-fe/src/features/event/components/event-header.tsx b/packages/pl-fe/src/features/event/components/event-header.tsx index 368d3f67e..915a29bea 100644 --- a/packages/pl-fe/src/features/event/components/event-header.tsx +++ b/packages/pl-fe/src/features/event/components/event-header.tsx @@ -171,7 +171,7 @@ const EventHeader: React.FC = ({ status }) => { const handleChatClick = () => { getOrCreateChatByAccountId(account.id) - .then((chat) => navigate({ to: '/chats/{-$chatId}', params: { chatId: chat.id } })) + .then((chat) => navigate({ to: '/chats/$chatId', params: { chatId: chat.id } })) .catch(() => {}); }; diff --git a/packages/pl-fe/src/features/ui/router/index.tsx b/packages/pl-fe/src/features/ui/router/index.tsx index 72d278ae0..43deae3a7 100644 --- a/packages/pl-fe/src/features/ui/router/index.tsx +++ b/packages/pl-fe/src/features/ui/router/index.tsx @@ -39,6 +39,7 @@ import StatusLayout from 'pl-fe/layouts/status-layout'; import { instanceInitialState } from 'pl-fe/reducers/instance'; import { isStandalone } from 'pl-fe/utils/state'; +import ChatPageChat from '../../chats/components/chat-page/components/chat-page-chat'; import ChatPageMain from '../../chats/components/chat-page/components/chat-page-main'; import ChatPageNew from '../../chats/components/chat-page/components/chat-page-new'; import ChatPageSettings from '../../chats/components/chat-page/components/chat-page-settings'; @@ -583,7 +584,13 @@ export const shoutboxRoute = createRoute({ export const chatRoute = createRoute({ getParentRoute: () => chatsRoute, - path: '/{-$chatId}', + path: '/$chatId', + component: ChatPageChat, +}); + +export const chatsEmptyRoute = createRoute({ + getParentRoute: () => chatsRoute, + path: '/', component: ChatPageMain, }); @@ -1311,6 +1318,7 @@ const routeTree = rootRoute.addChildren([ chatsSettingsRoute, shoutboxRoute, chatRoute, + chatsEmptyRoute, ]), ]), layouts.default.addChildren([