From 6944281625cd36e7a2462643e75fc7efa12ea1e0 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Mon, 23 Dec 2024 11:42:22 -0300 Subject: [PATCH 01/13] feat: create the search bar component --- ui/src/components/features/SearchBar.tsx | 52 ++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 ui/src/components/features/SearchBar.tsx diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx new file mode 100644 index 00000000..daea8220 --- /dev/null +++ b/ui/src/components/features/SearchBar.tsx @@ -0,0 +1,52 @@ +import useChatContext from "@/useChatContext"; +import { Button } from "../ui/Button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTrigger, +} from "../ui/Dialog"; +import { useEffect, useState } from "react"; + +export function SearchBar() { + const [open, setOpen] = useState(false); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if ((event.ctrlKey || event.metaKey) && event.key === "k") { + event.preventDefault(); + setOpen(true); + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, []); + + return ( + + + + + + +
+ +
+
+ +

Recently viewed

+ <> +

Contact list soon here

+ +
+
+
+ ); +} From bd093f42cf0db2ca765471053f7f9fdba1ac7cd5 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Mon, 23 Dec 2024 11:43:06 -0300 Subject: [PATCH 02/13] chore: remove unused imports --- ui/src/components/features/SearchBar.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index daea8220..fd4321b7 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -1,4 +1,3 @@ -import useChatContext from "@/useChatContext"; import { Button } from "../ui/Button"; import { Dialog, From 19c7642187d91576effc50a865ab8abd36bf309d Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Mon, 23 Dec 2024 11:46:12 -0300 Subject: [PATCH 03/13] chore: add search bar in app sidebar --- ui/src/components/features/AppSidebar.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/src/components/features/AppSidebar.tsx b/ui/src/components/features/AppSidebar.tsx index d612cfd1..1d611f3b 100644 --- a/ui/src/components/features/AppSidebar.tsx +++ b/ui/src/components/features/AppSidebar.tsx @@ -13,6 +13,7 @@ import ContactListv2 from "./contacts/ContactList"; import { UserSettingsDialog } from "./user/UserSettings"; import ActiveUserSelect from "./user/ActiveUserSelect"; import useChatContext from "@/useChatContext"; +import { SearchBar } from "./SearchBar"; const items = [ { @@ -33,6 +34,7 @@ export function AppSidebar() { + From 6d38b2ead24d1ac00c70d7c044408fdac64b2e57 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Wed, 8 Jan 2025 15:01:31 -0300 Subject: [PATCH 04/13] feat: add matching algorithm --- ui/src/components/features/SearchBar.tsx | 25 ++++++++++++++++--- .../features/contacts/ContactCard.tsx | 24 ++++++++++++++++++ ui/src/components/ui/Dialog.tsx | 4 +-- 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 ui/src/components/features/contacts/ContactCard.tsx diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index fd4321b7..e83be757 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -7,9 +7,13 @@ import { DialogTrigger, } from "../ui/Dialog"; import { useEffect, useState } from "react"; +import { invoke } from "@tauri-apps/api/core"; +import ContactCard from "./contacts/ContactCard"; export function SearchBar() { const [open, setOpen] = useState(false); + const [filteredContacts, setFilteredContacts] = useState([]); + const [query, setQuery] = useState(""); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { @@ -23,6 +27,22 @@ export function SearchBar() { return () => window.removeEventListener("keydown", handleKeyDown); }, []); + async function handleFilterInput(event: React.ChangeEvent) { + setQuery(event.target.value); + + const matches = (await invoke("match_array", { + pattern: query, + paths: [ + "Sam Winchester", + "Dean Winchester", + "Miguel Oliveira", + "Caina Oliveira", + ], + })) as string[]; + + setFilteredContacts(matches); + } + return ( @@ -36,14 +56,13 @@ export function SearchBar() { autoFocus className="block w-full bg-transparent border-transparent rounded-lg p-2 text-sm text-gray-300 placeholder:text-gray-400 placeholder:text-lg transition-shadow focus:outline-none focus:ring-0" placeholder="Search" + onChange={handleFilterInput} />

Recently viewed

- <> -

Contact list soon here

- +
diff --git a/ui/src/components/features/contacts/ContactCard.tsx b/ui/src/components/features/contacts/ContactCard.tsx new file mode 100644 index 00000000..3b3cee55 --- /dev/null +++ b/ui/src/components/features/contacts/ContactCard.tsx @@ -0,0 +1,24 @@ +import { Avatar, AvatarFallback } from "@/components/ui/Avatar"; + +type ContactCardProps = { + contactsList: string[]; +}; + +function ContactCard({ contactsList }: ContactCardProps) { + return ( +
+ {[...contactsList].map((name) => ( +
+ + {name.at(0)?.toUpperCase()} + +

+ {name} +

+
+ ))} +
+ ); +} + +export default ContactCard; diff --git a/ui/src/components/ui/Dialog.tsx b/ui/src/components/ui/Dialog.tsx index 775c93a9..3ce20c3d 100644 --- a/ui/src/components/ui/Dialog.tsx +++ b/ui/src/components/ui/Dialog.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import * as DialogPrimitive from "@radix-ui/react-dialog"; -import { X } from "lucide-react"; +// import { X } from "lucide-react"; import { cn } from "@/lib/utils"; @@ -43,7 +43,7 @@ const DialogContent = React.forwardRef< > {children} - + {/* */} Close From ca277eb3236ccda56a16a046758f30abacfd3c86 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Wed, 8 Jan 2025 15:02:58 -0300 Subject: [PATCH 05/13] chore: style search bar component --- ui/src/components/features/SearchBar.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index e83be757..487f69f5 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -32,12 +32,7 @@ export function SearchBar() { const matches = (await invoke("match_array", { pattern: query, - paths: [ - "Sam Winchester", - "Dean Winchester", - "Miguel Oliveira", - "Caina Oliveira", - ], + paths: ["Miguel Oliveira"], })) as string[]; setFilteredContacts(matches); From dcec2e3e430653ac44bfc76dba22d8af420d7a9f Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Wed, 8 Jan 2025 15:04:10 -0300 Subject: [PATCH 06/13] chore: add nucleo --- Cargo.lock | 67 ++++++++++++++++++++++++++++++++++++++++ ui/src-tauri/Cargo.toml | 3 +- ui/src-tauri/src/main.rs | 27 +++++++++++++++- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b35190dd..57c53e28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -589,6 +589,25 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -813,6 +832,12 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "embed-resource" version = "2.5.1" @@ -2004,6 +2029,7 @@ name = "muchat-ui" version = "0.0.1" dependencies = [ "log", + "nucleo", "serde", "serde_json", "tauri", @@ -2077,6 +2103,27 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nucleo" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5262af4c94921c2646c5ac6ff7900c2af9cbb08dc26a797e18130a7019c039d4" +dependencies = [ + "nucleo-matcher", + "parking_lot", + "rayon", +] + +[[package]] +name = "nucleo-matcher" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf33f538733d1a5a3494b836ba913207f14d9d4a1d3cd67030c5061bdd2cac85" +dependencies = [ + "memchr", + "unicode-segmentation", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2840,6 +2887,26 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.8" diff --git a/ui/src-tauri/Cargo.toml b/ui/src-tauri/Cargo.toml index 519913a8..2b1562cb 100644 --- a/ui/src-tauri/Cargo.toml +++ b/ui/src-tauri/Cargo.toml @@ -15,9 +15,10 @@ tauri-build = { version = "2.0.3", features = [] } [dependencies] log = "0.4.22" +nucleo = "0.5.0" serde = { workspace = true } serde_json = { workspace = true } -tauri = "2.1.1" +tauri = { version = "2.1.1", features = [] } tauri-plugin-fs = "2.2.0" tauri-plugin-log = "2.2.0" tauri-plugin-shell = "2.2.0" diff --git a/ui/src-tauri/src/main.rs b/ui/src-tauri/src/main.rs index cf8a74aa..33782eba 100644 --- a/ui/src-tauri/src/main.rs +++ b/ui/src-tauri/src/main.rs @@ -1,10 +1,35 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use nucleo::{ + pattern::{CaseMatching, Normalization, Pattern}, + Config, Matcher, +}; + +#[tauri::command] +fn match_array(pattern: String, paths: Vec) -> Vec { + if paths.is_empty() { + return vec![]; + } + + let mut matcher = Matcher::new(Config::DEFAULT); + let matches = Pattern::parse(&pattern, CaseMatching::Ignore, Normalization::Smart) + .match_list(paths, &mut matcher); + + matches + .into_iter() + .map(|(matched_text, _score)| matched_text) + .collect() +} + #[tokio::main] async fn main() { // let (client, stream_future) = ChatClient::new("ws://localhost:5225".to_string()).await.unwrap(); // let stream = stream_future.await; // tauri::async_runtime::set(tokio::runtime::Handle::current()); - app_lib::run(); + tauri::Builder::default() + // This is where you pass in your commands + .invoke_handler(tauri::generate_handler![match_array]) + .run(tauri::generate_context!()) + .expect("failed to run app"); } From 5f66e44d6d9a3e2608ffc7ea26f46a718332ba46 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Wed, 8 Jan 2025 23:40:27 -0300 Subject: [PATCH 07/13] feat: add plugins --- ui/src-tauri/src/main.rs | 3 ++- ui/src/components/features/SearchBar.tsx | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ui/src-tauri/src/main.rs b/ui/src-tauri/src/main.rs index 33782eba..d3099a55 100644 --- a/ui/src-tauri/src/main.rs +++ b/ui/src-tauri/src/main.rs @@ -28,7 +28,8 @@ async fn main() { // let stream = stream_future.await; // tauri::async_runtime::set(tokio::runtime::Handle::current()); tauri::Builder::default() - // This is where you pass in your commands + .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_websocket::init()) .invoke_handler(tauri::generate_handler![match_array]) .run(tauri::generate_context!()) .expect("failed to run app"); diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index 487f69f5..7ffd8521 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -6,13 +6,25 @@ import { DialogHeader, DialogTrigger, } from "../ui/Dialog"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { invoke } from "@tauri-apps/api/core"; import ContactCard from "./contacts/ContactCard"; +import useChatContext from "@/useChatContext"; export function SearchBar() { + const { contacts } = useChatContext(); + const contactsName = useMemo( + () => + Array.from(contacts.values()).map( + ({ localDisplayName }) => localDisplayName, + ), + [contacts], + ); + const [open, setOpen] = useState(false); - const [filteredContacts, setFilteredContacts] = useState([]); + const [filteredContacts, setFilteredContacts] = useState( + contactsName.slice(0, 5), + ); const [query, setQuery] = useState(""); useEffect(() => { @@ -32,7 +44,7 @@ export function SearchBar() { const matches = (await invoke("match_array", { pattern: query, - paths: ["Miguel Oliveira"], + paths: contactsName, })) as string[]; setFilteredContacts(matches); From 5ea61afb795d8fdfe93545e798571df0ecc6a1c8 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Thu, 9 Jan 2025 13:43:43 -0300 Subject: [PATCH 08/13] chore: useMemo hook to inital state --- ui/src/components/features/SearchBar.tsx | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index 7ffd8521..d2e2c8af 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -13,7 +13,7 @@ import useChatContext from "@/useChatContext"; export function SearchBar() { const { contacts } = useChatContext(); - const contactsName = useMemo( + const contactNames = useMemo( () => Array.from(contacts.values()).map( ({ localDisplayName }) => localDisplayName, @@ -22,10 +22,12 @@ export function SearchBar() { ); const [open, setOpen] = useState(false); - const [filteredContacts, setFilteredContacts] = useState( - contactsName.slice(0, 5), - ); const [query, setQuery] = useState(""); + const [matches, setMatches] = useState([]); + const filteredContacts = useMemo( + () => (query ? matches : contactNames.slice(0, 5)), + [query, matches, contactNames], + ); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { @@ -40,14 +42,14 @@ export function SearchBar() { }, []); async function handleFilterInput(event: React.ChangeEvent) { - setQuery(event.target.value); + const newQuery = event.target.value; + setQuery(newQuery); - const matches = (await invoke("match_array", { - pattern: query, - paths: contactsName, + const newMatches = (await invoke("match_array", { + pattern: newQuery, + paths: contactNames, })) as string[]; - - setFilteredContacts(matches); + setMatches(newMatches); } return ( From 81e5e7d64761e6f3d0f0e3cc1cd1d1af1c519f04 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Thu, 9 Jan 2025 14:19:35 -0300 Subject: [PATCH 09/13] feat: add hideCloseIcon prop to Dialog component --- ui/src/components/ui/Dialog.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ui/src/components/ui/Dialog.tsx b/ui/src/components/ui/Dialog.tsx index 3ce20c3d..02680218 100644 --- a/ui/src/components/ui/Dialog.tsx +++ b/ui/src/components/ui/Dialog.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import * as DialogPrimitive from "@radix-ui/react-dialog"; -// import { X } from "lucide-react"; +import { X } from "lucide-react"; import { cn } from "@/lib/utils"; @@ -27,10 +27,15 @@ const DialogOverlay = React.forwardRef< )); DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; +interface DialogContentProps + extends React.ComponentPropsWithoutRef { + hideCloseIcon?: boolean; +} + const DialogContent = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( + DialogContentProps +>(({ className, hideCloseIcon = false, children, ...props }, ref) => ( {children} - {/* */} + {!hideCloseIcon && } Close From 57b2738d0b81636f341eab4186068f575033609a Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Thu, 9 Jan 2025 15:00:32 -0300 Subject: [PATCH 10/13] chore: rename ContactCard to ContactSuggestions and fix logic in handleFilterInput --- ui/src/components/features/SearchBar.tsx | 31 ++++++++++++------- .../features/contacts/ContactCard.tsx | 24 -------------- .../features/contacts/ContactSuggestions.tsx | 31 +++++++++++++++++++ 3 files changed, 50 insertions(+), 36 deletions(-) delete mode 100644 ui/src/components/features/contacts/ContactCard.tsx create mode 100644 ui/src/components/features/contacts/ContactSuggestions.tsx diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index d2e2c8af..885f7351 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -8,25 +8,23 @@ import { } from "../ui/Dialog"; import { useEffect, useMemo, useState } from "react"; import { invoke } from "@tauri-apps/api/core"; -import ContactCard from "./contacts/ContactCard"; +import ContactSuggestions from "./contacts/ContactSuggestions"; import useChatContext from "@/useChatContext"; +import { Contact } from "@/lib/response"; export function SearchBar() { const { contacts } = useChatContext(); - const contactNames = useMemo( - () => - Array.from(contacts.values()).map( - ({ localDisplayName }) => localDisplayName, - ), + const currentContacts = useMemo( + () => Array.from(contacts.values()), [contacts], ); const [open, setOpen] = useState(false); const [query, setQuery] = useState(""); - const [matches, setMatches] = useState([]); + const [matches, setMatches] = useState([]); const filteredContacts = useMemo( - () => (query ? matches : contactNames.slice(0, 5)), - [query, matches, contactNames], + () => (query ? matches : currentContacts.slice(0, 5)), + [query, matches, currentContacts], ); useEffect(() => { @@ -47,9 +45,18 @@ export function SearchBar() { const newMatches = (await invoke("match_array", { pattern: newQuery, - paths: contactNames, + paths: currentContacts.map((contact) => contact.localDisplayName), })) as string[]; - setMatches(newMatches); + + const matchesMapped = newMatches + .map((match) => { + return currentContacts.find( + (contact) => contact.localDisplayName === match, + ); + }) + .filter((contact): contact is Contact => contact !== undefined); + + setMatches(matchesMapped); } return ( @@ -71,7 +78,7 @@ export function SearchBar() {

Recently viewed

- +
diff --git a/ui/src/components/features/contacts/ContactCard.tsx b/ui/src/components/features/contacts/ContactCard.tsx deleted file mode 100644 index 3b3cee55..00000000 --- a/ui/src/components/features/contacts/ContactCard.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Avatar, AvatarFallback } from "@/components/ui/Avatar"; - -type ContactCardProps = { - contactsList: string[]; -}; - -function ContactCard({ contactsList }: ContactCardProps) { - return ( -
- {[...contactsList].map((name) => ( -
- - {name.at(0)?.toUpperCase()} - -

- {name} -

-
- ))} -
- ); -} - -export default ContactCard; diff --git a/ui/src/components/features/contacts/ContactSuggestions.tsx b/ui/src/components/features/contacts/ContactSuggestions.tsx new file mode 100644 index 00000000..5d580a74 --- /dev/null +++ b/ui/src/components/features/contacts/ContactSuggestions.tsx @@ -0,0 +1,31 @@ +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/Avatar"; +import { Contact } from "@/lib/response"; + +type ContactSuggestionsProps = { + contactsList: Contact[]; +}; + +function ContactSuggestions({ contactsList }: ContactSuggestionsProps) { + return ( +
+ {contactsList.map(({ contactId, localDisplayName, profile }) => ( + + ))} +
+ ); +} + +export default ContactSuggestions; From aa146a3baed91a29e3120956b4893c43ad9ae660 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Thu, 9 Jan 2025 15:02:53 -0300 Subject: [PATCH 11/13] chore: rename matching method name --- ui/src-tauri/src/main.rs | 4 ++-- ui/src/components/features/SearchBar.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/src-tauri/src/main.rs b/ui/src-tauri/src/main.rs index d3099a55..239f041a 100644 --- a/ui/src-tauri/src/main.rs +++ b/ui/src-tauri/src/main.rs @@ -7,7 +7,7 @@ use nucleo::{ }; #[tauri::command] -fn match_array(pattern: String, paths: Vec) -> Vec { +fn match_string(pattern: String, paths: Vec) -> Vec { if paths.is_empty() { return vec![]; } @@ -30,7 +30,7 @@ async fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_websocket::init()) - .invoke_handler(tauri::generate_handler![match_array]) + .invoke_handler(tauri::generate_handler![match_string]) .run(tauri::generate_context!()) .expect("failed to run app"); } diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index 885f7351..66b311ad 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -43,7 +43,7 @@ export function SearchBar() { const newQuery = event.target.value; setQuery(newQuery); - const newMatches = (await invoke("match_array", { + const newMatches = (await invoke("match_string", { pattern: newQuery, paths: currentContacts.map((contact) => contact.localDisplayName), })) as string[]; From e38f117f76c7bb302fce9a80802e90a907cbf647 Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Thu, 9 Jan 2025 15:30:47 -0300 Subject: [PATCH 12/13] feat: add navigation to chat when clicking on a contact --- ui/src/components/features/SearchBar.tsx | 5 +- .../features/contacts/ContactSuggestions.tsx | 55 +++++++++++++------ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index 66b311ad..74d59e2d 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -78,7 +78,10 @@ export function SearchBar() {

Recently viewed

- +
diff --git a/ui/src/components/features/contacts/ContactSuggestions.tsx b/ui/src/components/features/contacts/ContactSuggestions.tsx index 5d580a74..54d9af50 100644 --- a/ui/src/components/features/contacts/ContactSuggestions.tsx +++ b/ui/src/components/features/contacts/ContactSuggestions.tsx @@ -1,29 +1,50 @@ +import React from "react"; + +import { getChatKey } from "@/ChatContext"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/Avatar"; import { Contact } from "@/lib/response"; +import useChatContext from "@/useChatContext"; type ContactSuggestionsProps = { contactsList: Contact[]; + setOpen: React.Dispatch>; }; -function ContactSuggestions({ contactsList }: ContactSuggestionsProps) { +function ContactSuggestions({ + contactsList, + setOpen, +}: ContactSuggestionsProps) { + const { setSelectedChatId } = useChatContext(); + + function handleContactSelection(contact: Contact) { + const chatKey = getChatKey({ contact }); + setSelectedChatId(chatKey); + setOpen(false); + } + return (
- {contactsList.map(({ contactId, localDisplayName, profile }) => ( - - ))} + {contactsList.map((contact) => { + const { contactId, localDisplayName, profile } = contact; + + return ( + + ); + })}
); } From fc29c70596e28ab4f2bcd2da52092476f2344d8c Mon Sep 17 00:00:00 2001 From: Miguel Tavares Date: Thu, 9 Jan 2025 15:33:27 -0300 Subject: [PATCH 13/13] chore: add hideCloseIcon prop to SearchBar --- ui/src/components/features/SearchBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/features/SearchBar.tsx b/ui/src/components/features/SearchBar.tsx index 74d59e2d..581220a3 100644 --- a/ui/src/components/features/SearchBar.tsx +++ b/ui/src/components/features/SearchBar.tsx @@ -64,7 +64,7 @@ export function SearchBar() { - +