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 01/14] 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([ From cb310cda4306da32407f519f81df87d54562e265 Mon Sep 17 00:00:00 2001 From: matty Date: Wed, 14 Jan 2026 17:11:50 +0000 Subject: [PATCH 02/14] pl-fe: fix emoji autosuggest submission on enter --- .../compose/editor/plugins/autosuggest-plugin.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pl-fe/src/features/compose/editor/plugins/autosuggest-plugin.tsx b/packages/pl-fe/src/features/compose/editor/plugins/autosuggest-plugin.tsx index 07a1b6ded..f290cdd89 100644 --- a/packages/pl-fe/src/features/compose/editor/plugins/autosuggest-plugin.tsx +++ b/packages/pl-fe/src/features/compose/editor/plugins/autosuggest-plugin.tsx @@ -11,7 +11,7 @@ import { $getSelection, $isRangeSelection, $isTextNode, - COMMAND_PRIORITY_LOW, + COMMAND_PRIORITY_NORMAL, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ENTER_COMMAND, @@ -485,7 +485,7 @@ const AutosuggestPlugin = ({ } return true; }, - COMMAND_PRIORITY_LOW, + COMMAND_PRIORITY_NORMAL, ), editor.registerCommand( KEY_ARROW_DOWN_COMMAND, @@ -499,7 +499,7 @@ const AutosuggestPlugin = ({ } return true; }, - COMMAND_PRIORITY_LOW, + COMMAND_PRIORITY_NORMAL, ), editor.registerCommand( KEY_TAB_COMMAND, @@ -511,7 +511,7 @@ const AutosuggestPlugin = ({ setResolution(null); return true; }, - COMMAND_PRIORITY_LOW, + COMMAND_PRIORITY_NORMAL, ), editor.registerCommand( KEY_ENTER_COMMAND, @@ -523,7 +523,7 @@ const AutosuggestPlugin = ({ setResolution(null); return true; }, - COMMAND_PRIORITY_LOW, + COMMAND_PRIORITY_NORMAL, ), editor.registerCommand( KEY_ESCAPE_COMMAND, @@ -534,7 +534,7 @@ const AutosuggestPlugin = ({ setResolution(null); return true; }, - COMMAND_PRIORITY_LOW, + COMMAND_PRIORITY_NORMAL, ), ); }, [editor, suggestions, selectedSuggestion, resolution]); From 49ba76c01f49a0d16535e6649b5aa555130659c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 15:22:37 +0100 Subject: [PATCH 03/14] pl-fe: fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../chats/components/chat-page/components/chat-page-chat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 875a9d70d..a9f2e36b2 100644 --- 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 @@ -107,7 +107,7 @@ const ChatPageMain = () => { navigate({ to: '/chats/$chatId' })} + onClick={() => navigate({ to: '/chats' })} /> From bb8e713d291c414cd0f20fc489424e73ff97412e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 15:44:28 +0100 Subject: [PATCH 04/14] pl-fe: rename pages so they make more sense MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../chats-page.tsx} | 8 ++++---- .../components/blankslate-empty.tsx | 0 .../components/blankslate-with-chats.tsx | 0 .../components/chats-page-chat.tsx} | 4 ++-- .../components/chats-page-empty.tsx} | 4 ++-- .../components/chats-page-new.tsx} | 7 ++----- .../components/chats-page-settings.tsx} | 4 ++-- .../components/chats-page-shoutbox.tsx} | 4 ++-- .../components/chats-page-sidebar.tsx} | 4 ++-- .../pl-fe/src/features/ui/router/index.tsx | 20 +++++++++---------- packages/pl-fe/src/pages/chats/chats.tsx | 2 +- 11 files changed, 27 insertions(+), 30 deletions(-) rename packages/pl-fe/src/features/chats/components/{chat-page/chat-page.tsx => chats-page/chats-page.tsx} (93%) rename packages/pl-fe/src/features/chats/components/{chat-page => chats-page}/components/blankslate-empty.tsx (100%) rename packages/pl-fe/src/features/chats/components/{chat-page => chats-page}/components/blankslate-with-chats.tsx (100%) rename packages/pl-fe/src/features/chats/components/{chat-page/components/chat-page-chat.tsx => chats-page/components/chats-page-chat.tsx} (98%) rename packages/pl-fe/src/features/chats/components/{chat-page/components/chat-page-main.tsx => chats-page/components/chats-page-empty.tsx} (85%) rename packages/pl-fe/src/features/chats/components/{chat-page/components/chat-page-new.tsx => chats-page/components/chats-page-new.tsx} (90%) rename packages/pl-fe/src/features/chats/components/{chat-page/components/chat-page-settings.tsx => chats-page/components/chats-page-settings.tsx} (98%) rename packages/pl-fe/src/features/chats/components/{chat-page/components/chat-page-shoutbox.tsx => chats-page/components/chats-page-shoutbox.tsx} (96%) rename packages/pl-fe/src/features/chats/components/{chat-page/components/chat-page-sidebar.tsx => chats-page/components/chats-page-sidebar.tsx} (96%) diff --git a/packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx b/packages/pl-fe/src/features/chats/components/chats-page/chats-page.tsx similarity index 93% rename from packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/chats-page.tsx index 39ce0223d..a352d78fe 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/chat-page.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/chats-page.tsx @@ -6,9 +6,9 @@ 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'; +import ChatsPageSidebar from './components/chats-page-sidebar'; -const ChatPage: React.FC = () => { +const ChatsPage: React.FC = () => { const { chatsQuery: { data: chats } } = useChats(); const isSidebarHidden = !useMatch({ from: chatsEmptyRoute.id, shouldThrow: false }) || chats?.length === 0; @@ -57,7 +57,7 @@ const ChatPage: React.FC = () => { 'hidden sm:block': isSidebarHidden, })} > - + { ); }; -export { ChatPage as default }; +export { ChatsPage as default }; diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/blankslate-empty.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/blankslate-empty.tsx similarity index 100% rename from packages/pl-fe/src/features/chats/components/chat-page/components/blankslate-empty.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/blankslate-empty.tsx diff --git a/packages/pl-fe/src/features/chats/components/chat-page/components/blankslate-with-chats.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/blankslate-with-chats.tsx similarity index 100% rename from packages/pl-fe/src/features/chats/components/chat-page/components/blankslate-with-chats.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/blankslate-with-chats.tsx 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/chats-page/components/chats-page-chat.tsx similarity index 98% rename from packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-chat.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-chat.tsx index a9f2e36b2..cb0d5983f 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-chat.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-chat.tsx @@ -32,7 +32,7 @@ const messages = defineMessages({ leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave chat' }, }); -const ChatPageMain = () => { +const ChatsPageChat = () => { const intl = useIntl(); const features = useFeatures(); const navigate = useNavigate(); @@ -153,4 +153,4 @@ const ChatPageMain = () => { ); }; -export { ChatPageMain as default }; +export { ChatsPageChat 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/chats-page/components/chats-page-empty.tsx similarity index 85% rename from packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-main.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-empty.tsx index deebd725b..d0188cf4a 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-main.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-empty.tsx @@ -5,7 +5,7 @@ import { useChats } from 'pl-fe/queries/chats'; import BlankslateEmpty from './blankslate-empty'; import BlankslateWithChats from './blankslate-with-chats'; -const ChatPageMain = () => { +const ChatsPageEmpty = () => { const { chatsQuery: { data: chats, isLoading } } = useChats(); if (isLoading) { @@ -19,4 +19,4 @@ const ChatPageMain = () => { return ; }; -export { ChatPageMain as default }; +export { ChatsPageEmpty 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/chats-page/components/chats-page-new.tsx similarity index 90% rename from packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-new.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-new.tsx index 68e4a7988..049fadd06 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-new.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-new.tsx @@ -13,11 +13,8 @@ const messages = defineMessages({ title: { id: 'chat.new_message.title', defaultMessage: 'New Message' }, }); -interface IChatPageNew { -} - /** New message form to create a chat. */ -const ChatPageNew: React.FC = () => { +const ChatsPageNew: React.FC = () => { const intl = useIntl(); const navigate = useNavigate(); @@ -40,4 +37,4 @@ const ChatPageNew: React.FC = () => { ); }; -export { ChatPageNew as default }; +export { ChatsPageNew as default }; 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/chats-page/components/chats-page-settings.tsx similarity index 98% rename from packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-settings.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-settings.tsx index c74e83b0e..b09dbb50a 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-settings.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-settings.tsx @@ -30,7 +30,7 @@ const messages = defineMessages({ submit: { id: 'chat.page_settings.submit', defaultMessage: 'Save' }, }); -const ChatPageSettings = () => { +const ChatsPageSettings = () => { const { account } = useOwnAccount(); const intl = useIntl(); const navigate = useNavigate(); @@ -98,4 +98,4 @@ const ChatPageSettings = () => { ); }; -export { ChatPageSettings as default }; +export { ChatsPageSettings as default }; 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/chats-page/components/chats-page-shoutbox.tsx similarity index 96% rename from packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-shoutbox.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx index 417701f63..6c4c659ef 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-shoutbox.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx @@ -12,7 +12,7 @@ import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config'; import Shoutbox from '../../shoutbox'; -const ChatPageShoutbox = () => { +const ChatsPageShoutbox = () => { const navigate = useNavigate(); const instance = useInstance(); const { logo } = usePlFeConfig(); @@ -48,4 +48,4 @@ const ChatPageShoutbox = () => { ); }; -export { ChatPageShoutbox as default }; +export { ChatsPageShoutbox as default }; 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/chats-page/components/chats-page-sidebar.tsx similarity index 96% rename from packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-sidebar.tsx rename to packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx index 918d6244f..651496224 100644 --- a/packages/pl-fe/src/features/chats/components/chat-page/components/chat-page-sidebar.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx @@ -15,7 +15,7 @@ const messages = defineMessages({ title: { id: 'column.chats', defaultMessage: 'Chats' }, }); -const ChatPageSidebar = () => { +const ChatsPageSidebar = () => { const intl = useIntl(); const navigate = useNavigate(); @@ -64,4 +64,4 @@ const ChatPageSidebar = () => { ); }; -export { ChatPageSidebar as default }; +export { ChatsPageSidebar as default }; diff --git a/packages/pl-fe/src/features/ui/router/index.tsx b/packages/pl-fe/src/features/ui/router/index.tsx index 43deae3a7..12087a923 100644 --- a/packages/pl-fe/src/features/ui/router/index.tsx +++ b/packages/pl-fe/src/features/ui/router/index.tsx @@ -39,11 +39,11 @@ 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'; -import ChatPageShoutbox from '../../chats/components/chat-page/components/chat-page-shoutbox'; +import ChatsPageChat from '../../chats/components/chats-page/components/chats-page-chat'; +import ChatsPageEmpty from '../../chats/components/chats-page/components/chats-page-empty'; +import ChatsPageNew from '../../chats/components/chats-page/components/chats-page-new'; +import ChatsPageSettings from '../../chats/components/chats-page/components/chats-page-settings'; +import ChatsPageShoutbox from '../../chats/components/chats-page/components/chats-page-shoutbox'; import ColumnLoading from '../components/column-loading'; import { AboutPage, @@ -567,31 +567,31 @@ export const chatsRoute = createRoute({ export const chatsNewRoute = createRoute({ getParentRoute: () => chatsRoute, path: '/new', - component: ChatPageNew, + component: ChatsPageNew, }); export const chatsSettingsRoute = createRoute({ getParentRoute: () => chatsRoute, path: '/settings', - component: ChatPageSettings, + component: ChatsPageSettings, }); export const shoutboxRoute = createRoute({ getParentRoute: () => chatsRoute, path: '/shoutbox', - component: ChatPageShoutbox, + component: ChatsPageShoutbox, }); export const chatRoute = createRoute({ getParentRoute: () => chatsRoute, path: '/$chatId', - component: ChatPageChat, + component: ChatsPageChat, }); export const chatsEmptyRoute = createRoute({ getParentRoute: () => chatsRoute, path: '/', - component: ChatPageMain, + component: ChatsPageEmpty, }); // Follow requests and blocks diff --git a/packages/pl-fe/src/pages/chats/chats.tsx b/packages/pl-fe/src/pages/chats/chats.tsx index f4fc07594..2ed12584a 100644 --- a/packages/pl-fe/src/pages/chats/chats.tsx +++ b/packages/pl-fe/src/pages/chats/chats.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { ChatProvider } from 'pl-fe/contexts/chat-context'; -import ChatPage from 'pl-fe/features/chats/components/chat-page/chat-page'; +import ChatPage from 'pl-fe/features/chats/components/chats-page/chats-page'; const ChatIndex: React.FC = () => ( From ddf88e406e4d5fbf0a2a36fef6af2a8c522a1c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 17:43:30 +0100 Subject: [PATCH 05/14] pl-fe: migrations from tailwind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../chats/components/chat-pane/blankslate.tsx | 39 ++---- .../chats/components/chat-pane/chat-pane.tsx | 5 +- .../chat-widget/chat-pane-header.tsx | 34 ++---- .../headers/chat-search-header.tsx | 5 +- .../src/features/chats/components/ui/pane.tsx | 5 +- packages/pl-fe/src/features/ui/index.tsx | 4 +- packages/pl-fe/src/pages/chats/chats.tsx | 4 +- packages/pl-fe/src/styles/new/chats.scss | 115 ++++++++++++++++++ packages/pl-fe/src/styles/new/index.scss | 1 + 9 files changed, 151 insertions(+), 61 deletions(-) create mode 100644 packages/pl-fe/src/styles/new/chats.scss diff --git a/packages/pl-fe/src/features/chats/components/chat-pane/blankslate.tsx b/packages/pl-fe/src/features/chats/components/chat-pane/blankslate.tsx index 6e46ad099..0e7281994 100644 --- a/packages/pl-fe/src/features/chats/components/chat-pane/blankslate.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-pane/blankslate.tsx @@ -1,10 +1,6 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import Button from 'pl-fe/components/ui/button'; -import Stack from 'pl-fe/components/ui/stack'; -import Text from 'pl-fe/components/ui/text'; - const messages = defineMessages({ title: { id: 'chat_pane.blankslate.title', defaultMessage: 'No messages yet' }, body: { id: 'chat_pane.blankslate.body', defaultMessage: 'Search for someone to chat with.' }, @@ -19,30 +15,21 @@ const Blankslate = ({ onSearch }: IBlankslate) => { const intl = useIntl(); return ( - - - - - {intl.formatMessage(messages.title)} - +
+
+

+ {intl.formatMessage(messages.title)} +

- - {intl.formatMessage(messages.body)} - - +

+ {intl.formatMessage(messages.body)} +

+
-
- -
- - + +
); }; diff --git a/packages/pl-fe/src/features/chats/components/chat-pane/chat-pane.tsx b/packages/pl-fe/src/features/chats/components/chat-pane/chat-pane.tsx index b64692c09..12c9dfab5 100644 --- a/packages/pl-fe/src/features/chats/components/chat-pane/chat-pane.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-pane/chat-pane.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; -import Stack from 'pl-fe/components/ui/stack'; import { ChatWidgetScreens, useChatContext } from 'pl-fe/contexts/chat-context'; import { useStatContext } from 'pl-fe/contexts/stat-context'; import { useChats } from 'pl-fe/queries/chats'; @@ -37,9 +36,9 @@ const ChatPane = () => { const renderBody = () => { if (Number(chats?.length) > 0 || showShoutbox || isLoading) { return ( - +
- +
); } else if (chats?.length === 0) { return ( diff --git a/packages/pl-fe/src/features/chats/components/chat-widget/chat-pane-header.tsx b/packages/pl-fe/src/features/chats/components/chat-widget/chat-pane-header.tsx index 74374327c..5a37dd7f8 100644 --- a/packages/pl-fe/src/features/chats/components/chat-widget/chat-pane-header.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-widget/chat-pane-header.tsx @@ -1,9 +1,6 @@ -import clsx from 'clsx'; import React, { HTMLAttributes } from 'react'; -import HStack from 'pl-fe/components/ui/hstack'; import IconButton from 'pl-fe/components/ui/icon-button'; -import Text from 'pl-fe/components/ui/text'; import { useSettings } from 'pl-fe/stores/settings'; interface IChatPaneHeader { @@ -37,45 +34,40 @@ const ChatPaneHeader = (props: IChatPaneHeader) => { } return ( - +
- - {title} - +
{title}
- {(!demetricator && typeof unreadCount !== 'undefined' && unreadCount > 0) && ( - - + {(!demetricator && unreadCount !== undefined && unreadCount > 0) && ( +
+

({unreadCount}) - +

-
- +
+
)} - +
{secondaryAction ? ( ) : null} - - +
+
); }; diff --git a/packages/pl-fe/src/features/chats/components/chat-widget/headers/chat-search-header.tsx b/packages/pl-fe/src/features/chats/components/chat-widget/headers/chat-search-header.tsx index 28203a7c7..7951f1e67 100644 --- a/packages/pl-fe/src/features/chats/components/chat-widget/headers/chat-search-header.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-widget/headers/chat-search-header.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import HStack from 'pl-fe/components/ui/hstack'; import Icon from 'pl-fe/components/ui/icon'; import Text from 'pl-fe/components/ui/text'; import { ChatWidgetScreens, useChatContext } from 'pl-fe/contexts/chat-context'; @@ -21,7 +20,7 @@ const ChatSearchHeader = () => { +
} isOpen={isOpen} isToggleable={false} diff --git a/packages/pl-fe/src/features/chats/components/ui/pane.tsx b/packages/pl-fe/src/features/chats/components/ui/pane.tsx index 74f9ce4fb..e358a9192 100644 --- a/packages/pl-fe/src/features/chats/components/ui/pane.tsx +++ b/packages/pl-fe/src/features/chats/components/ui/pane.tsx @@ -11,10 +11,7 @@ interface IPane { /** Chat pane UI component for desktop. */ const Pane: React.FC = ({ isOpen = false, children }) => (
{children} diff --git a/packages/pl-fe/src/features/ui/index.tsx b/packages/pl-fe/src/features/ui/index.tsx index 8c8ca036b..bd2907f7b 100644 --- a/packages/pl-fe/src/features/ui/index.tsx +++ b/packages/pl-fe/src/features/ui/index.tsx @@ -176,8 +176,8 @@ const UI: React.FC = React.memo(() => { {me && features.chats && ( -
- }> +
+ }>
diff --git a/packages/pl-fe/src/pages/chats/chats.tsx b/packages/pl-fe/src/pages/chats/chats.tsx index 2ed12584a..8f3064635 100644 --- a/packages/pl-fe/src/pages/chats/chats.tsx +++ b/packages/pl-fe/src/pages/chats/chats.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { ChatProvider } from 'pl-fe/contexts/chat-context'; -import ChatPage from 'pl-fe/features/chats/components/chats-page/chats-page'; +import ChatsPage from 'pl-fe/features/chats/components/chats-page/chats-page'; const ChatIndex: React.FC = () => ( - + ); diff --git a/packages/pl-fe/src/styles/new/chats.scss b/packages/pl-fe/src/styles/new/chats.scss new file mode 100644 index 000000000..52c61ddb4 --- /dev/null +++ b/packages/pl-fe/src/styles/new/chats.scss @@ -0,0 +1,115 @@ +@use 'mixins'; +@use 'variables'; + +.⁂-chat-widget { + @apply fixed bottom-0 z-[99] flex w-96 flex-col rounded-t-lg bg-white shadow-3xl black:border black:border-b-0 black:border-gray-800 black:bg-black dark:bg-gray-900 ltr:right-5 rtl:left-5 h-16; + + &--open { + height: 550px; + max-height: 100vh; + + .⁂-chat-widget__header__open-button svg { + transform: rotate(180deg); + } + } + + &--placeholder { + @apply fixed bottom-0 z-[99] flex h-16 w-96 animate-pulse flex-col rounded-t-lg bg-white shadow-3xl dark:bg-gray-900 ltr:right-5 rtl:left-5; + } + + &__container { + display: none; + + @media (min-width: variables.$breakpoint-xl) { + display: block; + } + } + + &__header { + display: flex; + align-items: center; + justify-content: space-between; + height: 4rem; + border-top-left-radius: 0.75rem; + border-top-right-radius: 0.75rem; + padding: 0.75rem 1rem; + gap: 0.5rem; + overflow: hidden; + + &__title { + display: flex; + height: 4rem; + flex-grow: 1; + flex-direction: row; + align-items: center; + gap: 0.25rem; + } + + &__title div:first-child, + &__count p { + @include mixins.text($weight: semibold); + overflow: hidden; + text-overflow: ellipsis; + } + + &__count { + display: flex; + align-items: center; + gap: 0.5rem; + + &__dot { + height: 0.625rem; + width: 0.625rem; + border-radius: 50%; + background: rgb(var(--color-accent-300)); + } + } + + &__actions { + display: flex; + align-items: center; + gap: 0.5rem; + + svg { + height: 1.25rem; + width: 1.25rem; + color: rgb(var(--color-gray-600)); + } + } + + &__open-button svg { + transform: rotate(0deg); + transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1); + } + } + + &__blankslate { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + flex-grow: 1; + gap: 1rem; + + &__text { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.25rem; + max-width: 80%; + + &__title { + @include mixins.text($size: lg, $weight: bold, $align: center); + } + + &__body { + @include mixins.text($theme: muted, $align: center); + } + } + + button { + @include mixins.button($theme: primary); + } + } +} \ No newline at end of file diff --git a/packages/pl-fe/src/styles/new/index.scss b/packages/pl-fe/src/styles/new/index.scss index 606ce6187..f99242e32 100644 --- a/packages/pl-fe/src/styles/new/index.scss +++ b/packages/pl-fe/src/styles/new/index.scss @@ -6,4 +6,5 @@ @use 'timelines'; @use 'compose'; @use 'drive'; +@use 'chats'; @use 'events'; From c5c3962bb9aeae46d98a48e617a4de2b4927fda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 28 Jan 2026 10:33:26 +0100 Subject: [PATCH 06/14] pl-fe: migrations from tailwind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-fe/src/styles/new/chats.scss | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/pl-fe/src/styles/new/chats.scss b/packages/pl-fe/src/styles/new/chats.scss index 52c61ddb4..edb43b4b3 100644 --- a/packages/pl-fe/src/styles/new/chats.scss +++ b/packages/pl-fe/src/styles/new/chats.scss @@ -83,6 +83,20 @@ } } + &__search-header { + display: flex; + align-items: center; + gap: 0.5rem; + } + + &__list { + display: flex; + flex-direction: column; + gap: 1rem; + height: 100%; + flex-grow: 1; + } + &__blankslate { display: flex; flex-direction: column; From e4f56e1623df3c2b27f5b5545f625e75516d6345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 29 Jan 2026 14:51:17 +0100 Subject: [PATCH 07/14] pl-fe: use useDeferredValue for search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../compose/components/language-dropdown.tsx | 12 +++++++----- .../src/modals/select-bookmark-folder-modal.tsx | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/pl-fe/src/features/compose/components/language-dropdown.tsx b/packages/pl-fe/src/features/compose/components/language-dropdown.tsx index d81121c06..6cbf3efbe 100644 --- a/packages/pl-fe/src/features/compose/components/language-dropdown.tsx +++ b/packages/pl-fe/src/features/compose/components/language-dropdown.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx'; import fuzzysort from 'fuzzysort'; -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { useDeferredValue, useEffect, useMemo, useRef, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { addComposeLanguage, changeComposeLanguage, changeComposeModifiedLanguage, deleteComposeLanguage } from 'pl-fe/actions/compose'; @@ -96,8 +96,8 @@ const getLanguageDropdown = (composeId: string): React.FC => setSearchValue(''); }; - const search = () => { - if (searchValue === '') { + const search = (value: string) => { + if (value === '') { return [...languages].sort((a, b) => { // Push current selection to the top of the list @@ -124,7 +124,7 @@ const getLanguageDropdown = (composeId: string): React.FC => }); } - return fuzzysort.go(searchValue, languages, { + return fuzzysort.go(value, languages, { keys: ['0', '1'], limit: 5, threshold: -10000, @@ -143,7 +143,9 @@ const getLanguageDropdown = (composeId: string): React.FC => }, [node.current]); const isSearching = searchValue !== ''; - const results = useMemo(search, [searchValue]); + + const deferredSearchValue = useDeferredValue(searchValue); + const results = useMemo(() => search(deferredSearchValue), [deferredSearchValue]); return ( <> diff --git a/packages/pl-fe/src/modals/select-bookmark-folder-modal.tsx b/packages/pl-fe/src/modals/select-bookmark-folder-modal.tsx index dd44ce4b2..55f2e9822 100644 --- a/packages/pl-fe/src/modals/select-bookmark-folder-modal.tsx +++ b/packages/pl-fe/src/modals/select-bookmark-folder-modal.tsx @@ -1,6 +1,6 @@ import fuzzysort from 'fuzzysort'; import { BookmarkFolder } from 'pl-api'; -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useDeferredValue, useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { ListItem } from 'pl-fe/components/list'; @@ -38,6 +38,7 @@ const SelectBookmarkFolderModal: React.FC = e => { setSearchTerm(e.target.value); @@ -73,10 +74,10 @@ const SelectBookmarkFolderModal: React.FC { if (!bookmarkFolders) return []; - const filtered = search(bookmarkFolders, searchTerm); + const filtered = search(bookmarkFolders, deferredSearchTerm); return filtered; - }, [bookmarkFolders, searchTerm]); + }, [bookmarkFolders, deferredSearchTerm]); let items; From 63a278bf6e1eac518cd2b96c00c43f952fdafd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 30 Jan 2026 07:18:03 +0100 Subject: [PATCH 08/14] pl-fe: fix event management page layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-fe/src/features/ui/router/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pl-fe/src/features/ui/router/index.tsx b/packages/pl-fe/src/features/ui/router/index.tsx index 12087a923..e96aa5c18 100644 --- a/packages/pl-fe/src/features/ui/router/index.tsx +++ b/packages/pl-fe/src/features/ui/router/index.tsx @@ -743,8 +743,8 @@ export const eventInformationRoute = createRoute({ }); export const eventEditRoute = createRoute({ - getParentRoute: () => layouts.event, - path: '/edit', + getParentRoute: () => layouts.events, + path: '/@{$username}/events/$statusId/edit', component: EditEvent, beforeLoad: requireAuthMiddleware(({ context: { features } }) => { if (!features.events) throw notFound(); From c58d60a8e73184258bf21d1e049c2170bcaf1016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 30 Jan 2026 07:23:05 +0100 Subject: [PATCH 09/14] pl-fe: feedback on event participation accept/reject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../tabs/manage-pending-participants.tsx | 23 +++++++++++++++++-- packages/pl-fe/src/locales/en.json | 4 ++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx b/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx index 1f246e4ac..d008d4bd8 100644 --- a/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx +++ b/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx @@ -8,10 +8,15 @@ import Spinner from 'pl-fe/components/ui/spinner'; import Stack from 'pl-fe/components/ui/stack'; import AccountContainer from 'pl-fe/containers/account-container'; import { useAcceptEventParticipationRequestMutation, useEventParticipationRequests, useRejectEventParticipationRequestMutation } from 'pl-fe/queries/events/use-event-participation-requests'; +import toast from 'pl-fe/toast'; const messages = defineMessages({ authorize: { id: 'compose_event.participation_requests.authorize', defaultMessage: 'Authorize' }, + authorizeSuccess: { id: 'compose_event.participation_requests.authorize.success', defaultMessage: 'Event participation request authorized successfully' }, + authorizeFail: { id: 'compose_event.participation_requests.authorize.fail', defaultMessage: 'Failed to authorize event participation request' }, reject: { id: 'compose_event.participation_requests.reject', defaultMessage: 'Reject' }, + rejectSuccess: { id: 'compose_event.participation_requests.reject.success', defaultMessage: 'Event participation request rejected successfully' }, + rejectFail: { id: 'compose_event.participation_requests.reject.fail', defaultMessage: 'Failed to reject event participation request' }, }); interface IAccount { @@ -36,13 +41,27 @@ const Account: React.FC = ({ eventId, id, participationMessage }) => { theme='secondary' size='sm' text={intl.formatMessage(messages.authorize)} - onClick={() => acceptEventParticipationRequest()} + onClick={() => acceptEventParticipationRequest(undefined, { + onSuccess: () => { + toast.success(messages.authorizeSuccess); + }, + onError: () => { + toast.error(messages.authorizeFail); + }, + })} />