zeroed-some/bashamole / 06bc5c2

Browse files

quirked

Authored by espadonne
SHA
06bc5c2b920dc5fceedfff2aa8f76e040e2aaf4d
Parents
0454653
Tree
88c87a3

12 changed files

StatusFile+-
A frontend/public/icons/config.svg 13 0
A frontend/public/icons/database.svg 5 0
A frontend/public/icons/desktop.svg 6 0
A frontend/public/icons/document.svg 6 0
A frontend/public/icons/download.svg 5 0
A frontend/public/icons/folder.svg 4 0
A frontend/public/icons/home.svg 0 0
A frontend/public/icons/package.svg 5 0
A frontend/public/icons/picture.svg 5 0
A frontend/public/icons/terminal.svg 4 0
A frontend/public/icons/trash.svg 7 0
M frontend/src/components/TreeVisualizer.tsx 24 307
frontend/public/icons/config.svgadded
@@ -0,0 +1,13 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <circle cx="12" cy="12" r="8" fill="#8B5CF6" stroke="#6D28D9" stroke-width="1.5"/>
3
+  <circle cx="12" cy="12" r="4" fill="#DDD6FE"/>
4
+  <!-- Gear teeth -->
5
+  <line x1="12" y1="4" x2="12" y2="1" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
6
+  <line x1="18.66" y1="7.34" x2="20.78" y2="5.22" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
7
+  <line x1="20" y1="12" x2="23" y2="12" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
8
+  <line x1="18.66" y1="16.66" x2="20.78" y2="18.78" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
9
+  <line x1="12" y1="20" x2="12" y2="23" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
10
+  <line x1="5.34" y1="16.66" x2="3.22" y2="18.78" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
11
+  <line x1="4" y1="12" x2="1" y2="12" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
12
+  <line x1="5.34" y1="7.34" x2="3.22" y2="5.22" stroke="#6D28D9" stroke-width="2" stroke-linecap="round"/>
13
+</svg>
frontend/public/icons/database.svgadded
@@ -0,0 +1,5 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <ellipse cx="12" cy="8" rx="8" ry="3" fill="#F59E0B" stroke="#D97706" stroke-width="1.5"/>
3
+  <rect x="4" y="8" width="16" height="8" fill="#F59E0B"/>
4
+  <ellipse cx="12" cy="16" rx="8" ry="3" fill="#FBBF24" stroke="#D97706" stroke-width="1.5"/>
5
+</svg>
frontend/public/icons/desktop.svgadded
@@ -0,0 +1,6 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <rect x="3" y="5" width="18" height="12" rx="1" fill="#1F2937" stroke="#111827" stroke-width="1.5"/>
3
+  <rect x="5" y="7" width="14" height="8" fill="#60A5FA"/>
4
+  <rect x="10" y="17" width="4" height="3" fill="#374151"/>
5
+  <rect x="7" y="20" width="10" height="2" rx="1" fill="#374151"/>
6
+</svg>
frontend/public/icons/document.svgadded
@@ -0,0 +1,6 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <rect x="6" y="4" width="12" height="16" rx="1" fill="#E5E7EB" stroke="#6B7280" stroke-width="1.5"/>
3
+  <path d="M12 4 L18 4 L18 10" fill="#D1D5DB" stroke="#6B7280" stroke-width="1.5"/>
4
+  <line x1="9" y1="12" x2="15" y2="12" stroke="#6B7280" stroke-width="1"/>
5
+  <line x1="9" y1="15" x2="15" y2="15" stroke="#6B7280" stroke-width="1"/>
6
+</svg>
frontend/public/icons/download.svgadded
@@ -0,0 +1,5 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <rect x="4" y="14" width="16" height="3" fill="#10B981" stroke="#059669" stroke-width="1"/>
3
+  <rect x="11" y="4" width="2" height="10" fill="#10B981"/>
4
+  <path d="M8 10 L12 14 L16 10" fill="none" stroke="#10B981" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+</svg>
frontend/public/icons/folder.svgadded
@@ -0,0 +1,4 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <path d="M4 8 L4 18 L20 18 L20 10 L18 8 Z" fill="#3B82F6" stroke="#2563EB" stroke-width="1.5"/>
3
+  <path d="M4 8 L10 8 L12 10 L18 10" fill="none" stroke="#2563EB" stroke-width="1.5"/>
4
+</svg>
frontend/public/icons/home.svgadded
frontend/public/icons/package.svgadded
@@ -0,0 +1,5 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <path d="M4 10 L12 6 L20 10 L20 18 L12 22 L4 18 Z" fill="#10B981" stroke="#059669" stroke-width="1.5"/>
3
+  <path d="M4 10 L12 14 L20 10" fill="none" stroke="#059669" stroke-width="1.5"/>
4
+  <line x1="12" y1="14" x2="12" y2="22" stroke="#059669" stroke-width="1.5"/>
5
+</svg>
frontend/public/icons/picture.svgadded
@@ -0,0 +1,5 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <rect x="4" y="6" width="16" height="12" rx="1" fill="#DBEAFE" stroke="#3B82F6" stroke-width="1.5"/>
3
+  <path d="M4 18 L10 10 L14 14 L20 8 L20 18 Z" fill="#60A5FA"/>
4
+  <circle cx="15" cy="10" r="2" fill="#FDE047"/>
5
+</svg>
frontend/public/icons/terminal.svgadded
@@ -0,0 +1,4 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <rect x="4" y="6" width="16" height="12" rx="2" fill="#1F2937" stroke="#374151" stroke-width="1.5"/>
3
+  <text x="12" y="14" text-anchor="middle" fill="#10B981" font-family="monospace" font-size="10px" font-weight="bold">&gt;_</text>
4
+</svg>
frontend/public/icons/trash.svgadded
@@ -0,0 +1,7 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
2
+  <rect x="4" y="8" width="16" height="14" rx="1" fill="#6B7280" stroke="#374151" stroke-width="1.5"/>
3
+  <rect x="2" y="6" width="20" height="3" fill="#374151"/>
4
+  <line x1="8" y1="12" x2="8" y2="18" stroke="#9CA3AF" stroke-width="1"/>
5
+  <line x1="12" y1="12" x2="12" y2="18" stroke="#9CA3AF" stroke-width="1"/>
6
+  <line x1="16" y1="12" x2="16" y2="18" stroke="#9CA3AF" stroke-width="1"/>
7
+</svg>
frontend/src/components/TreeVisualizer.tsxmodified
@@ -583,317 +583,34 @@ const TreeVisualizer: React.FC<TreeVisualizerProps> = ({
583583
         .attr('height', bbox.height + LABEL_CONFIG.background.padding.y * 2);
584584
     });
585585
 
586
-    // Add minimal SVG icons for special directories
586
+    // Add icon images for special directories
587587
     node.each(function(d) {
588588
       const nodeEl = d3.select(this);
589
-      const iconSize = 24;
590
-      const iconOffset = -iconSize / 2;
589
+      let iconPath = null;
591590
       
592
-      // Create icon group
593
-      const iconGroup = nodeEl.append('g')
594
-        .attr('class', 'directory-icon')
595
-        .style('pointer-events', 'none');
591
+      // Map paths to icon files
592
+      if (d.data.path === '/home') iconPath = '/icons/home.svg';
593
+      else if (d.data.path === '/tmp') iconPath = '/icons/trash.svg';
594
+      else if (d.data.path === '/etc') iconPath = '/icons/config.svg';
595
+      else if (d.data.path === '/bin' || d.data.path === '/sbin') iconPath = '/icons/terminal.svg';
596
+      else if (d.data.path === '/var') iconPath = '/icons/database.svg';
597
+      else if (d.data.path === '/usr') iconPath = '/icons/folder.svg';
598
+      else if (d.data.path === '/opt') iconPath = '/icons/package.svg';
599
+      else if (d.data.path.includes('Documents')) iconPath = '/icons/document.svg';
600
+      else if (d.data.path.includes('Pictures')) iconPath = '/icons/picture.svg';
601
+      else if (d.data.path.includes('Downloads')) iconPath = '/icons/download.svg';
602
+      else if (d.data.path.includes('Desktop')) iconPath = '/icons/desktop.svg';
596603
       
597
-      if (d.data.path === '/home') {
598
-        // Simple house icon
599
-        iconGroup.append('path')
600
-          .attr('d', `M ${iconOffset} 5 L 0 ${iconOffset + 5} L ${iconSize/2} 5 L ${iconSize/2} ${iconSize/2 - 2} L ${iconOffset} ${iconSize/2 - 2} Z`)
601
-          .attr('fill', '#F59E0B')
602
-          .attr('stroke', '#92400E')
603
-          .attr('stroke-width', 1.5);
604
-        
605
-        iconGroup.append('rect')
606
-          .attr('x', iconOffset + 8)
607
-          .attr('y', 5)
608
-          .attr('width', 8)
609
-          .attr('height', 10)
610
-          .attr('fill', '#92400E');
611
-          
612
-      } else if (d.data.path === '/tmp') {
613
-        // Simple trash can icon
614
-        iconGroup.append('rect')
615
-          .attr('x', iconOffset + 4)
616
-          .attr('y', iconOffset + 8)
617
-          .attr('width', 16)
618
-          .attr('height', 14)
619
-          .attr('rx', 1)
620
-          .attr('fill', '#6B7280')
621
-          .attr('stroke', '#374151')
622
-          .attr('stroke-width', 1.5);
623
-        
624
-        iconGroup.append('rect')
625
-          .attr('x', iconOffset + 2)
626
-          .attr('y', iconOffset + 6)
627
-          .attr('width', 20)
628
-          .attr('height', 3)
629
-          .attr('fill', '#374151');
630
-        
631
-        iconGroup.append('line')
632
-          .attr('x1', iconOffset + 8)
633
-          .attr('y1', iconOffset + 12)
634
-          .attr('x2', iconOffset + 8)
635
-          .attr('y2', iconOffset + 18)
636
-          .attr('stroke', '#9CA3AF')
637
-          .attr('stroke-width', 1);
638
-        
639
-        iconGroup.append('line')
640
-          .attr('x1', iconOffset + 12)
641
-          .attr('y1', iconOffset + 12)
642
-          .attr('x2', iconOffset + 12)
643
-          .attr('y2', iconOffset + 18)
644
-          .attr('stroke', '#9CA3AF')
645
-          .attr('stroke-width', 1);
646
-        
647
-        iconGroup.append('line')
648
-          .attr('x1', iconOffset + 16)
649
-          .attr('y1', iconOffset + 12)
650
-          .attr('x2', iconOffset + 16)
651
-          .attr('y2', iconOffset + 18)
652
-          .attr('stroke', '#9CA3AF')
653
-          .attr('stroke-width', 1);
654
-          
655
-      } else if (d.data.path === '/etc') {
656
-        // Simple gear/config icon
657
-        iconGroup.append('circle')
658
-          .attr('cx', iconOffset + 12)
659
-          .attr('cy', iconOffset + 12)
660
-          .attr('r', 8)
661
-          .attr('fill', '#8B5CF6')
662
-          .attr('stroke', '#6D28D9')
663
-          .attr('stroke-width', 1.5);
664
-        
665
-        iconGroup.append('circle')
666
-          .attr('cx', iconOffset + 12)
667
-          .attr('cy', iconOffset + 12)
668
-          .attr('r', 4)
669
-          .attr('fill', '#DDD6FE');
670
-        
671
-        // Gear teeth
672
-        for (let i = 0; i < 8; i++) {
673
-          const angle = (i * Math.PI * 2) / 8;
674
-          const x1 = iconOffset + 12 + Math.cos(angle) * 6;
675
-          const y1 = iconOffset + 12 + Math.sin(angle) * 6;
676
-          const x2 = iconOffset + 12 + Math.cos(angle) * 9;
677
-          const y2 = iconOffset + 12 + Math.sin(angle) * 9;
678
-          
679
-          iconGroup.append('line')
680
-            .attr('x1', x1)
681
-            .attr('y1', y1)
682
-            .attr('x2', x2)
683
-            .attr('y2', y2)
684
-            .attr('stroke', '#6D28D9')
685
-            .attr('stroke-width', 2)
686
-            .attr('stroke-linecap', 'round');
687
-        }
688
-        
689
-      } else if (d.data.path === '/bin' || d.data.path === '/sbin') {
690
-        // Simple terminal/binary icon
691
-        iconGroup.append('rect')
692
-          .attr('x', iconOffset + 4)
693
-          .attr('y', iconOffset + 6)
694
-          .attr('width', 16)
695
-          .attr('height', 12)
696
-          .attr('rx', 2)
697
-          .attr('fill', '#1F2937')
698
-          .attr('stroke', '#374151')
699
-          .attr('stroke-width', 1.5);
700
-        
701
-        iconGroup.append('text')
702
-          .attr('x', iconOffset + 12)
703
-          .attr('y', iconOffset + 14)
704
-          .attr('text-anchor', 'middle')
705
-          .attr('fill', '#10B981')
706
-          .attr('font-family', 'monospace')
707
-          .attr('font-size', '10px')
708
-          .attr('font-weight', 'bold')
709
-          .text('>_');
710
-          
711
-      } else if (d.data.path === '/var') {
712
-        // Simple database/variable icon
713
-        iconGroup.append('ellipse')
714
-          .attr('cx', iconOffset + 12)
715
-          .attr('cy', iconOffset + 8)
716
-          .attr('rx', 8)
717
-          .attr('ry', 3)
718
-          .attr('fill', '#F59E0B')
719
-          .attr('stroke', '#D97706')
720
-          .attr('stroke-width', 1.5);
721
-        
722
-        iconGroup.append('rect')
723
-          .attr('x', iconOffset + 4)
724
-          .attr('y', iconOffset + 8)
725
-          .attr('width', 16)
726
-          .attr('height', 8)
727
-          .attr('fill', '#F59E0B');
728
-        
729
-        iconGroup.append('ellipse')
730
-          .attr('cx', iconOffset + 12)
731
-          .attr('cy', iconOffset + 16)
732
-          .attr('rx', 8)
733
-          .attr('ry', 3)
734
-          .attr('fill', '#FBBF24')
735
-          .attr('stroke', '#D97706')
736
-          .attr('stroke-width', 1.5);
737
-          
738
-      } else if (d.data.path === '/usr') {
739
-        // Simple user/folder icon
740
-        iconGroup.append('path')
741
-          .attr('d', `M ${iconOffset + 4} ${iconOffset + 8} L ${iconOffset + 4} ${iconOffset + 18} L ${iconOffset + 20} ${iconOffset + 18} L ${iconOffset + 20} ${iconOffset + 10} L ${iconOffset + 18} ${iconOffset + 8} Z`)
742
-          .attr('fill', '#3B82F6')
743
-          .attr('stroke', '#2563EB')
744
-          .attr('stroke-width', 1.5);
745
-        
746
-        iconGroup.append('path')
747
-          .attr('d', `M ${iconOffset + 4} ${iconOffset + 8} L ${iconOffset + 10} ${iconOffset + 8} L ${iconOffset + 12} ${iconOffset + 10} L ${iconOffset + 18} ${iconOffset + 10}`)
748
-          .attr('fill', 'none')
749
-          .attr('stroke', '#2563EB')
750
-          .attr('stroke-width', 1.5);
751
-          
752
-      } else if (d.data.path === '/opt') {
753
-        // Simple package/box icon
754
-        iconGroup.append('path')
755
-          .attr('d', `M ${iconOffset + 4} ${iconOffset + 10} L ${iconOffset + 12} ${iconOffset + 6} L ${iconOffset + 20} ${iconOffset + 10} L ${iconOffset + 20} ${iconOffset + 18} L ${iconOffset + 12} ${iconOffset + 22} L ${iconOffset + 4} ${iconOffset + 18} Z`)
756
-          .attr('fill', '#10B981')
757
-          .attr('stroke', '#059669')
758
-          .attr('stroke-width', 1.5);
759
-        
760
-        iconGroup.append('path')
761
-          .attr('d', `M ${iconOffset + 4} ${iconOffset + 10} L ${iconOffset + 12} ${iconOffset + 14} L ${iconOffset + 20} ${iconOffset + 10}`)
762
-          .attr('fill', 'none')
763
-          .attr('stroke', '#059669')
764
-          .attr('stroke-width', 1.5);
765
-        
766
-        iconGroup.append('line')
767
-          .attr('x1', iconOffset + 12)
768
-          .attr('y1', iconOffset + 14)
769
-          .attr('x2', iconOffset + 12)
770
-          .attr('y2', iconOffset + 22)
771
-          .attr('stroke', '#059669')
772
-          .attr('stroke-width', 1.5);
773
-          
774
-      } else if (d.data.path.includes('Documents')) {
775
-        // Simple document icon
776
-        iconGroup.append('rect')
777
-          .attr('x', iconOffset + 6)
778
-          .attr('y', iconOffset + 4)
779
-          .attr('width', 12)
780
-          .attr('height', 16)
781
-          .attr('rx', 1)
782
-          .attr('fill', '#E5E7EB')
783
-          .attr('stroke', '#6B7280')
784
-          .attr('stroke-width', 1.5);
785
-        
786
-        iconGroup.append('path')
787
-          .attr('d', `M ${iconOffset + 12} ${iconOffset + 4} L ${iconOffset + 18} ${iconOffset + 4} L ${iconOffset + 18} ${iconOffset + 10}`)
788
-          .attr('fill', '#D1D5DB')
789
-          .attr('stroke', '#6B7280')
790
-          .attr('stroke-width', 1.5);
791
-        
792
-        // Text lines
793
-        iconGroup.append('line')
794
-          .attr('x1', iconOffset + 9)
795
-          .attr('y1', iconOffset + 12)
796
-          .attr('x2', iconOffset + 15)
797
-          .attr('y2', iconOffset + 12)
798
-          .attr('stroke', '#6B7280')
799
-          .attr('stroke-width', 1);
800
-        
801
-        iconGroup.append('line')
802
-          .attr('x1', iconOffset + 9)
803
-          .attr('y1', iconOffset + 15)
804
-          .attr('x2', iconOffset + 15)
805
-          .attr('y2', iconOffset + 15)
806
-          .attr('stroke', '#6B7280')
807
-          .attr('stroke-width', 1);
808
-          
809
-      } else if (d.data.path.includes('Pictures')) {
810
-        // Simple picture frame icon
811
-        iconGroup.append('rect')
812
-          .attr('x', iconOffset + 4)
813
-          .attr('y', iconOffset + 6)
814
-          .attr('width', 16)
815
-          .attr('height', 12)
816
-          .attr('rx', 1)
817
-          .attr('fill', '#DBEAFE')
818
-          .attr('stroke', '#3B82F6')
819
-          .attr('stroke-width', 1.5);
820
-        
821
-        // Mountain
822
-        iconGroup.append('path')
823
-          .attr('d', `M ${iconOffset + 4} ${iconOffset + 18} L ${iconOffset + 10} ${iconOffset + 10} L ${iconOffset + 14} ${iconOffset + 14} L ${iconOffset + 20} ${iconOffset + 8} L ${iconOffset + 20} ${iconOffset + 18} Z`)
824
-          .attr('fill', '#60A5FA');
825
-        
826
-        // Sun
827
-        iconGroup.append('circle')
828
-          .attr('cx', iconOffset + 15)
829
-          .attr('cy', iconOffset + 10)
830
-          .attr('r', 2)
831
-          .attr('fill', '#FDE047');
832
-          
833
-      } else if (d.data.path.includes('Downloads')) {
834
-        // Simple download arrow icon
835
-        iconGroup.append('rect')
836
-          .attr('x', iconOffset + 4)
837
-          .attr('y', iconOffset + 14)
838
-          .attr('width', 16)
839
-          .attr('height', 3)
840
-          .attr('fill', '#10B981')
841
-          .attr('stroke', '#059669')
842
-          .attr('stroke-width', 1);
843
-        
844
-        iconGroup.append('rect')
845
-          .attr('x', iconOffset + 11)
846
-          .attr('y', iconOffset + 4)
847
-          .attr('width', 2)
848
-          .attr('height', 10)
849
-          .attr('fill', '#10B981');
850
-        
851
-        iconGroup.append('path')
852
-          .attr('d', `M ${iconOffset + 8} ${iconOffset + 10} L ${iconOffset + 12} ${iconOffset + 14} L ${iconOffset + 16} ${iconOffset + 10}`)
853
-          .attr('fill', 'none')
854
-          .attr('stroke', '#10B981')
855
-          .attr('stroke-width', 2)
856
-          .attr('stroke-linecap', 'round')
857
-          .attr('stroke-linejoin', 'round');
858
-          
859
-      } else if (d.data.path.includes('Desktop')) {
860
-        // Simple monitor icon
861
-        iconGroup.append('rect')
862
-          .attr('x', iconOffset + 3)
863
-          .attr('y', iconOffset + 5)
864
-          .attr('width', 18)
865
-          .attr('height', 12)
866
-          .attr('rx', 1)
867
-          .attr('fill', '#1F2937')
868
-          .attr('stroke', '#111827')
869
-          .attr('stroke-width', 1.5);
870
-        
871
-        iconGroup.append('rect')
872
-          .attr('x', iconOffset + 5)
873
-          .attr('y', iconOffset + 7)
874
-          .attr('width', 14)
875
-          .attr('height', 8)
876
-          .attr('fill', '#60A5FA');
877
-        
878
-        iconGroup.append('rect')
879
-          .attr('x', iconOffset + 10)
880
-          .attr('y', iconOffset + 17)
881
-          .attr('width', 4)
882
-          .attr('height', 3)
883
-          .attr('fill', '#374151');
884
-        
885
-        iconGroup.append('rect')
886
-          .attr('x', iconOffset + 7)
887
-          .attr('y', iconOffset + 20)
888
-          .attr('width', 10)
889
-          .attr('height', 2)
890
-          .attr('rx', 1)
891
-          .attr('fill', '#374151');
892
-      }
893
-      
894
-      // Add subtle animation to icons
895
-      if (iconGroup.node()?.hasChildNodes()) {
896
-        iconGroup
604
+      if (iconPath) {
605
+        const iconSize = 24;
606
+        nodeEl.append('image')
607
+          .attr('class', 'directory-icon')
608
+          .attr('xlink:href', iconPath)
609
+          .attr('width', iconSize)
610
+          .attr('height', iconSize)
611
+          .attr('x', -iconSize / 2)
612
+          .attr('y', -iconSize / 2)
613
+          .style('pointer-events', 'none')
897614
           .style('opacity', 0.8)
898615
           .on('mouseover', function() {
899616
             d3.select(this)