Replace zustand state management with URL-based routing (#640)
* feat: added router * feat: added params to messages page * fixing tests, added translation labels * Update src/i18n/locales/en/ui.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/components/PageComponents/Map/NodeDetail.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/pages/Messages.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * updated dev tools * fixing tests --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+45
-27
@@ -9,7 +9,13 @@ import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
import { Protobuf, Types } from "@meshtastic/core";
|
||||
import { getChannelName } from "@pages/Channels.tsx";
|
||||
import { HashIcon, LockIcon, LockOpenIcon } from "lucide-react";
|
||||
import { useCallback, useDeferredValue, useMemo, useState } from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useDeferredValue,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import { MessageInput } from "@components/PageComponents/Messages/MessageInput.tsx";
|
||||
import { cn } from "@core/utils/cn.ts";
|
||||
import {
|
||||
@@ -21,6 +27,7 @@ import { useSidebar } from "@core/stores/sidebarStore.tsx";
|
||||
import { Input } from "@components/UI/Input.tsx";
|
||||
import { randId } from "@core/utils/randId.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||
|
||||
type NodeInfoWithUnread = Protobuf.Mesh.NodeInfo & { unreadCount: number };
|
||||
|
||||
@@ -37,18 +44,45 @@ export const MessagesPage = () => {
|
||||
const {
|
||||
getMyNodeNum,
|
||||
getMessages,
|
||||
setActiveChat,
|
||||
chatType,
|
||||
activeChat,
|
||||
setChatType,
|
||||
setMessageState,
|
||||
} = useMessageStore();
|
||||
const params = useParams({ from: "", shouldThrow: false });
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
const { isCollapsed } = useSidebar();
|
||||
const [searchTerm, setSearchTerm] = useState<string>("");
|
||||
const { t } = useTranslation(["messages", "channels", "ui"]);
|
||||
const deferredSearch = useDeferredValue(searchTerm);
|
||||
|
||||
const chatType = params.type === "direct"
|
||||
? MessageType.Direct
|
||||
: params.type === "broadcast"
|
||||
? MessageType.Broadcast
|
||||
: undefined;
|
||||
const activeChat = params.chatId ? Number(params.chatId) : undefined;
|
||||
|
||||
const allChannels = Array.from(channels.values());
|
||||
const filteredChannels = allChannels.filter(
|
||||
(ch) => ch.role !== Protobuf.Channel.Channel_Role.DISABLED,
|
||||
);
|
||||
const currentChannel = channels.get(activeChat);
|
||||
const otherNode = getNode(activeChat);
|
||||
|
||||
const isDirect = chatType === MessageType.Direct;
|
||||
const isBroadcast = chatType === MessageType.Broadcast;
|
||||
|
||||
const navigateToChat = useCallback((type: MessageType, chatId: number) => {
|
||||
const typeParam = type === MessageType.Direct ? "direct" : "broadcast";
|
||||
navigate({ to: `/messages/${typeParam}/${chatId}` });
|
||||
}, [navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!params.type && !params.chatId && filteredChannels.length > 0) {
|
||||
const defaultChannel = filteredChannels[0];
|
||||
navigateToChat(MessageType.Broadcast, defaultChannel.index);
|
||||
}
|
||||
}, [params.type, params.chatId, filteredChannels, navigateToChat]);
|
||||
|
||||
const filteredNodes = (): NodeInfoWithUnread[] => {
|
||||
const lowerCaseSearchTerm = deferredSearch.toLowerCase();
|
||||
|
||||
@@ -69,16 +103,6 @@ export const MessagesPage = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const allChannels = Array.from(channels.values());
|
||||
const filteredChannels = allChannels.filter(
|
||||
(ch) => ch.role !== Protobuf.Channel.Channel_Role.DISABLED,
|
||||
);
|
||||
const currentChannel = channels.get(activeChat);
|
||||
const otherNode = getNode(activeChat);
|
||||
|
||||
const isDirect = chatType === MessageType.Direct;
|
||||
const isBroadcast = chatType === MessageType.Broadcast;
|
||||
|
||||
const sendText = useCallback(async (message: string) => {
|
||||
const isDirect = chatType === MessageType.Direct;
|
||||
const toValue = isDirect ? activeChat : MessageType.Broadcast;
|
||||
@@ -116,10 +140,8 @@ export const MessagesPage = () => {
|
||||
} else {
|
||||
console.warn("sendText completed but messageId is undefined");
|
||||
}
|
||||
// deno-lint-ignore no-explicit-any
|
||||
} catch (e: any) {
|
||||
console.error("Failed to send message:", e);
|
||||
// Note: messageId might be undefined here if the error occurred before it was assigned
|
||||
const failedId = messageId ?? randId();
|
||||
if (chatType === MessageType.Broadcast) {
|
||||
setMessageState({
|
||||
@@ -165,7 +187,7 @@ export const MessagesPage = () => {
|
||||
default:
|
||||
return (
|
||||
<div className="flex-1 flex items-center justify-center text-slate-500 p-4">
|
||||
{t("messagesPage.selectChatPrompt")}
|
||||
{t("selectChatPrompt.text", { ns: "messages" })}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -191,8 +213,7 @@ export const MessagesPage = () => {
|
||||
active={activeChat === channel.index &&
|
||||
chatType === MessageType.Broadcast}
|
||||
onClick={() => {
|
||||
setChatType(MessageType.Broadcast);
|
||||
setActiveChat(channel.index);
|
||||
navigateToChat(MessageType.Broadcast, channel.index);
|
||||
resetUnread(channel.index);
|
||||
}}
|
||||
>
|
||||
@@ -210,8 +231,7 @@ export const MessagesPage = () => {
|
||||
activeChat,
|
||||
chatType,
|
||||
isCollapsed,
|
||||
setActiveChat,
|
||||
setChatType,
|
||||
navigateToChat,
|
||||
resetUnread,
|
||||
]);
|
||||
|
||||
@@ -245,8 +265,7 @@ export const MessagesPage = () => {
|
||||
active={activeChat === node.num &&
|
||||
chatType === MessageType.Direct}
|
||||
onClick={() => {
|
||||
setChatType(MessageType.Direct);
|
||||
setActiveChat(node.num);
|
||||
navigateToChat(MessageType.Direct, node.num);
|
||||
resetUnread(node.num);
|
||||
}}
|
||||
>
|
||||
@@ -268,8 +287,7 @@ export const MessagesPage = () => {
|
||||
searchTerm,
|
||||
activeChat,
|
||||
chatType,
|
||||
setActiveChat,
|
||||
setChatType,
|
||||
navigateToChat,
|
||||
resetUnread,
|
||||
hasNodeError,
|
||||
],
|
||||
@@ -319,7 +337,7 @@ export const MessagesPage = () => {
|
||||
)
|
||||
: (
|
||||
<div className="p-4 text-center text-slate-400 italic">
|
||||
{t("messagesPage.sendMessagePrompt")}
|
||||
{t("sendMessage.sendButton", { ns: "messages" })}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user