@@ -23,13 +23,14 @@ use tokio::{
2323} ;
2424use tracing:: { debug, info} ;
2525
26- use crate :: state:: { ModOrGroup , ModProfile } ;
2726use crate :: {
2827 integrate:: uninstall,
2928 is_drg_pak,
30- providers:: ModioTags ,
31- providers:: { FetchProgress , ModSpecification , ModStore , ProviderFactory } ,
32- state:: { ModConfig , ModData_v0_1_0 as ModData , State } ,
29+ providers:: {
30+ ApprovalStatus , FetchProgress , ModInfo , ModSpecification , ModStore , ModioTags ,
31+ ProviderFactory , RequiredStatus ,
32+ } ,
33+ state:: { ModConfig , ModData_v0_1_0 as ModData , ModOrGroup , ModProfile , State } ,
3334} ;
3435use find_string:: FindString ;
3536use message:: MessageHandle ;
@@ -117,11 +118,13 @@ impl App {
117118
118119 struct Ctx {
119120 needs_save : bool ,
121+ scroll_to_match : bool ,
120122 btn_remove : Option < usize > ,
121123 add_deps : Option < Vec < ModSpecification > > ,
122124 }
123125 let mut ctx = Ctx {
124126 needs_save : false ,
127+ scroll_to_match : self . scroll_to_match ,
125128 btn_remove : None ,
126129 add_deps : None ,
127130 } ;
@@ -154,6 +157,143 @@ impl App {
154157 } )
155158 . collect :: < Vec < _ > > ( ) ;
156159
160+ let ui_mod_tags = |ctx : & mut Ctx , ui : & mut Ui , info : & ModInfo | {
161+ if let Some ( ModioTags {
162+ qol,
163+ gameplay,
164+ audio,
165+ visual,
166+ framework,
167+ required_status,
168+ approval_status,
169+ versions : _,
170+ } ) = info. modio_tags . as_ref ( )
171+ {
172+ let mut mk_searchable_modio_tag =
173+ |tag_str : & str ,
174+ ui : & mut Ui ,
175+ color : Option < egui:: Color32 > ,
176+ hover_str : Option < & str > | {
177+ let text_color = if color. is_some ( ) {
178+ Color32 :: BLACK
179+ } else {
180+ Color32 :: GRAY
181+ } ;
182+ let mut job = LayoutJob :: default ( ) ;
183+ let mut is_match = false ;
184+ if let Some ( search_string) = & self . search_string {
185+ for ( m, chunk) in
186+ find_string:: FindString :: new ( tag_str, search_string)
187+ {
188+ let background = if m {
189+ is_match = true ;
190+ TextFormat {
191+ background : Color32 :: YELLOW ,
192+ color : text_color,
193+ ..Default :: default ( )
194+ }
195+ } else {
196+ TextFormat {
197+ color : text_color,
198+ ..Default :: default ( )
199+ }
200+ } ;
201+ job. append ( chunk, 0.0 , background) ;
202+ }
203+ } else {
204+ job. append (
205+ tag_str,
206+ 0.0 ,
207+ TextFormat {
208+ color : text_color,
209+ ..Default :: default ( )
210+ } ,
211+ ) ;
212+ }
213+
214+ let button = if let Some ( color) = color {
215+ egui:: Button :: new ( job)
216+ . small ( )
217+ . fill ( color)
218+ . stroke ( egui:: Stroke :: NONE )
219+ } else {
220+ egui:: Button :: new ( job) . small ( ) . stroke ( egui:: Stroke :: NONE )
221+ } ;
222+
223+ let res = if let Some ( hover_str) = hover_str {
224+ ui. add_enabled ( false , button)
225+ . on_disabled_hover_text ( hover_str)
226+ } else {
227+ ui. add_enabled ( false , button)
228+ } ;
229+
230+ if is_match && self . scroll_to_match {
231+ res. scroll_to_me ( None ) ;
232+ ctx. scroll_to_match = false ;
233+ }
234+ } ;
235+
236+ match approval_status {
237+ ApprovalStatus :: Verified => {
238+ mk_searchable_modio_tag (
239+ "Verified" ,
240+ ui,
241+ Some ( egui:: Color32 :: LIGHT_GREEN ) ,
242+ Some ( "Does not contain any gameplay affecting features or changes" ) ,
243+ ) ;
244+ }
245+ ApprovalStatus :: Approved => {
246+ mk_searchable_modio_tag (
247+ "Approved" ,
248+ ui,
249+ Some ( egui:: Color32 :: LIGHT_BLUE ) ,
250+ Some ( "Contains gameplay affecting features or changes" ) ,
251+ ) ;
252+ }
253+ ApprovalStatus :: Sandbox => {
254+ mk_searchable_modio_tag ( "Sandbox" , ui, Some ( egui:: Color32 :: LIGHT_YELLOW ) , Some ( "Contains significant, possibly progression breaking, changes to gameplay" ) ) ;
255+ }
256+ }
257+
258+ match required_status {
259+ RequiredStatus :: RequiredByAll => {
260+ mk_searchable_modio_tag (
261+ "RequiredByAll" ,
262+ ui,
263+ Some ( egui:: Color32 :: LIGHT_RED ) ,
264+ Some (
265+ "All lobby members must use this mod for it to work correctly!" ,
266+ ) ,
267+ ) ;
268+ }
269+ RequiredStatus :: Optional => {
270+ mk_searchable_modio_tag (
271+ "Optional" ,
272+ ui,
273+ None ,
274+ Some ( "Clients are not required to install this mod to function" ) ,
275+ ) ;
276+ }
277+ }
278+
279+ if * qol {
280+ mk_searchable_modio_tag ( "QoL" , ui, None , None ) ;
281+ }
282+ if * gameplay {
283+ mk_searchable_modio_tag ( "Gameplay" , ui, None , None ) ;
284+ }
285+ if * audio {
286+ mk_searchable_modio_tag ( "Audio" , ui, None , None ) ;
287+ }
288+ if * visual {
289+ mk_searchable_modio_tag ( "Visual" , ui, None , None ) ;
290+ }
291+ if * framework {
292+ mk_searchable_modio_tag ( "Framework" , ui, None , None ) ;
293+ }
294+ }
295+ } ;
296+
157297 let mut ui_mod = |ctx : & mut Ctx ,
158298 ui : & mut Ui ,
159299 _group : Option < & str > ,
@@ -331,105 +471,12 @@ impl App {
331471 let res = ui. hyperlink_to ( job, & mc. spec . url ) ;
332472 if is_match && self . scroll_to_match {
333473 res. scroll_to_me ( None ) ;
334- self . scroll_to_match = false ;
474+ ctx . scroll_to_match = false ;
335475 }
336476
337- if let Some ( ModioTags {
338- qol,
339- gameplay,
340- audio,
341- visual,
342- framework,
343- required_status,
344- approval_status,
345- .. // version ignored
346- } ) = info. modio_tags . as_ref ( )
347- {
348- let mut mk_searchable_modio_tag = |tag_str : & str , ui : & mut Ui , color : Option < egui:: Color32 > , hover_str : Option < & str > | {
349- let text_color = if color. is_some ( ) { Color32 :: BLACK } else { Color32 :: GRAY } ;
350- let mut job = LayoutJob :: default ( ) ;
351- let mut is_match = false ;
352- if let Some ( search_string) = & self . search_string {
353- for ( m, chunk) in find_string:: FindString :: new ( tag_str, search_string) {
354- let background = if m {
355- is_match = true ;
356- TextFormat {
357- background : Color32 :: YELLOW ,
358- color : text_color,
359- ..Default :: default ( )
360- }
361- } else {
362- TextFormat {
363- color : text_color,
364- ..Default :: default ( )
365- }
366- } ;
367- job. append ( chunk, 0.0 , background) ;
368- }
369- } else {
370- job. append ( tag_str, 0.0 , TextFormat {
371- color : text_color,
372- ..Default :: default ( )
373- } ) ;
374- }
375-
376- let button = if let Some ( color) = color {
377- egui:: Button :: new ( job) . small ( ) . fill ( color) . stroke ( egui:: Stroke :: NONE )
378- } else {
379- egui:: Button :: new ( job) . small ( ) . stroke ( egui:: Stroke :: NONE )
380- } ;
381-
382- let res = if let Some ( hover_str) = hover_str {
383- ui. add_enabled ( false , button) . on_disabled_hover_text ( hover_str)
384- } else {
385- ui. add_enabled ( false , button)
386- } ;
387-
388- if is_match && self . scroll_to_match {
389- res. scroll_to_me ( None ) ;
390- self . scroll_to_match = false ;
391- }
392- } ;
393-
394- ui. with_layout ( Layout :: right_to_left ( Align :: Center ) , |ui| {
395- match approval_status {
396- crate :: providers:: ApprovalStatus :: Verified => {
397- mk_searchable_modio_tag ( "Verified" , ui, Some ( egui:: Color32 :: LIGHT_GREEN ) , Some ( "Does not contain any gameplay affecting features or changes" ) ) ;
398- }
399- crate :: providers:: ApprovalStatus :: Approved => {
400- mk_searchable_modio_tag ( "Approved" , ui, Some ( egui:: Color32 :: LIGHT_BLUE ) , Some ( "Contains gameplay affecting features or changes" ) ) ;
401- }
402- crate :: providers:: ApprovalStatus :: Sandbox => {
403- mk_searchable_modio_tag ( "Sandbox" , ui, Some ( egui:: Color32 :: LIGHT_YELLOW ) , Some ( "Contains significant, possibly progression breaking, changes to gameplay" ) ) ;
404- }
405- }
406-
407- match required_status {
408- crate :: providers:: RequiredStatus :: RequiredByAll => {
409- mk_searchable_modio_tag ( "RequiredByAll" , ui, Some ( egui:: Color32 :: LIGHT_RED ) , Some ( "All lobby members must use this mod for it to work correctly!" ) ) ;
410- }
411- crate :: providers:: RequiredStatus :: Optional => {
412- mk_searchable_modio_tag ( "Optional" , ui, None , Some ( "Clients are not required to install this mod to function" ) ) ;
413- }
414- }
415-
416- if * qol {
417- mk_searchable_modio_tag ( "QoL" , ui, None , None ) ;
418- }
419- if * gameplay {
420- mk_searchable_modio_tag ( "Gameplay" , ui, None , None ) ;
421- }
422- if * audio {
423- mk_searchable_modio_tag ( "Audio" , ui, None , None ) ;
424- }
425- if * visual {
426- mk_searchable_modio_tag ( "Visual" , ui, None , None ) ;
427- }
428- if * framework {
429- mk_searchable_modio_tag ( "Framework" , ui, None , None ) ;
430- }
431- } ) ;
432- }
477+ ui. with_layout ( Layout :: right_to_left ( Align :: Center ) , |ui| {
478+ ui_mod_tags ( ctx, ui, info) ;
479+ } ) ;
433480 } else {
434481 if ui
435482 . button ( "📋" )
@@ -533,6 +580,8 @@ impl App {
533580 message:: ResolveMods :: send ( self , ui. ctx ( ) , add_deps, true ) ;
534581 }
535582
583+ self . scroll_to_match = ctx. scroll_to_match ;
584+
536585 if ctx. needs_save {
537586 self . state . mod_data . save ( ) . unwrap ( ) ;
538587 }
0 commit comments