@@ -16,6 +16,19 @@ use crate::{
1616pub const TITLE : & str = "Reprompt" ;
1717pub const VERSION : & str = env ! ( "CARGO_PKG_VERSION" ) ;
1818
19+ #[ derive( serde:: Serialize , serde:: Deserialize , Clone , Copy , PartialEq , Eq ) ]
20+ pub enum SortMode {
21+ HistoryCount ,
22+ LastUsage ,
23+ InsertionOrder ,
24+ }
25+
26+ impl Default for SortMode {
27+ fn default ( ) -> Self {
28+ Self :: InsertionOrder
29+ }
30+ }
31+
1932#[ derive( serde:: Serialize , serde:: Deserialize ) ]
2033#[ serde( default ) ]
2134pub struct App {
@@ -29,6 +42,8 @@ pub struct App {
2942 ollama_client : OllamaClient ,
3043 #[ serde( skip) ]
3144 commonmark_cache : CommonMarkCache ,
45+ #[ serde( skip) ]
46+ sort_mode : SortMode ,
3247}
3348
3449impl Default for App {
@@ -44,6 +59,7 @@ impl Default for App {
4459 ollama_client : OllamaClient :: new ( Ollama :: default ( ) ) ,
4560 ollama_models : Default :: default ( ) ,
4661 commonmark_cache : CommonMarkCache :: default ( ) ,
62+ sort_mode : SortMode :: InsertionOrder ,
4763 }
4864 }
4965}
@@ -225,27 +241,27 @@ impl App {
225241 }
226242 }
227243 AppAction :: GeneratePromptResponse { idx, input } => {
228- if let Some ( selected_model) = & self . ollama_models . selected {
229- if let Some ( prompt) = self . prompts . get_mut ( idx) {
230- prompt . generate_response (
231- input ,
232- selected_model ,
233- & self . tokio_runtime ,
234- & self . ollama_client ,
235- ) ;
236- }
244+ if let Some ( selected_model) = & self . ollama_models . selected
245+ && let Some ( prompt) = self . prompts . get_mut ( idx)
246+ {
247+ prompt . generate_response (
248+ input ,
249+ selected_model ,
250+ & self . tokio_runtime ,
251+ & self . ollama_client ,
252+ ) ;
237253 }
238254 }
239255 AppAction :: RegeneratePromptResponse { idx, history_idx } => {
240- if let Some ( selected_model) = & self . ollama_models . selected {
241- if let Some ( prompt) = self . prompts . get_mut ( idx) {
242- prompt . regenerate_response (
243- history_idx ,
244- selected_model ,
245- & self . tokio_runtime ,
246- & self . ollama_client ,
247- ) ;
248- }
256+ if let Some ( selected_model) = & self . ollama_models . selected
257+ && let Some ( prompt) = self . prompts . get_mut ( idx)
258+ {
259+ prompt . regenerate_response (
260+ history_idx ,
261+ selected_model ,
262+ & self . tokio_runtime ,
263+ & self . ollama_client ,
264+ ) ;
249265 }
250266 }
251267 AppAction :: CloseDialog => {
@@ -442,7 +458,9 @@ impl App {
442458 ui. horizontal_top ( |ui| {
443459 assign_if_some ! ( action, self . show_left_panel_create_protmp_button( ui) ) ;
444460
445- assign_if_some ! ( action, self . show_left_panel_model_selector( ui) )
461+ assign_if_some ! ( action, self . show_left_panel_model_selector( ui) ) ;
462+
463+ self . show_left_panel_sort_mode_selector ( ui) ;
446464 } ) ;
447465
448466 ui. separator ( ) ;
@@ -557,6 +575,85 @@ impl App {
557575 action
558576 }
559577
578+ fn show_left_panel_sort_mode_selector ( & mut self , ui : & mut egui:: Ui ) {
579+ ui. horizontal ( |ui| {
580+ ui. label ( "Sort by:" ) ;
581+
582+ egui:: ComboBox :: from_id_salt ( "sort_mode_selector" )
583+ . selected_text ( match self . sort_mode {
584+ SortMode :: InsertionOrder => "insertion" ,
585+ SortMode :: HistoryCount => "history count" ,
586+ SortMode :: LastUsage => "last usage" ,
587+ } )
588+ . show_ui ( ui, |ui| {
589+ if ui
590+ . selectable_label (
591+ matches ! ( self . sort_mode, SortMode :: InsertionOrder ) ,
592+ "insertion (default)" ,
593+ )
594+ . clicked ( )
595+ {
596+ self . sort_mode = SortMode :: InsertionOrder ;
597+ }
598+ if ui
599+ . selectable_label (
600+ matches ! ( self . sort_mode, SortMode :: HistoryCount ) ,
601+ "history count" ,
602+ )
603+ . clicked ( )
604+ {
605+ self . sort_mode = SortMode :: HistoryCount ;
606+ }
607+ if ui
608+ . selectable_label (
609+ matches ! ( self . sort_mode, SortMode :: LastUsage ) ,
610+ "last usage" ,
611+ )
612+ . clicked ( )
613+ {
614+ self . sort_mode = SortMode :: LastUsage ;
615+ }
616+ } ) ;
617+ } ) ;
618+ }
619+
620+ /// Sorts prompt indices based on the current sort mode
621+ fn sort_prompt_indices ( & self ) -> Vec < usize > {
622+ let mut prompt_indices = ( 0 ..self . prompts . len ( ) ) . collect :: < Vec < usize > > ( ) ;
623+
624+ match self . sort_mode {
625+ SortMode :: HistoryCount => {
626+ prompt_indices. sort_by ( |& a, & b| {
627+ // First sort by history count (descending)
628+ let count_a = self . prompts [ a] . history_count ( ) ;
629+ let count_b = self . prompts [ b] . history_count ( ) ;
630+
631+ count_b. cmp ( & count_a)
632+ } ) ;
633+ }
634+ SortMode :: LastUsage => {
635+ prompt_indices. sort_by ( |& a, & b| {
636+ // Sort by last usage time (descending)
637+ let last_used_a = self . prompts [ a] . get_last_used_time ( ) ;
638+ let last_used_b = self . prompts [ b] . get_last_used_time ( ) ;
639+
640+ // Handle cases where one or both might be None
641+ match ( last_used_a, last_used_b) {
642+ ( Some ( time_a) , Some ( time_b) ) => time_b. cmp ( & time_a) , // More recent first
643+ ( Some ( _) , None ) => std:: cmp:: Ordering :: Less , // a is more recent
644+ ( None , Some ( _) ) => std:: cmp:: Ordering :: Greater , // b is more recent
645+ ( None , None ) => std:: cmp:: Ordering :: Equal , // both are equal
646+ }
647+ } ) ;
648+ }
649+ SortMode :: InsertionOrder => {
650+ // No sorting - maintain insertion order
651+ }
652+ }
653+
654+ prompt_indices
655+ }
656+
560657 fn show_left_panel_prompts (
561658 & mut self ,
562659 ui : & mut egui:: Ui ,
@@ -566,7 +663,11 @@ impl App {
566663 let mut action = None ;
567664
568665 ScrollArea :: vertical ( ) . show ( ui, |ui| {
569- for ( idx, prompt) in self . prompts . iter ( ) . enumerate ( ) {
666+ // Sort prompts based on current sort mode
667+ let prompt_indices = self . sort_prompt_indices ( ) ;
668+
669+ for & idx in & prompt_indices {
670+ let prompt = & self . prompts [ idx] ;
570671 let selected = self . view . is_prompt_selected ( idx) ;
571672
572673 ui. add_space ( 3.0 ) ;
0 commit comments