@@ -247,144 +247,195 @@ public override async Task<int> ExecuteAsync(CommandContext context, SearchComma
247247
248248 private async Task RunInteractiveAsync ( )
249249 {
250+
250251 string cmd = null ;
251252
252253 do {
253- cmd = GetCommandPrompt ( ) ;
254-
255- if ( cmd == R2 . Chc_Exit ) {
256- continue ;
257- }
258254
259- var sr = GetEnginePrompt ( ) ;
260- var num = GetNumberPrompt ( sr ) ;
261- var res = sr . Results [ num ] ;
255+ var res = GetEnginePrompt ( ) ;
262256
263- if ( cmd == R2 . Chc_Open ) {
264- SearchClient . OpenResult ( res . Url ) ;
265- continue ;
266- }
257+ var ( sri , ui ) = GetUniPrompt ( res ) ;
267258
268- if ( cmd == R2 . Chc_Scan ) {
269- var run3 = await ShowImageScanResultsAsync ( res ) ;
259+ if ( sri is not null ) {
260+ cmd = GetCommandPrompt ( ) ;
270261
271- if ( ! run3 ) {
272- goto cont ;
262+ if ( cmd == R2 . Chc_Open ) {
263+ SearchClient . OpenResult ( sri . Url ) ;
264+ continue ;
273265 }
266+ else if ( cmd == R2 . Chc_Scan ) {
274267
275- var cmd2 = GetCommandPrompt ( ) ;
268+ var run3 = await ShowImageScanResultsAsync ( sri ) ;
276269
277- if ( cmd2 == R2 . Chc_Exit ) {
278- goto cont ;
270+ if ( run3 ) {
271+ continue ;
272+ }
279273 }
280274
281- if ( cmd2 == R2 . Chc_Calc ) {
275+ if ( cmd == R2 . Chc_Calc ) {
282276
283277 await AnsiConsole . Live ( m_table ) . StartAsync ( async ( f ) =>
284278 {
285279 // var ui2 = res.Uni[0];
286- for ( int i = 0 ; i < res . Uni . Count ; i ++ ) {
287- var uii = res . Uni [ i ] ;
288- var hashOk = uii . TryCalculateSimilarity ( Query . Source ) ;
289-
290- if ( hashOk ) {
291- var row = GetRow ( uii ) ;
292- m_table . Rows . Update ( row , 2 , new Text ( uii . Similarity . ToString ( ) ) ) ;
293- f . Refresh ( ) ;
280+ if ( ui is null ) {
281+ for ( int i = 0 ; i < sri . Uni . Count ; i ++ ) {
282+ var uii = sri . Uni [ i ] ;
283+ NewFunction ( uii , f ) ;
294284 }
295285
296-
297286 }
298- /*var ui = res.Uni[0];
299- var hashOk = ui.TryCalculateSimilarity(Query.Source);
300-
301- if (hashOk) {
302- var row = GetRow(ui);
303- m_table.Rows.Update(row, 2, new Text(res.Similarity.ToString()));
304- f.Refresh();
287+ else {
288+ NewFunction ( ui , f ) ;
289+ }
305290
306- }*/
307291 } ) ;
308292
309- // var row = dict[item];
310- // table2.Rows.Update(row, 2, new Text(item.Similarity.ToString()));
311293 continue ;
312- }
313294
295+ void NewFunction ( UniImage uii , LiveDisplayContext f )
296+ {
297+ var hashOk = uii . TryCalculateSimilarity ( Query . Source ) ;
314298
315- }
299+ if ( hashOk ) {
300+ var row = GetRow ( uii ) ;
301+ m_table . Rows . Update ( row , 2 , new Text ( uii . Similarity . ToString ( ) ) ) ;
302+ f . Refresh ( ) ;
303+ }
304+ }
316305
317- if ( cmd == R2 . Chc_Preview ) {
306+ continue ;
307+ }
318308
319- //todo
320- Stream str ;
309+ if ( cmd == R2 . Chc_Preview ) {
321310
322- if ( res . HasUni ) {
323- var uniIndex = GetUniPrompt ( res ) ;
324- var uni = res . Uni [ uniIndex ] ;
325- str = uni . Image . ToStream ( ) ;
326- }
327- else if ( res . Thumbnail != null ) {
328- using var thumbRes = await res . Thumbnail . GetAsync ( ) ;
329- str = await thumbRes . GetStreamAsync ( ) ;
311+ //todo
312+ Stream str ;
330313
331- // var exist = res.Uni.Any(u => u.ValueString == res.Thumbnail);
314+ if ( ui is not null ) {
315+ str = ui . Image . ToStream ( ) ;
316+ }
317+ else if ( sri . Thumbnail != null ) {
318+ // using var thumbRes = await sri.Thumbnail.GetAsync();
319+ // str = await thumbRes.GetStreamAsync();
320+ var th = await sri . LoadThumbnail ( ) ;
321+
322+ if ( th ) {
323+ ui = sri . Uni . Find ( f => f . ValueString == sri . Thumbnail ) ;
324+ str = ui . Image . ToStream ( ) ;
325+ }
326+ else {
327+ continue ;
328+ }
329+ // var exist = res.Uni.Any(u => u.ValueString == res.Thumbnail);
332330
333- }
334- else {
335- continue ;
336- }
331+ }
332+ else {
333+ continue ;
334+ }
337335
338336
339- var cip = new CacheItemPolicy ( )
340- {
341- AbsoluteExpiration = DateTimeOffset . Now + TimeSpan . FromMinutes ( 1 ) ,
342- RemovedCallback = arguments =>
337+ var cip = new CacheItemPolicy ( )
343338 {
344- switch ( arguments . RemovedReason ) {
339+ AbsoluteExpiration = DateTimeOffset . Now + TimeSpan . FromMinutes ( 1 ) ,
340+ RemovedCallback = arguments =>
341+ {
342+ switch ( arguments . RemovedReason ) {
345343
346- case CacheEntryRemovedReason . Removed :
347- break ;
344+ case CacheEntryRemovedReason . Removed :
345+ break ;
348346
349- case CacheEntryRemovedReason . Expired :
350- break ;
347+ case CacheEntryRemovedReason . Expired :
348+ break ;
351349
352- case CacheEntryRemovedReason . Evicted :
353- break ;
350+ case CacheEntryRemovedReason . Evicted :
351+ break ;
354352
355- case CacheEntryRemovedReason . ChangeMonitorChanged :
356- break ;
353+ case CacheEntryRemovedReason . ChangeMonitorChanged :
354+ break ;
357355
358- case CacheEntryRemovedReason . CacheSpecificEviction :
359- break ;
356+ case CacheEntryRemovedReason . CacheSpecificEviction :
357+ break ;
360358
361- default :
362- throw new ArgumentOutOfRangeException ( ) ;
359+ default :
360+ throw new ArgumentOutOfRangeException ( ) ;
361+ }
362+
363+ Debug . WriteLine ( $ "{ arguments . CacheItem } :: { arguments . RemovedReason } ") ;
364+ return ;
363365 }
366+ } ;
364367
365- Debug . WriteLine ( $ "{ arguments . CacheItem } :: { arguments . RemovedReason } ") ;
366- return ;
368+ // string key = sri.Url.ToString();
369+
370+ var o = m_cache . Get ( ui . ValueString ) ;
371+
372+ if ( o is not Stream ) {
373+ // Get the current console width (in characters)
374+ int consoleWidth = AnsiConsole . Console . Profile . Width ;
375+ int consoleHeight = AnsiConsole . Console . Profile . Height ;
376+
377+ int maxImageWidth = Math . Max ( 1 , consoleWidth - 2 ) ;
378+
379+
380+ m_cache . Set ( ui . ValueString , str , cip ) ;
367381 }
368- } ;
369382
370- string key = res . Url . ToString ( ) ;
383+ AnsiConsole . AlternateScreen ( ( ) =>
384+ {
385+ var ci = new CanvasImage ( str ) ;
386+
387+ //
371388
372- var o = m_cache . Get ( key ) ;
389+ // AnsiConsole.Write($"{ci.Width}x{ci.Height}" );
373390
374- if ( o is not CanvasImage ci ) {
375- ci = new CanvasImage ( str ) ;
376- m_cache . Set ( key , ci , cip ) ;
377- }
391+ while ( true ) {
392+ AnsiConsole . Clear ( ) ;
393+ AnsiConsole . Write ( ci ) ;
378394
379- AnsiConsole . AlternateScreen ( ( ) =>
380- {
381- //
382- AnsiConsole . Clear ( ) ;
395+ var k = AnsiConsole . Console . Input . ReadKey ( true ) ;
396+
397+ if ( k . HasValue ) {
398+ int mw = 0 , pw = 0 ;
399+
400+ switch ( k . Value . Key ) {
401+ case ConsoleKey . DownArrow :
402+ pw = - 1 ;
403+ break ;
383404
384- // AnsiConsole.Write($"{ci.Width}x{ci.Height}");
385- AnsiConsole . Write ( ci ) ;
386- Console . ReadKey ( ) ;
387- } ) ;
405+ case ConsoleKey . LeftArrow :
406+ mw = - 1 ;
407+ break ;
408+
409+ case ConsoleKey . UpArrow :
410+ pw = 1 ;
411+ break ;
412+
413+ case ConsoleKey . RightArrow :
414+ mw = 1 ;
415+ break ;
416+
417+ case ConsoleKey . Escape :
418+ return ;
419+ }
420+
421+
422+ ci . PixelWidth = Math . Clamp ( ci . PixelWidth + pw , 0 , ci . Width ) ;
423+
424+ ci . MaxWidth ??= ci . Width ;
425+
426+ // if (ci.MaxWidth.HasValue) { }
427+ ci . MaxWidth = Math . Clamp ( ci . MaxWidth . Value + mw , 0 , AnsiConsole . Profile . Width ) ;
428+ }
429+ AnsiConsole . WriteLine ( $ "{ ci . MaxWidth } / { ci . PixelWidth } ") ;
430+
431+
432+ }
433+
434+ return ;
435+ } ) ;
436+ }
437+
438+ if ( cmd == R2 . Chc_Download ) { }
388439 }
389440
390441 cont :
@@ -665,6 +716,54 @@ private int GetUniPrompt(SearchResultItem res)
665716 return AnsiConsole . Prompt ( Prm_Num ) ;
666717 }
667718
719+
720+ private ( SearchResultItem , UniImage ) GetUniPrompt ( SearchResult res )
721+ {
722+ ( SearchResultItem , UniImage ) Converter ( string str )
723+ {
724+ var spl = str . Split ( '.' ) ;
725+ int i ;
726+
727+ SearchResultItem sri = null ;
728+ UniImage ui = UniImage . Null ;
729+
730+ if ( Int32 . TryParse ( spl [ 0 ] , out i ) && ( i < res . Results . Count && i >= 0 ) ) {
731+
732+ sri = res . Results [ i ] ;
733+
734+ if ( spl . Length == 2 ) {
735+
736+ if ( Int32 . TryParse ( spl [ 1 ] , out var j ) && ( j < sri . Uni . Count && j >= 0 ) ) {
737+ ui = sri . Uni [ j ] ;
738+
739+ }
740+ }
741+ else { }
742+
743+ }
744+ else { }
745+
746+ return ( sri , ui ) ;
747+ }
748+
749+ ( SearchResultItem , UniImage ) ret ;
750+
751+ Prm_Num2 . Validator = str =>
752+ {
753+ ret = Converter ( str ) ;
754+
755+ if ( ret is ( null , null ) ) {
756+ return ValidationResult . Error ( ) ;
757+ }
758+
759+ return ValidationResult . Success ( ) ;
760+ } ;
761+
762+
763+ var val = AnsiConsole . Prompt ( Prm_Num2 ) ;
764+ return Converter ( val ) ;
765+ }
766+
668767 private int GetNumberPrompt ( SearchResult result )
669768 {
670769 Prm_Num . Validator = i =>
@@ -883,7 +982,7 @@ public void Dispose()
883982 AllowEmpty = false ,
884983 } ;
885984
886- private static readonly TextPrompt < string > Prm_Num2 = new ( Markup . Escape ( "[#]" ) )
985+ private static readonly TextPrompt < string > Prm_Num2 = new ( Markup . Escape ( "[#.# ]" ) )
887986 {
888987 ShowChoices = false ,
889988 ShowDefaultValue = false ,
0 commit comments