11use crate :: {
22 db:: { FONT_TABLE as DB_TABLE , FontEntry } ,
3- db_add , db_remove_all , db_select_all, db_update,
3+ db_select_all, db_update,
44 logic:: { toast, tr:: tr, video_editor:: playlist:: picker_files} ,
55 logic_cb,
66 slint_generatedAppWindow:: { AppWindow , FontEntry as UIFontEntry } ,
77} ;
8- use slint:: { ComponentHandle , Model , VecModel , Weak } ;
8+ use once_cell:: sync:: Lazy ;
9+ use slint:: { ComponentHandle , Model , SharedString , VecModel , Weak } ;
910use std:: { collections:: HashSet , path:: PathBuf } ;
10- use video_editor:: font:: get_font_family_from_file;
11+ use tokio:: sync:: RwLock ;
12+ use video_editor:: font:: { get_font_family_from_file, get_fonts_info} ;
1113
12- db_add ! ( DB_TABLE , FontEntry ) ;
13- db_remove_all ! ( DB_TABLE ) ;
1414db_update ! ( DB_TABLE , FontEntry ) ;
1515
16+ static FONT_CACHE : Lazy < RwLock < Vec < FontEntry > > > = Lazy :: new ( || RwLock :: new ( Vec :: new ( ) ) ) ;
17+
1618#[ macro_export]
1719macro_rules! store_font_entries {
1820 ( $ui: expr) => {
@@ -30,6 +32,7 @@ pub fn init(ui: &AppWindow) {
3032 logic_cb ! ( init_font_dialog, ui) ;
3133 logic_cb ! ( refresh_font_entries, ui) ;
3234 logic_cb ! ( import_font_files, ui) ;
35+ logic_cb ! ( search_font_entries, ui, text) ;
3336 logic_cb ! ( toggle_font_marked, ui, index) ;
3437}
3538
@@ -40,7 +43,7 @@ fn init_font_dialog(ui: &AppWindow) {
4043 if db_fonts. is_empty ( ) {
4144 refresh_font_entries_impl ( ui_weak. clone ( ) ) . await ;
4245 } else {
43- sync_fonts_to_ui ( ui_weak, db_fonts) ;
46+ sync_fonts_to_ui ( ui_weak, db_fonts) . await ;
4447 }
4548 } ) ;
4649}
@@ -66,7 +69,7 @@ async fn refresh_font_entries_impl(ui_weak: Weak<AppWindow>) {
6669 log:: warn!( "Failed to clear font table: {}" , e) ;
6770 }
6871
69- let system_fonts = match video_editor :: font :: get_fonts_info ( ) {
72+ let system_fonts = match get_fonts_info ( ) {
7073 Ok ( fonts) => fonts,
7174 Err ( e) => {
7275 toast:: async_toast_warn ( ui_weak. clone ( ) , format ! ( "Failed to get fonts: {}" , e) ) ;
@@ -94,10 +97,13 @@ async fn refresh_font_entries_impl(ui_weak: Weak<AppWindow>) {
9497 font_entries. push ( entry) ;
9598 }
9699
97- sync_fonts_to_ui ( ui_weak, font_entries) ;
100+ sync_fonts_to_ui ( ui_weak, font_entries) . await ;
98101}
99102
100- fn sync_fonts_to_ui ( ui_weak : Weak < AppWindow > , mut fonts : Vec < FontEntry > ) {
103+ async fn sync_fonts_to_ui ( ui_weak : Weak < AppWindow > , mut fonts : Vec < FontEntry > ) {
104+ let fonts_for_cache = fonts. clone ( ) ;
105+ * FONT_CACHE . write ( ) . await = fonts_for_cache;
106+
101107 fonts. sort_by ( |a, b| b. marked . cmp ( & a. marked ) ) ;
102108 let ui_fonts: Vec < UIFontEntry > = fonts. into_iter ( ) . map ( |f| f. into ( ) ) . collect ( ) ;
103109
@@ -119,23 +125,37 @@ fn import_font_files(ui: &AppWindow) {
119125 None => return ,
120126 } ;
121127
128+ let mut imported_fonts: Vec < UIFontEntry > = Vec :: new ( ) ;
122129 for file_path in file_paths {
123- import_font_to_db ( ui_weak. clone ( ) , file_path) . await ;
130+ if let Some ( font_entry) = import_font_to_db ( ui_weak. clone ( ) , file_path) . await {
131+ imported_fonts. push ( font_entry. into ( ) ) ;
132+ }
124133 }
125134
126- refresh_font_entries_impl ( ui_weak) . await ;
135+ if !imported_fonts. is_empty ( ) {
136+ let mut cache = FONT_CACHE . write ( ) . await ;
137+ for font in & imported_fonts {
138+ cache. push ( font. clone ( ) . into ( ) ) ;
139+ }
140+
141+ _ = ui_weak. upgrade_in_event_loop ( move |ui| {
142+ let mut fonts: Vec < UIFontEntry > = store_font_entries ! ( ui) . iter ( ) . collect ( ) ;
143+ fonts. splice ( 0 ..0 , imported_fonts) ;
144+ store_font_entries ! ( ui) . set_vec ( fonts) ;
145+ } ) ;
146+ }
127147 } ) ;
128148}
129149
130- async fn import_font_to_db ( ui_weak : Weak < AppWindow > , file_path : PathBuf ) {
150+ async fn import_font_to_db ( ui_weak : Weak < AppWindow > , file_path : PathBuf ) -> Option < FontEntry > {
131151 let family = match get_font_family_from_file ( & file_path) {
132152 Ok ( f) => f,
133153 Err ( e) => {
134154 toast:: async_toast_warn (
135155 ui_weak. clone ( ) ,
136156 format ! ( "Failed to read font file {}: {}" , file_path. display( ) , e) ,
137157 ) ;
138- return ;
158+ return None ;
139159 }
140160 } ;
141161
@@ -154,10 +174,11 @@ async fn import_font_to_db(ui_weak: Weak<AppWindow>, file_path: PathBuf) {
154174 ui_weak. clone ( ) ,
155175 format ! ( "Failed to import font {}: {}" , entry. family, e) ,
156176 ) ;
157- return ;
177+ return None ;
158178 }
159179
160180 toast:: async_toast_success ( ui_weak. clone ( ) , format ! ( "Imported font: {}" , entry. family) ) ;
181+ Some ( entry)
161182}
162183
163184fn toggle_font_marked ( ui : & AppWindow , index : i32 ) {
@@ -175,3 +196,24 @@ fn toggle_font_marked(ui: &AppWindow, index: i32) {
175196 store_font_entries ! ( ui) . set_vec ( fonts) ;
176197 }
177198}
199+
200+ fn search_font_entries ( ui : & AppWindow , text : SharedString ) {
201+ let ui_weak = ui. as_weak ( ) ;
202+ let text = text. to_string ( ) ;
203+
204+ tokio:: spawn ( async move {
205+ let cache = FONT_CACHE . read ( ) . await . clone ( ) ;
206+
207+ let filtered = if text. is_empty ( ) {
208+ cache
209+ } else {
210+ let keyword = text. to_lowercase ( ) ;
211+ cache
212+ . into_iter ( )
213+ . filter ( |f| f. family . to_lowercase ( ) . contains ( & keyword) )
214+ . collect ( )
215+ } ;
216+
217+ sync_fonts_to_ui ( ui_weak, filtered) . await ;
218+ } ) ;
219+ }
0 commit comments