From f28693c8c7743fc134aa2a6aaa04f82992ff355d Mon Sep 17 00:00:00 2001 From: sabaimran Date: Wed, 7 Aug 2024 21:04:44 +0530 Subject: [PATCH] create a useismobilewidth method for standardized mobile view detection. --- src/interface/web/app/agents/page.tsx | 25 +++---------------- src/interface/web/app/automations/page.tsx | 17 ++----------- src/interface/web/app/chat/page.tsx | 10 ++------ src/interface/web/app/common/utils.ts | 21 ++++++++++++++++ .../components/chatHistory/chatHistory.tsx | 11 ++------ .../web/app/components/navMenu/navMenu.tsx | 22 +++------------- .../components/suggestions/suggestionCard.tsx | 2 +- src/interface/web/app/factchecker/page.tsx | 19 +++----------- src/interface/web/app/page.tsx | 9 ++----- src/interface/web/app/search/page.tsx | 16 +++--------- src/interface/web/app/settings/page.tsx | 13 +++------- src/interface/web/app/share/chat/page.tsx | 10 ++------ 12 files changed, 48 insertions(+), 127 deletions(-) diff --git a/src/interface/web/app/agents/page.tsx b/src/interface/web/app/agents/page.tsx index b201504e..e0449c09 100644 --- a/src/interface/web/app/agents/page.tsx +++ b/src/interface/web/app/agents/page.tsx @@ -5,7 +5,7 @@ import styles from "./agents.module.css"; import Image from "next/image"; import useSWR from "swr"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { useAuthenticatedData, UserProfile } from "../common/auth"; import { Button } from "@/components/ui/button"; @@ -13,14 +13,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/comp import { PaperPlaneTilt, Lightning, Plus } from "@phosphor-icons/react"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, @@ -41,10 +34,10 @@ import { import LoginPrompt from "../components/loginPrompt/loginPrompt"; import { InlineLoading } from "../components/loading/loading"; import SidePanel from "../components/sidePanel/chatHistorySidePanel"; -import NavMenu from "../components/navMenu/navMenu"; import { getIconFromIconName } from "../common/iconUtils"; import { convertColorToTextClass } from "../common/colorUtils"; import { Alert, AlertDescription } from "@/components/ui/alert"; +import { useIsMobileWidth } from "../common/utils"; export interface AgentData { slug: string; @@ -265,18 +258,8 @@ export default function Agents() { revalidateOnFocus: false, }); const authenticatedData = useAuthenticatedData(); - const [isMobileWidth, setIsMobileWidth] = useState(false); const [showLoginPrompt, setShowLoginPrompt] = useState(false); - - useEffect(() => { - if (typeof window !== "undefined") { - setIsMobileWidth(window.innerWidth < 786); - } - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - }, []); + const isMobileWidth = useIsMobileWidth(); if (error) { return ( diff --git a/src/interface/web/app/automations/page.tsx b/src/interface/web/app/automations/page.tsx index 3f402769..4bd4624a 100644 --- a/src/interface/web/app/automations/page.tsx +++ b/src/interface/web/app/automations/page.tsx @@ -41,7 +41,7 @@ import { Input } from "@/components/ui/input"; import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"; import { DialogTitle } from "@radix-ui/react-dialog"; import { Textarea } from "@/components/ui/textarea"; -import { LocationData, useIPLocationData } from "../common/utils"; +import { LocationData, useIPLocationData, useIsMobileWidth } from "../common/utils"; import styles from "./automations.module.css"; import ShareLink from "../components/shareLink/shareLink"; @@ -53,13 +53,10 @@ import { CalendarDots, Clock, ClockAfternoon, - ClockCounterClockwise, DotsThreeVertical, Envelope, - Info, Lightning, MapPinSimple, - Pencil, Play, Plus, Trash, @@ -980,20 +977,10 @@ export default function Automations() { const [allNewAutomations, setAllNewAutomations] = useState([]); const [suggestedAutomations, setSuggestedAutomations] = useState([]); const [showLoginPrompt, setShowLoginPrompt] = useState(false); - const [isMobileWidth, setIsMobileWidth] = useState(false); + const isMobileWidth = useIsMobileWidth(); const ipLocationData = useIPLocationData(); - useEffect(() => { - if (window.innerWidth < 786) { - setIsMobileWidth(true); - } - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - }, []); - useEffect(() => { if (newAutomationData) { setAllNewAutomations([...allNewAutomations, newAutomationData]); diff --git a/src/interface/web/app/chat/page.tsx b/src/interface/web/app/chat/page.tsx index 9bfb1b18..55eb8cd5 100644 --- a/src/interface/web/app/chat/page.tsx +++ b/src/interface/web/app/chat/page.tsx @@ -13,7 +13,7 @@ import { processMessageChunk } from "../common/chatFunctions"; import "katex/dist/katex.min.css"; import { Context, OnlineContext, StreamMessage } from "../components/chatMessage/chatMessage"; -import { useIPLocationData, welcomeConsole } from "../common/utils"; +import { useIPLocationData, useIsMobileWidth, welcomeConsole } from "../common/utils"; import ChatInputArea, { ChatOptions } from "../components/chatInputArea/chatInputArea"; import { useAuthenticatedData } from "../common/auth"; import { AgentData } from "../agents/page"; @@ -116,9 +116,9 @@ export default function Chat() { const [queryToProcess, setQueryToProcess] = useState(""); const [processQuerySignal, setProcessQuerySignal] = useState(false); const [uploadedFiles, setUploadedFiles] = useState([]); - const [isMobileWidth, setIsMobileWidth] = useState(false); const locationData = useIPLocationData(); const authenticatedData = useAuthenticatedData(); + const isMobileWidth = useIsMobileWidth(); useEffect(() => { fetch("/api/chat/options") @@ -136,12 +136,6 @@ export default function Chat() { }); welcomeConsole(); - - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); }, []); useEffect(() => { diff --git a/src/interface/web/app/common/utils.ts b/src/interface/web/app/common/utils.ts index c6958c66..c3395dbb 100644 --- a/src/interface/web/app/common/utils.ts +++ b/src/interface/web/app/common/utils.ts @@ -1,3 +1,4 @@ +import { useEffect, useState } from "react"; import useSWR from "swr"; export interface LocationData { @@ -54,3 +55,23 @@ export function useIPLocationData() { return locationData; } + +export function useIsMobileWidth() { + const [isMobileWidth, setIsMobileWidth] = useState(false); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth <= 768) { + setIsMobileWidth(true); + } else { + setIsMobileWidth(false); + } + }; + + handleResize(); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + return isMobileWidth; +} diff --git a/src/interface/web/app/components/chatHistory/chatHistory.tsx b/src/interface/web/app/components/chatHistory/chatHistory.tsx index 5afe2293..453ab900 100644 --- a/src/interface/web/app/components/chatHistory/chatHistory.tsx +++ b/src/interface/web/app/components/chatHistory/chatHistory.tsx @@ -19,6 +19,7 @@ import ProfileCard from "../profileCard/profileCard"; import { getIconFromIconName } from "@/app/common/iconUtils"; import { AgentData } from "@/app/agents/page"; import React from "react"; +import { useIsMobileWidth } from "@/app/common/utils"; interface ChatResponse { status: string; @@ -75,15 +76,7 @@ export default function ChatHistory(props: ChatHistoryProps) { number | null >(null); const [fetchingData, setFetchingData] = useState(false); - const [isMobileWidth, setIsMobileWidth] = useState(false); - - useEffect(() => { - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - - setIsMobileWidth(window.innerWidth < 786); - }, []); + const isMobileWidth = useIsMobileWidth(); useEffect(() => { // This function ensures that scrolling to bottom happens after the data (chat messages) has been updated and rendered the first time. diff --git a/src/interface/web/app/components/navMenu/navMenu.tsx b/src/interface/web/app/components/navMenu/navMenu.tsx index 6ab9be82..2ff4eaf4 100644 --- a/src/interface/web/app/components/navMenu/navMenu.tsx +++ b/src/interface/web/app/components/navMenu/navMenu.tsx @@ -22,33 +22,17 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { - Moon, - Sun, - UserCircle, - User, - Robot, - MagnifyingGlass, - Question, - GearFine, - ArrowRight, - UsersFour, -} from "@phosphor-icons/react"; +import { Moon, Sun, UserCircle, Question, GearFine, ArrowRight } from "@phosphor-icons/react"; import { KhojAgentLogo, KhojAutomationLogo, KhojSearchLogo } from "../logo/khojLogo"; +import { useIsMobileWidth } from "@/app/common/utils"; export default function NavMenu() { const userData = useAuthenticatedData(); - const [isMobileWidth, setIsMobileWidth] = useState(false); const [darkMode, setDarkMode] = useState(false); const [initialLoadDone, setInitialLoadDone] = useState(false); + const isMobileWidth = useIsMobileWidth(); useEffect(() => { - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - if (localStorage.getItem("theme") === "dark") { document.documentElement.classList.add("dark"); setDarkMode(true); diff --git a/src/interface/web/app/components/suggestions/suggestionCard.tsx b/src/interface/web/app/components/suggestions/suggestionCard.tsx index 58ff55bd..2491b53d 100644 --- a/src/interface/web/app/components/suggestions/suggestionCard.tsx +++ b/src/interface/web/app/components/suggestions/suggestionCard.tsx @@ -14,7 +14,7 @@ interface SuggestionCardProps { export default function SuggestionCard(data: SuggestionCardProps) { const bgColors = converColorToBgGradient(data.color); - const cardClassName = `${styles.card} ${bgColors} md:w-full md:h-fit sm:w-full sm:h-fit lg:w-[200px] lg:h-[200px] cursor-pointer`; + const cardClassName = `${styles.card} ${bgColors} md:w-full md:h-fit sm:w-full h-fit md:w-[200px] md:h-[200px] cursor-pointer`; const titleClassName = `${styles.title} pt-2 dark:text-white dark:font-bold`; const descriptionClassName = `${styles.text} dark:text-white`; diff --git a/src/interface/web/app/factchecker/page.tsx b/src/interface/web/app/factchecker/page.tsx index 4484aedf..1bc7a54f 100644 --- a/src/interface/web/app/factchecker/page.tsx +++ b/src/interface/web/app/factchecker/page.tsx @@ -19,6 +19,7 @@ import { Button } from "@/components/ui/button"; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; import Link from "next/link"; import SidePanel from "../components/sidePanel/chatHistorySidePanel"; +import { useIsMobileWidth } from "../common/utils"; const chatURL = "/api/chat"; const verificationPrecursor = @@ -136,7 +137,7 @@ function ReferenceVerification(props: ReferenceVerificationProps) { const [initialResponse, setInitialResponse] = useState(""); const [isLoading, setIsLoading] = useState(true); const verificationStatement = `${props.message}. Use this link for reference: ${props.additionalLink}`; - const [isMobileWidth, setIsMobileWidth] = useState(false); + const isMobileWidth = useIsMobileWidth(); useEffect(() => { if (props.prefilledResponse) { @@ -151,12 +152,6 @@ function ReferenceVerification(props: ReferenceVerificationProps) { () => {}, ); } - - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); }, [verificationStatement, props.conversationId, props.prefilledResponse]); useEffect(() => { @@ -260,7 +255,7 @@ export default function FactChecker() { const [initialReferences, setInitialReferences] = useState(); const [childReferences, setChildReferences] = useState(); const [modelUsed, setModelUsed] = useState(); - const [isMobileWidth, setIsMobileWidth] = useState(false); + const isMobileWidth = useIsMobileWidth(); const [conversationID, setConversationID] = useState(""); const [runId, setRunId] = useState(""); @@ -282,14 +277,6 @@ export default function FactChecker() { setChildReferences(newReferences); } - useEffect(() => { - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - }, []); - let userData = useAuthenticatedData(); function storeData() { diff --git a/src/interface/web/app/page.tsx b/src/interface/web/app/page.tsx index ddfe06d5..29270be6 100644 --- a/src/interface/web/app/page.tsx +++ b/src/interface/web/app/page.tsx @@ -21,6 +21,7 @@ import { convertColorToBorderClass } from "@/app/common/colorUtils"; import { getIconFromIconName } from "@/app/common/iconUtils"; import { AgentData } from "@/app/agents/page"; import { createNewConversation } from "./common/chatFunctions"; +import { useIsMobileWidth } from "./common/utils"; interface ChatBodyDataProps { chatOptionsData: ChatOptions | null; @@ -325,7 +326,7 @@ export default function Home() { const [isLoading, setLoading] = useState(true); const [conversationId, setConversationID] = useState(null); const [uploadedFiles, setUploadedFiles] = useState([]); - const [isMobileWidth, setIsMobileWidth] = useState(false); + const isMobileWidth = useIsMobileWidth(); const { userConfig: initialUserConfig, isLoadingUserConfig } = useUserConfig(true); const [userConfig, setUserConfig] = useState(null); @@ -353,12 +354,6 @@ export default function Home() { console.error(err); return; }); - - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); }, []); if (isLoading) { diff --git a/src/interface/web/app/search/page.tsx b/src/interface/web/app/search/page.tsx index a49f0268..5d942819 100644 --- a/src/interface/web/app/search/page.tsx +++ b/src/interface/web/app/search/page.tsx @@ -30,6 +30,7 @@ import { import { Button } from "@/components/ui/button"; import Link from "next/link"; import { getIconFromFilename } from "../common/iconUtils"; +import { useIsMobileWidth } from "../common/utils"; interface AdditionalData { file: string; @@ -165,23 +166,16 @@ function focusNote(note: SearchResult) { } export default function Search() { - const authenticatedData = useAuthenticatedData(); const [searchQuery, setSearchQuery] = useState(""); - const [isMobileWidth, setIsMobileWidth] = useState(false); - const [title, setTitle] = useState("Search"); const [searchResults, setSearchResults] = useState(null); const [searchResultsLoading, setSearchResultsLoading] = useState(false); const [focusSearchResult, setFocusSearchResult] = useState(null); const [exampleQuery, setExampleQuery] = useState(""); const searchTimeoutRef = useRef(null); + const isMobileWidth = useIsMobileWidth(); + useEffect(() => { - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - setExampleQuery( naturalLanguageSearchQueryExamples[ Math.floor(Math.random() * naturalLanguageSearchQueryExamples.length) @@ -189,10 +183,6 @@ export default function Search() { ); }, []); - useEffect(() => { - setTitle(isMobileWidth ? "" : "Search"); - }, [isMobileWidth]); - function search() { if (searchResultsLoading || !searchQuery.trim()) return; diff --git a/src/interface/web/app/settings/page.tsx b/src/interface/web/app/settings/page.tsx index c6a219fd..2794abc4 100644 --- a/src/interface/web/app/settings/page.tsx +++ b/src/interface/web/app/settings/page.tsx @@ -7,7 +7,7 @@ import { Suspense, useEffect, useRef, useState } from "react"; import { useToast } from "@/components/ui/use-toast"; import { useUserConfig, ModelOptions, UserConfig } from "../common/auth"; -import { toTitleCase } from "../common/utils"; +import { toTitleCase, useIsMobileWidth } from "../common/utils"; import { isValidPhoneNumber } from "libphonenumber-js"; @@ -37,7 +37,6 @@ import { ChatCircleText, Key, Palette, - SpeakerHigh, UserCircle, FileMagnifyingGlass, Trash, @@ -500,7 +499,6 @@ enum PhoneNumberValidationState { export default function SettingsView() { const [title, setTitle] = useState("Settings"); - const [isMobileWidth, setIsMobileWidth] = useState(false); const { apiKeys, generateAPIKey, copyAPIKey, deleteAPIKey } = useApiKeys(); const { userConfig: initialUserConfig } = useUserConfig(true); const [userConfig, setUserConfig] = useState(null); @@ -513,6 +511,8 @@ export default function SettingsView() { ); const [isManageFilesModalOpen, setIsManageFilesModalOpen] = useState(false); const { toast } = useToast(); + const isMobileWidth = useIsMobileWidth(); + const cardClassName = "w-full lg:w-1/3 grid grid-flow-column border border-gray-300 shadow-md rounded-lg bg-gradient-to-b from-background to-gray-50 dark:to-gray-950"; @@ -530,13 +530,6 @@ export default function SettingsView() { setNotionToken(initialUserConfig?.notion_token ?? null); }, [initialUserConfig]); - useEffect(() => { - setIsMobileWidth(window.innerWidth < 786); - const handleResize = () => setIsMobileWidth(window.innerWidth < 786); - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); - const sendOTP = async () => { try { const response = await fetch(`/api/phone?phone_number=${phoneNumber}`, { diff --git a/src/interface/web/app/share/chat/page.tsx b/src/interface/web/app/share/chat/page.tsx index 4c19a8e7..b07a6df2 100644 --- a/src/interface/web/app/share/chat/page.tsx +++ b/src/interface/web/app/share/chat/page.tsx @@ -10,7 +10,7 @@ import Loading from "../../components/loading/loading"; import "katex/dist/katex.min.css"; -import { useIPLocationData, welcomeConsole } from "../../common/utils"; +import { useIPLocationData, useIsMobileWidth, welcomeConsole } from "../../common/utils"; import { useAuthenticatedData } from "@/app/common/auth"; import ChatInputArea, { ChatOptions } from "@/app/components/chatInputArea/chatInputArea"; @@ -100,11 +100,11 @@ export default function SharedChat() { const [queryToProcess, setQueryToProcess] = useState(""); const [processQuerySignal, setProcessQuerySignal] = useState(false); const [uploadedFiles, setUploadedFiles] = useState([]); - const [isMobileWidth, setIsMobileWidth] = useState(false); const [paramSlug, setParamSlug] = useState(undefined); const locationData = useIPLocationData(); const authenticatedData = useAuthenticatedData(); + const isMobileWidth = useIsMobileWidth(); useEffect(() => { fetch("/api/chat/options") @@ -123,12 +123,6 @@ export default function SharedChat() { welcomeConsole(); - setIsMobileWidth(window.innerWidth < 786); - - window.addEventListener("resize", () => { - setIsMobileWidth(window.innerWidth < 786); - }); - setParamSlug(window.location.pathname.split("/").pop() || ""); }, []);