4
4
import { open , message } from " @tauri-apps/plugin-dialog" ;
5
5
import { onMount } from " svelte" ;
6
6
import { BaseDirectory , readTextFile , writeFile } from " @tauri-apps/plugin-fs" ;
7
+ import VirtualList from ' svelte-tiny-virtual-list' ;
7
8
8
9
interface FileStatus {
9
10
name: string ;
13
14
let addressesStatus: FileStatus | null = $state (null );
14
15
let filteredStatus: FileStatus | null = $state (null );
15
16
let recognizedPreview: string = $state (" " );
17
+ let elementIndex: number | null = $state (null );
18
+ let references: string [] = $state ([]);
16
19
17
20
async function updateRecognizedPreview() {
18
21
if (! loadedContent ) return ;
244
247
}
245
248
}
246
249
250
+ async function onClickFindReferencesHandler() {
251
+ if (elementIndex === null ) {
252
+ elementIndex = null ;
253
+ references = [];
254
+ await invoke (" clear_references" );
255
+ return ;
256
+ }
257
+
258
+ try {
259
+ references = await invoke (" get_all_references" , { elemIdx: elementIndex });
260
+
261
+ if (references .length === 0 ) {
262
+ await message (` No references found for element ${elementIndex } ` , { title: " Info" , kind: " info" });
263
+ }
264
+ } catch (error ) {
265
+ await message (
266
+ ` Failed to find references: ${error } ` ,
267
+ { title: " Error" , kind: " error" }
268
+ );
269
+ }
270
+ }
271
+
272
+ async function onClickReference(ref : string ) {
273
+ const [funcPart] = ref .split (' ###' );
274
+ const [name, id, findex] = funcPart .split (' @' );
275
+ const fullName = ` ${name }@${id }@${findex } ` ;
276
+
277
+ console .log (" findex: `" + findex + " `" );
278
+ await invoke (" set_selected_item" , {
279
+ appItem: {
280
+ index: findex ,
281
+ typ: " function"
282
+ }
283
+ });
284
+
285
+ console .log (" fullName: `" + fullName + " `" );
286
+ await invoke (" add_history_item" , {
287
+ item: {
288
+ name: fullName ,
289
+ typ: " function" ,
290
+ timestamp: new Date ().toISOString ()
291
+ }
292
+ });
293
+
294
+ console .log (" fullName: `" + fullName + " `" );
295
+ const ev = new CustomEvent (" bytecode-item-selected" , {
296
+ detail: {
297
+ name: fullName ,
298
+ type: " function"
299
+ }
300
+ });
301
+
302
+ window .dispatchEvent (ev );
303
+ }
304
+
305
+ function parseReference(ref : string ) {
306
+ const [funcPart, pos, op] = ref .split (' ###' );
307
+ return { funcPart , pos , op };
308
+ }
309
+
247
310
let loadedContent: string | null = null ;
248
311
312
+ async function loadSavedReferences() {
313
+ try {
314
+ const saved = await invoke <[number , string []] | null >(" get_saved_references" );
315
+ if (saved ) {
316
+ const [idx, refs] = saved ;
317
+ elementIndex = idx ;
318
+ references = refs ;
319
+ }
320
+ } catch (error ) {
321
+ console .error (" Failed to load saved references:" , error );
322
+ }
323
+ }
324
+
325
+ async function onClickSaveReferencesHandler() {
326
+ try {
327
+ if (references .length === 0 ) {
328
+ await message (" No references to save" , { title: " Error" , kind: " error" });
329
+ return ;
330
+ }
331
+
332
+ const result = await save ({
333
+ defaultPath: ` references_${elementIndex }.csv ` ,
334
+ title: " Save references" ,
335
+ filters: [{
336
+ name: " CSV Files" ,
337
+ extensions: [" csv" ]
338
+ },
339
+ {
340
+ name: " All Files" ,
341
+ extensions: [" *" ]
342
+ }]
343
+ });
344
+
345
+ if (result ) {
346
+ const csvContent = references .map (ref => {
347
+ const { funcPart, pos, op } = parseReference (ref );
348
+ return ` ${funcPart },${pos },${op } ` ;
349
+ }).join (' \n ' );
350
+
351
+ await writeFile (result , new TextEncoder ().encode (csvContent ));
352
+ }
353
+ } catch (error ) {
354
+ await message (
355
+ ` Failed to save references: ${error } ` ,
356
+ { title: " Error" , kind: " error" }
357
+ );
358
+ }
359
+ }
360
+
249
361
onMount (() => {
362
+ loadSavedReferences ();
250
363
});
251
364
</script >
252
365
315
428
{/if }
316
429
</div >
317
430
</section >
431
+ <section class =" card p-4 variant-soft-secondary space-y-2" >
432
+ <div class =" flex justify-between items-center" >
433
+ <h4 class =" h4" >Reference finder</h4 >
434
+ {#if references .length > 0 }
435
+ <button
436
+ type =" button"
437
+ class =" btn variant-soft-secondary"
438
+ onclick ={onClickSaveReferencesHandler }
439
+ >
440
+ Save to csv
441
+ </button >
442
+ {/if }
443
+ </div >
444
+ <div class =" flex flex-row space-x-2" >
445
+ <input
446
+ type =" number"
447
+ class =" input variant-form-material"
448
+ placeholder =" Element index"
449
+ bind:value ={elementIndex }
450
+ />
451
+ <button
452
+ type =" button"
453
+ class =" btn variant-soft-secondary"
454
+ onclick ={onClickFindReferencesHandler }
455
+ >
456
+ Find
457
+ </button >
458
+ </div >
459
+ {#if references .length > 0 }
460
+ <div class =" card p-2 variant-soft-secondary" >
461
+ <VirtualList
462
+ itemCount ={references .length }
463
+ itemSize ={35 }
464
+ height ={400 }
465
+ width =" 100%"
466
+ >
467
+ <div slot ="item" let:index let:style {style }>
468
+ {@const { funcPart , pos , op } = parseReference (references [index ])}
469
+ <button
470
+ class =" grid grid-cols-3 gap-4 p-2 hover:bg-secondary-700/20 w-full text-left"
471
+ onclick ={() => onClickReference (references [index ])}
472
+ >
473
+ <div class ="truncate" >{funcPart }</div >
474
+ <div >{pos }</div >
475
+ <div >{op }</div >
476
+ </button >
477
+ </div >
478
+ </VirtualList >
479
+ </div >
480
+ {/if }
481
+ </section >
318
482
</div >
319
483
</div >
0 commit comments