@@ -47,6 +47,23 @@ pub struct App {
4747 pub icons : Option < iced:: widget:: image:: Handle > ,
4848 pub display_name : String ,
4949 pub search_name : String ,
50+ /// When true, the result row expands to fit AI response text
51+ pub is_ai_response : bool ,
52+ }
53+
54+ impl App {
55+ /// Estimate the rendered height for this result item.
56+ /// AI responses grow based on text length; normal items are fixed at 66px.
57+ pub fn estimated_height ( & self ) -> usize {
58+ if self . is_ai_response {
59+ // ~60 chars per line at size 16 in a 460px-wide area, 20px per line
60+ let lines = ( self . display_name . len ( ) as f32 / 55.0 ) . ceil ( ) . max ( 1.0 ) as usize ;
61+ let text_height = lines * 20 + 30 ; // 30 for desc + spacing + padding
62+ text_height. max ( 66 ) . min ( 400 ) // min 66, max 400
63+ } else {
64+ 66
65+ }
66+ }
5067}
5168
5269impl PartialEq for App {
@@ -55,6 +72,7 @@ impl PartialEq for App {
5572 && self . icons == other. icons
5673 && self . desc == other. desc
5774 && self . display_name == other. display_name
75+ && self . is_ai_response == other. is_ai_response
5876 }
5977}
6078
@@ -68,6 +86,7 @@ impl App {
6886 icons : None ,
6987 display_name : x. to_string ( ) ,
7088 search_name : x. name ( ) . to_string ( ) ,
89+ is_ai_response : false ,
7190 open_command : AppCommand :: Function ( Function :: CopyToClipboard (
7291 ClipBoardContentType :: Text ( x. to_string ( ) ) ,
7392 ) ) ,
@@ -99,6 +118,7 @@ impl App {
99118 desc: "Easter Egg" . to_string( ) ,
100119 display_name: "Ferris Plushies" . to_string( ) ,
101120 search_name: "ferris.rs" . to_string( ) ,
121+ is_ai_response: false ,
102122 } ,
103123 App {
104124 ranking: 0 ,
@@ -107,6 +127,7 @@ impl App {
107127 icons: icons. clone( ) ,
108128 display_name: "Quit RustCast" . to_string( ) ,
109129 search_name: "quit" . to_string( ) ,
130+ is_ai_response: false ,
110131 } ,
111132 App {
112133 ranking: 0 ,
@@ -115,6 +136,7 @@ impl App {
115136 icons: icons. clone( ) ,
116137 display_name: "Open RustCast Preferences" . to_string( ) ,
117138 search_name: "settings" . to_string( ) ,
139+ is_ai_response: false ,
118140 } ,
119141 App {
120142 ranking: 0 ,
@@ -123,6 +145,7 @@ impl App {
123145 icons: icons. clone( ) ,
124146 display_name: "Search for an Emoji" . to_string( ) ,
125147 search_name: "emoji" . to_string( ) ,
148+ is_ai_response: false ,
126149 } ,
127150 App {
128151 ranking: 0 ,
@@ -131,6 +154,7 @@ impl App {
131154 icons: icons. clone( ) ,
132155 display_name: "Clipboard History" . to_string( ) ,
133156 search_name: "clipboard" . to_string( ) ,
157+ is_ai_response: false ,
134158 } ,
135159 App {
136160 ranking: 0 ,
@@ -139,6 +163,7 @@ impl App {
139163 icons: icons. clone( ) ,
140164 display_name: "Search for a file" . to_string( ) ,
141165 search_name: "file search" . to_string( ) ,
166+ is_ai_response: false ,
142167 } ,
143168 App {
144169 ranking: 0 ,
@@ -147,6 +172,7 @@ impl App {
147172 icons: icons. clone( ) ,
148173 display_name: "Reload RustCast" . to_string( ) ,
149174 search_name: "refresh" . to_string( ) ,
175+ is_ai_response: false ,
150176 } ,
151177 App {
152178 ranking: 0 ,
@@ -155,6 +181,7 @@ impl App {
155181 icons: icons. clone( ) ,
156182 display_name: format!( "Current RustCast Version: {app_version}" ) ,
157183 search_name: "version" . to_string( ) ,
184+ is_ai_response: false ,
158185 } ,
159186 ]
160187 }
@@ -185,11 +212,21 @@ impl App {
185212 . color ( theme. text_color ( 0.55 ) ) ,
186213 ) ;
187214
215+ let is_ai = self . is_ai_response ;
216+
188217 let mut row = Row :: new ( )
189- . align_y ( Alignment :: Center )
218+ . align_y ( if is_ai {
219+ Alignment :: Start
220+ } else {
221+ Alignment :: Center
222+ } )
190223 . width ( Fill )
191- . spacing ( 10 )
192- . height ( 50 ) ;
224+ . spacing ( 10 ) ;
225+
226+ // Only set fixed height for non-AI results
227+ if !is_ai {
228+ row = row. height ( 50 ) ;
229+ }
193230
194231 if theme. show_icons
195232 && let Some ( icon) = & self . icons
@@ -210,12 +247,16 @@ impl App {
210247
211248 let theme_clone = theme. clone ( ) ;
212249
213- let content = Button :: new ( row)
250+ let mut content = Button :: new ( row)
214251 . on_press_maybe ( msg)
215252 . style ( move |_, _| result_button_style ( & theme_clone) )
216253 . width ( Fill )
217- . padding ( 0 )
218- . height ( 50 ) ;
254+ . padding ( if is_ai { 10 } else { 0 } ) ;
255+
256+ // Only set fixed height for non-AI results
257+ if !is_ai {
258+ content = content. height ( 50 ) ;
259+ }
219260
220261 container ( content)
221262 . id ( format ! ( "result-{}" , id_num) )
0 commit comments