Skip to content

Commit 8b9614a

Browse files
committed
Update search
1 parent 78b6d15 commit 8b9614a

File tree

6 files changed

+58
-78
lines changed

6 files changed

+58
-78
lines changed

packages/app/src/discovery/engine.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::HashMap;
33
use axum::async_trait;
44
use enstate_shared::core::lookup_data::LookupInfo;
55
use enstate_shared::core::{ENSService, Profile};
6-
use enstate_shared::discovery::Discovery;
6+
use enstate_shared::discovery::{Discovery, SearchResult};
77
use ethers::providers::namehash;
88
use futures::future::join_all;
99
use serde::{Deserialize, Serialize};
@@ -106,7 +106,7 @@ impl Discovery for DiscoveryEngine {
106106
}
107107
}
108108

109-
async fn query_search(&self, service: &ENSService, query: String) -> Result<Vec<Profile>, ()> {
109+
async fn query_search(&self, service: &ENSService, query: String) -> Result<Vec<SearchResult>, ()> {
110110
let index = self.client.index("profiles");
111111

112112
// Create search with query and limit to 12 results
@@ -124,20 +124,14 @@ impl Discovery for DiscoveryEngine {
124124
if search_results.hits.is_empty() {
125125
return Ok(vec![]);
126126
}
127-
127+
128128
// Extract the name for each result to use with resolve_name
129-
let names: Vec<String> = search_results.hits
129+
let names: Vec<SearchResult> = search_results.hits
130130
.into_iter()
131-
.map(|hit| hit.result.name)
131+
.map(|hit| SearchResult { name: hit.result.name })
132132
.collect();
133-
134-
let profiles = names.into_iter().map(|name| async move {
135-
service.resolve_profile(LookupInfo::Name(name), false).await.unwrap()
136-
}).collect::<Vec<_>>();
137-
138-
let profiles = join_all(profiles).await;
139133

140-
Ok(profiles)
134+
Ok(names)
141135
},
142136
Err(e) => {
143137
tracing::error!("Error searching profiles: {}", e);

packages/app/src/routes/v2/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use enstate_shared::core::lookup_data::LookupInfo;
1414
use enstate_shared::core::Profile;
1515
use ethers_core::types::Address;
1616
use futures::future::join_all;
17-
use serde::Deserialize;
17+
use serde::{Deserialize, Serialize};
1818
use tokio_stream::wrappers::UnboundedReceiverStream;
1919
use tracing::info;
2020

@@ -36,6 +36,11 @@ pub struct SearchQuery {
3636
s: String,
3737
}
3838

39+
#[derive(Serialize, Deserialize)]
40+
pub struct ProfileSearchResult {
41+
pub name: String,
42+
}
43+
3944
/// /a/{address}
4045
///
4146
/// Here is an example of a valid request that looks up an address:
@@ -59,13 +64,13 @@ pub struct SearchQuery {
5964
pub async fn discovery_search(
6065
Query(query): Query<SearchQuery>,
6166
State(state): State<Arc<crate::AppState>>,
62-
) -> Result<Json<Vec<Profile>>, RouteError> {
67+
) -> Result<Json<Vec<ProfileSearchResult>>, RouteError> {
6368

6469
info!("query: {:?}", query.s);
6570

6671
if let Some(discovery) = &state.service.discovery {
6772
let profiles = discovery.query_search(&state.service, query.s).await.unwrap();
68-
return Ok(Json(profiles));
73+
return Ok(Json(profiles.into_iter().map(|x| ProfileSearchResult { name: x.name }).collect()));
6974
}
7075
// get_bulk(
7176
// Qs(AddressGetBulkQuery {

packages/search/src/components/SearchResult.tsx

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { LuMapPin, LuMail, LuGlobe, LuTwitter, LuGithub, LuMessageSquare, LuSend
33
import { ChainIcon } from './ChainIcon';
44
import { getChainIconUrl } from '../utils/chainIcons';
55
import { useFollowers } from '../hooks/useFollowers';
6+
import { ProfileSearchResult } from '@/hooks/useSearch';
7+
import { useProfile } from '@/hooks/useProfile';
68

79
interface Profile {
810
name: string;
@@ -26,11 +28,12 @@ interface Profile {
2628
}
2729

2830
interface SearchResultProps {
29-
profile: Profile;
31+
profile: ProfileSearchResult;
3032
}
3133

3234
export function SearchResult({ profile }: SearchResultProps) {
3335
const { data: followersData } = useFollowers(profile.name);
36+
const { data: profileData } = useProfile(profile.name);
3437

3538
return (
3639
<div className="bg-white rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-all duration-200">
@@ -41,11 +44,11 @@ export function SearchResult({ profile }: SearchResultProps) {
4144
>
4245
<div className="relative h-full flex flex-col">
4346
{/* Header/Banner image */}
44-
{profile.header || profile.records?.header ? (
47+
{profileData?.header || profileData?.records?.header ? (
4548
<div className="w-full aspect-[3/1] overflow-hidden">
4649
<img
47-
src={profile.header || profile.records?.header}
48-
alt={`${profile.display} banner`}
50+
src={profileData.header || profileData.records?.header}
51+
alt={`${profileData.display} banner`}
4952
className="w-full h-full object-cover"
5053
/>
5154
</div>
@@ -57,38 +60,38 @@ export function SearchResult({ profile }: SearchResultProps) {
5760
<div className="p-2 flex-1">
5861
<div className="flex items-start space-x-2 pr-2 pb-1 h-full">
5962
{/* Avatar */}
60-
<div className={`${profile.header || profile.records?.header ? '-mt-7' : ''} flex-shrink-0`}>
61-
{profile.avatar ? (
63+
<div className={`${profileData?.header || profileData?.records?.header ? '-mt-7' : ''} flex-shrink-0`}>
64+
{profileData?.avatar ? (
6265
<img
63-
src={profile.avatar}
64-
alt={profile.display}
66+
src={profileData.avatar}
67+
alt={profileData.display}
6568
className="h-14 w-14 rounded-full border-2 border-white shadow-md object-cover"
6669
/>
6770
) : (
6871
<div className="h-14 w-14 rounded-full bg-gray-200 flex items-center justify-center text-gray-500 text-xl font-bold">
69-
{profile.display.charAt(0).toUpperCase()}
72+
{profileData?.display?.charAt(0).toUpperCase()}
7073
</div>
7174
)}
7275
</div>
7376

7477
{/* Profile details */}
7578
<div className="flex-1 min-w-0 h-full flex flex-col">
7679
<h3 className="text-base font-semibold text-blue-600 truncate">
77-
{profile.display}
80+
{profileData?.display}
7881
</h3>
79-
{profile.address && (
82+
{profileData?.address && (
8083
<p className="text-xs text-gray-500 truncate">
81-
{profile.address}
84+
{profileData.address}
8285
</p>
8386
)}
8487
<p className="mt-1 text-xs text-gray-600 whitespace-pre-line line-clamp-2">
85-
{profile.records?.description || ''}
88+
{profileData?.records?.description || ''}
8689
</p>
8790

8891
{/* Chain addresses */}
89-
{profile.chains && Object.keys(profile.chains).length > 0 && (
92+
{profileData?.chains && Object.keys(profileData.chains).length > 0 && (
9093
<div className="mt-1.5 flex flex-wrap gap-x-2 gap-y-1">
91-
{Object.entries(profile.chains).map(([chain, address]) => (
94+
{Object.entries(profileData.chains).map(([chain, address]) => (
9295
<div key={chain} className="flex items-center text-xs text-gray-500" title={`${chain.toUpperCase()}: ${address}`}>
9396
<ChainIcon
9497
chain={chain}
@@ -103,47 +106,47 @@ export function SearchResult({ profile }: SearchResultProps) {
103106

104107
{/* Profile metadata */}
105108
<div className="mt-1.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-gray-500">
106-
{profile.records?.location && (
109+
{profileData?.records?.location && (
107110
<div className="flex items-center">
108111
<LuMapPin className="mr-1 h-4 w-4" />
109-
<span>{profile.records.location}</span>
112+
<span>{profileData.records.location}</span>
110113
</div>
111114
)}
112-
{profile.records?.email && (
115+
{profileData?.records?.email && (
113116
<div className="flex items-center">
114117
<LuMail className="mr-1 h-4 w-4" />
115-
<span>{profile.records.email}</span>
118+
<span>{profileData.records.email}</span>
116119
</div>
117120
)}
118-
{profile.records?.url && (
121+
{profileData?.records?.url && (
119122
<div className="flex items-center">
120123
<LuGlobe className="mr-1 h-4 w-4" />
121-
<span>{profile.records.url}</span>
124+
<span>{profileData.records.url}</span>
122125
</div>
123126
)}
124127
</div>
125128

126129
{/* Social links and followers */}
127130
<div className="mt-1.5 flex justify-between items-center flex-1">
128131
<div className="flex space-x-2">
129-
{profile.records?.['com.twitter'] && (
132+
{profileData?.records?.['com.twitter'] && (
130133
<div className="text-blue-400 hover:text-blue-600">
131-
<LuTwitter className="h-4 w-4" title={`Twitter: ${profile.records['com.twitter']}`} />
134+
<LuTwitter className="h-4 w-4" title={`Twitter: ${profileData.records['com.twitter']}`} />
132135
</div>
133136
)}
134-
{profile.records?.['com.github'] && (
137+
{profileData?.records?.['com.github'] && (
135138
<div className="text-gray-700 hover:text-gray-900">
136-
<LuGithub className="h-4 w-4" title={`GitHub: ${profile.records['com.github']}`} />
139+
<LuGithub className="h-4 w-4" title={`GitHub: ${profileData.records['com.github']}`} />
137140
</div>
138141
)}
139-
{profile.records?.['com.discord'] && (
142+
{profileData?.records?.['com.discord'] && (
140143
<div className="text-indigo-500 hover:text-indigo-700">
141-
<LuMessageSquare className="h-4 w-4" title={`Discord: ${profile.records['com.discord']}`} />
144+
<LuMessageSquare className="h-4 w-4" title={`Discord: ${profileData.records['com.discord']}`} />
142145
</div>
143146
)}
144-
{profile.records?.['org.telegram'] && (
147+
{profileData?.records?.['org.telegram'] && (
145148
<div className="text-blue-500 hover:text-blue-700">
146-
<LuSend className="h-4 w-4" title={`Telegram: ${profile.records['org.telegram']}`} />
149+
<LuSend className="h-4 w-4" title={`Telegram: ${profileData.records['org.telegram']}`} />
147150
</div>
148151
)}
149152
</div>

packages/search/src/hooks/useProfile.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { useQuery } from '@tanstack/react-query';
2-
import { SearchResult } from './useSearch';
2+
import { ProfileSearchResult } from './useSearch';
33

44
// We'll use the same interface as SearchResult for consistency
5-
export type Profile = SearchResult;
5+
export type Profile = ProfileSearchResult;
66

77
import { profileFetcher } from 'use-enstate/helpers';
88

@@ -28,4 +28,4 @@ export const useProfile = (profileId: string) => {
2828
enabled: Boolean(profileId),
2929
staleTime: 1000 * 60 * 5, // 5 minutes
3030
});
31-
};
31+
};

packages/search/src/hooks/useSearch.ts

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,20 @@
11
import { useQuery } from '@tanstack/react-query';
22
import axios from 'axios';
33

4-
export interface SearchResult {
4+
export interface ProfileSearchResult {
55
name: string;
6-
address: string;
7-
avatar?: string;
8-
header?: string;
9-
display: string;
10-
contenthash?: string;
11-
records?: {
12-
avatar?: string;
13-
description?: string;
14-
email?: string;
15-
name?: string;
16-
url?: string;
17-
location?: string;
18-
'com.discord'?: string;
19-
'com.github'?: string;
20-
'com.twitter'?: string;
21-
'org.telegram'?: string;
22-
header?: string;
23-
timezone?: string;
24-
pronouns?: string;
25-
[key: string]: string | undefined;
26-
};
27-
chains?: Record<string, string>;
28-
fresh?: number;
29-
resolver?: string;
30-
ccip_urls?: string[];
31-
errors?: Record<string, any>;
326
}
337

348
export const useSearch = (searchTerm: string) => {
359
return useQuery({
3610
queryKey: ['search', searchTerm],
3711
queryFn: async () => {
3812
if (!searchTerm.trim()) {
39-
return [] as SearchResult[];
13+
return [] as ProfileSearchResult[];
4014
}
41-
15+
4216
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:3000';
43-
const response = await axios.get<SearchResult[]>(
17+
const response = await axios.get<ProfileSearchResult[]>(
4418
`${apiUrl}/v2/discover/search?s=${encodeURIComponent(searchTerm)}`
4519
);
4620

packages/shared/src/discovery/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
use crate::core::{ENSService, Profile};
22
use async_trait::async_trait;
33

4+
pub struct SearchResult {
5+
pub name: String,
6+
}
7+
48
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
59
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
610
pub trait Discovery: Send + Sync {
711
async fn discover_name(&self, profile: &Profile) -> Result<(), ()>;
812

9-
async fn query_search(&self, service: &ENSService, query: String) -> Result<Vec<Profile>, ()>;
13+
async fn query_search(&self, service: &ENSService, query: String) -> Result<Vec<SearchResult>, ()>;
1014
}

0 commit comments

Comments
 (0)