11use crate :: calculator:: Expression ;
2+ use crate :: clipboard:: ClipBoardContentType ;
23use crate :: commands:: Function ;
34use crate :: config:: Config ;
45use crate :: macos:: { focus_this_app, transform_process_to_ui_element} ;
56use crate :: { macos, utils:: get_installed_apps} ;
67
8+ use arboard:: Clipboard ;
79use global_hotkey:: { GlobalHotKeyEvent , HotKeyState } ;
810use iced:: futures:: SinkExt ;
11+ use iced:: widget:: text:: LineHeight ;
912use iced:: {
1013 Alignment , Element , Fill , Subscription , Task , Theme ,
1114 alignment:: Vertical ,
@@ -14,7 +17,7 @@ use iced::{
1417 stream,
1518 widget:: {
1619 Button , Column , Row , Text , container, image:: Viewer , operation, scrollable, space,
17- text :: LineHeight , text_input,
20+ text_input,
1821 } ,
1922 window:: { self , Id , Settings } ,
2023} ;
@@ -61,6 +64,7 @@ impl App {
6164 } ,
6265 ]
6366 }
67+
6468 pub fn render ( & self , theme : & crate :: config:: Theme ) -> impl Into < iced:: Element < ' _ , Message > > {
6569 let mut tile = Row :: new ( ) . width ( Fill ) . height ( 55 ) ;
6670
@@ -115,6 +119,12 @@ impl App {
115119 }
116120}
117121
122+ #[ derive( Debug , Clone , PartialEq ) ]
123+ pub enum Page {
124+ Main ,
125+ ClipboardHistory ,
126+ }
127+
118128#[ derive( Debug , Clone ) ]
119129pub enum Message {
120130 OpenWindow ,
@@ -126,6 +136,7 @@ pub enum Message {
126136 WindowFocusChanged ( Id , bool ) ,
127137 ClearSearchQuery ,
128138 ReloadConfig ,
139+ ClipboardHistory ( ClipBoardContentType ) ,
129140 _Nothing,
130141}
131142
@@ -158,6 +169,8 @@ pub struct Tile {
158169 frontmost : Option < Retained < NSRunningApplication > > ,
159170 config : Config ,
160171 open_hotkey_id : u32 ,
172+ clipboard_content : Vec < ClipBoardContentType > ,
173+ page : Page ,
161174}
162175
163176impl Tile {
@@ -207,6 +220,8 @@ impl Tile {
207220 config : config. clone ( ) ,
208221 theme : config. theme . to_owned ( ) . into ( ) ,
209222 open_hotkey_id : keybind_id,
223+ clipboard_content : vec ! [ ] ,
224+ page : Page :: Main ,
210225 } ,
211226 Task :: batch ( [ open. map ( |_| Message :: OpenWindow ) ] ) ,
212227 )
@@ -262,6 +277,10 @@ impl Tile {
262277 id,
263278 iced:: Size :: new ( WINDOW_WIDTH , 55. + DEFAULT_WINDOW_HEIGHT ) ,
264279 ) ;
280+ } else if self . query_lc == "cbhist" {
281+ self . page = Page :: ClipboardHistory
282+ } else if self . query_lc == "main" {
283+ self . page = Page :: Main
265284 }
266285
267286 self . handle_search_query_changed ( ) ;
@@ -281,15 +300,25 @@ impl Tile {
281300
282301 let max_elem = min ( 5 , new_length) ;
283302
284- if prev_size != new_length {
303+ if prev_size != new_length && self . page == Page :: Main {
285304 thread:: sleep ( Duration :: from_millis ( 30 ) ) ;
305+
286306 window:: resize (
287307 id,
288308 iced:: Size {
289309 width : WINDOW_WIDTH ,
290310 height : ( ( max_elem * 55 ) + DEFAULT_WINDOW_HEIGHT as usize ) as f32 ,
291311 } ,
292312 )
313+ } else if self . page == Page :: ClipboardHistory {
314+ let element_count = min ( self . clipboard_content . len ( ) , 5 ) ;
315+ window:: resize (
316+ id,
317+ iced:: Size {
318+ width : WINDOW_WIDTH ,
319+ height : ( ( element_count * 55 ) + DEFAULT_WINDOW_HEIGHT as usize ) as f32 ,
320+ } ,
321+ )
293322 } else {
294323 Task :: none ( )
295324 }
@@ -357,6 +386,7 @@ impl Tile {
357386 self . restore_frontmost ( ) ;
358387 self . visible = false ;
359388 self . focused = false ;
389+ self . page = Page :: Main ;
360390 Task :: batch ( [ window:: close ( a) , Task :: done ( Message :: ClearSearchResults ) ] )
361391 }
362392 Message :: ClearSearchResults => {
@@ -373,6 +403,11 @@ impl Tile {
373403 }
374404 }
375405
406+ Message :: ClipboardHistory ( clip_content) => {
407+ self . clipboard_content . push ( clip_content) ;
408+ Task :: none ( )
409+ }
410+
376411 Message :: _Nothing => Task :: none ( ) ,
377412 }
378413 }
@@ -391,18 +426,31 @@ impl Tile {
391426 } )
392427 . id ( "query" )
393428 . width ( Fill )
394- . padding ( 20 )
395- . line_height ( LineHeight :: Relative ( 1.5 ) ) ;
396-
397- let mut search_results = Column :: new ( ) ;
398- for result in & self . results {
399- search_results = search_results. push ( result. render ( & self . config . theme ) ) ;
429+ . line_height ( LineHeight :: Relative ( 1.5 ) )
430+ . padding ( 20 ) ;
431+
432+ match self . page {
433+ Page :: Main => {
434+ let mut search_results = Column :: new ( ) ;
435+ for result in & self . results {
436+ search_results = search_results. push ( result. render ( & self . config . theme ) ) ;
437+ }
438+ Column :: new ( )
439+ . push ( title_input)
440+ . push ( scrollable ( search_results) )
441+ . into ( )
442+ }
443+ Page :: ClipboardHistory => {
444+ let mut clipboard_history = Column :: new ( ) ;
445+ for result in & self . clipboard_content {
446+ clipboard_history = clipboard_history. push ( result. render_clipboard_item ( ) ) ;
447+ }
448+ Column :: new ( )
449+ . push ( title_input)
450+ . push ( scrollable ( clipboard_history) )
451+ . into ( )
452+ }
400453 }
401-
402- Column :: new ( )
403- . push ( title_input)
404- . push ( scrollable ( search_results) )
405- . into ( )
406454 } else {
407455 space ( ) . into ( )
408456 }
@@ -416,6 +464,7 @@ impl Tile {
416464 Subscription :: batch ( [
417465 Subscription :: run ( handle_hotkeys) ,
418466 Subscription :: run ( handle_hot_reloading) ,
467+ Subscription :: run ( handle_clipboard_history) ,
419468 window:: close_events ( ) . map ( Message :: HideWindow ) ,
420469 keyboard:: listen ( ) . filter_map ( |event| {
421470 if let keyboard:: Event :: KeyPressed { key, .. } = event {
@@ -527,3 +576,31 @@ fn handle_hotkeys() -> impl futures::Stream<Item = Message> {
527576 }
528577 } )
529578}
579+
580+ fn handle_clipboard_history ( ) -> impl futures:: Stream < Item = Message > {
581+ stream:: channel ( 100 , async |mut output| {
582+ let mut clipboard = Clipboard :: new ( ) . unwrap ( ) ;
583+ let mut prev_byte_rep: Option < ClipBoardContentType > = None ;
584+
585+ loop {
586+ let byte_rep = if let Ok ( a) = clipboard. get_image ( ) {
587+ Some ( ClipBoardContentType :: Image ( a) )
588+ } else if let Ok ( a) = clipboard. get_text ( ) {
589+ Some ( ClipBoardContentType :: Text ( a) )
590+ } else {
591+ None
592+ } ;
593+
594+ if byte_rep != prev_byte_rep
595+ && let Some ( content) = & byte_rep
596+ {
597+ output
598+ . send ( Message :: ClipboardHistory ( content. to_owned ( ) ) )
599+ . await
600+ . ok ( ) ;
601+ prev_byte_rep = byte_rep;
602+ }
603+ tokio:: time:: sleep ( Duration :: from_millis ( 10 ) ) . await ;
604+ }
605+ } )
606+ }
0 commit comments