icons
BIN
app-icon.png
Normal file
After Width: | Height: | Size: 247 KiB |
@ -21,7 +21,8 @@
|
|||||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
"@tauri-apps/plugin-shell": "^2.2.0",
|
||||||
"next": "^15.1.7",
|
"next": "^15.1.7",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0",
|
||||||
|
"tauri": "^0.15.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2.2.7",
|
"@tauri-apps/cli": "^2.2.7",
|
||||||
|
78
src-next/PLAN.md
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Folder Explorer Tree View Implementation Plan
|
||||||
|
|
||||||
|
## 1. Project Setup
|
||||||
|
* The project is already a Next.js project.
|
||||||
|
|
||||||
|
## 2. Data Generation
|
||||||
|
* Create a JSON file (`data.json`) containing the fake data for the folder structure, subfolder counts, folder sizes, and folder paths.
|
||||||
|
* The data should be nested to simulate a realistic file system.
|
||||||
|
* The data should only contain folders.
|
||||||
|
* Example data structure:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Root Folder",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/",
|
||||||
|
"subfolders": 3,
|
||||||
|
"size": 1000000, // in bytes
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "Subfolder 1",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 1",
|
||||||
|
"subfolders": 2,
|
||||||
|
"size": 500000,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "Subfolder 1.1",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 1/Subfolder 1.1",
|
||||||
|
"subfolders": 0,
|
||||||
|
"size": 100000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Subfolder 1.2",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 1/Subfolder 1.2",
|
||||||
|
"subfolders": 0,
|
||||||
|
"size": 200000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Component Structure
|
||||||
|
* Create a `Tree` component (`components/Tree/index.tsx`) to render the entire tree view.
|
||||||
|
* Create a `TreeNode` component (`components/TreeNode/index.tsx`) to represent each folder node in the tree.
|
||||||
|
* This component will be responsible for rendering the folder name, badges, and progress bar.
|
||||||
|
|
||||||
|
## 4. Badge Implementation
|
||||||
|
* Within the `TreeNode` component, implement the subfolder count badge.
|
||||||
|
* Use a distinct, visually contrasting color for the badge.
|
||||||
|
* Display the badge next to the folder name.
|
||||||
|
|
||||||
|
## 5. Progress Bar Implementation
|
||||||
|
* Implement the storage space progress bar within the `TreeNode` component.
|
||||||
|
* Calculate the percentage of storage space occupied by the folder and its contents relative to the root folder's total storage capacity.
|
||||||
|
* Use a visually appealing progress bar style.
|
||||||
|
|
||||||
|
## 6. Responsiveness and Styling
|
||||||
|
* Use CSS Modules (`components/TreeNode/style.css`, `components/Tree/style.css`) to style the components.
|
||||||
|
* Ensure the interface is responsive and visually appealing on different screen sizes.
|
||||||
|
|
||||||
|
## 7. Interactivity
|
||||||
|
* Add interactivity to the tree view, such as expanding and collapsing folder nodes on click.
|
||||||
|
* Use state management (e.g., useState) to track the expanded/collapsed state of each node.
|
||||||
|
|
||||||
|
## 8. Performance Optimization
|
||||||
|
* Optimize the tree view for performance, especially when dealing with a large number of folders.
|
||||||
|
* Consider techniques like virtualization or lazy loading if necessary.
|
||||||
|
|
||||||
|
## 9. Integration
|
||||||
|
* Integrate the `Tree` component into the main `app/page.tsx` file.
|
||||||
|
* Pass the data from `data.json` to the `Tree` component.
|
@ -1,7 +1,34 @@
|
|||||||
import Home from 'containers/Home';
|
import React from 'react';
|
||||||
|
import Tree from 'components/Tree';
|
||||||
|
import rawData from '../data.json';
|
||||||
|
|
||||||
|
interface TreeNodeData {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
path: string;
|
||||||
|
subfolders: number;
|
||||||
|
size: number;
|
||||||
|
files: number;
|
||||||
|
children?: TreeNodeData[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const addFilesToData = (data: any): TreeNodeData[] => {
|
||||||
|
return data.map((node: any) => {
|
||||||
|
const files = 1; // Assuming each folder has 1 file
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
files: files,
|
||||||
|
children: node.children ? addFilesToData(node.children) : [],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = addFilesToData(rawData);
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
return (
|
return (
|
||||||
<Home />
|
<div style={{ width: '100vw', height: '100vh', backgroundColor: "#222" }}>
|
||||||
)
|
<Tree data={data} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
30
src-next/components/Tree/index.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import TreeNode from '../TreeNode';
|
||||||
|
|
||||||
|
interface TreeNodeData {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
path: string;
|
||||||
|
subfolders: number;
|
||||||
|
size: number;
|
||||||
|
files: number;
|
||||||
|
children?: TreeNodeData[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TreeProps {
|
||||||
|
data: TreeNodeData[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tree: React.FC<TreeProps> = ({ data }) => {
|
||||||
|
const rootSize = data[0].size;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="tree">
|
||||||
|
{data.map((node) => (
|
||||||
|
<TreeNode key={node.path} node={node} rootSize={rootSize} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tree;
|
54
src-next/components/TreeNode/index.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
interface TreeNodeData {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
path: string;
|
||||||
|
subfolders: number;
|
||||||
|
size: number;
|
||||||
|
files: number;
|
||||||
|
children?: TreeNodeData[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TreeNodeProps {
|
||||||
|
node: TreeNodeData;
|
||||||
|
rootSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TreeNode: React.FC<TreeNodeProps> = ({ node, rootSize }) => {
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
|
const toggleExpand = () => {
|
||||||
|
setIsExpanded(!isExpanded);
|
||||||
|
};
|
||||||
|
|
||||||
|
const percentage = (node.size / rootSize) * 100;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="treeNode">
|
||||||
|
<div className="nodeHeader" onClick={toggleExpand}>
|
||||||
|
<span className="nodeName">{node.name}</span>
|
||||||
|
<span className="subfolderBadge">Subfolders: {node.subfolders}</span>
|
||||||
|
<span className="fileBadge">Files: {node.files}</span>
|
||||||
|
</div>
|
||||||
|
<div className="progressBarContainer">
|
||||||
|
<div
|
||||||
|
className={`progressBar ${percentage > 70 ? 'red' : percentage > 40 ? 'yellow' : ''}`}
|
||||||
|
style={{ width: `${percentage}%` }}
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{isExpanded && node.children && (
|
||||||
|
<div className="children">
|
||||||
|
{node.children.map((child) => (
|
||||||
|
<TreeNode key={child.path} node={child} rootSize={rootSize} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TreeNode;
|
@ -23,3 +23,70 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
.tree {
|
||||||
|
font-family: sans-serif;
|
||||||
|
padding-left: 0px;
|
||||||
|
background-color: #222;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.treeNode {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodeName {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subfolderBadge {
|
||||||
|
background-color: #444;
|
||||||
|
color: #aaa;
|
||||||
|
padding: 2px 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileBadge {
|
||||||
|
background-color: #444;
|
||||||
|
color: #aaa;
|
||||||
|
margin-left: 5px;
|
||||||
|
padding: 2px 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressBarContainer {
|
||||||
|
height: 5px;
|
||||||
|
background-color: #555;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressBar {
|
||||||
|
height: 100%;
|
||||||
|
background-color: #1eff00;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.yellow {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.children {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
61
src-next/data.json
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Root Folder",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/",
|
||||||
|
"subfolders": 3,
|
||||||
|
"size": 1000000,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "Subfolder 1",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 1",
|
||||||
|
"subfolders": 2,
|
||||||
|
"size": 500000,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "Subfolder 1.1",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 1/Subfolder 1.1",
|
||||||
|
"subfolders": 0,
|
||||||
|
"size": 100000,
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Subfolder 1.2",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 1/Subfolder 1.2",
|
||||||
|
"subfolders": 0,
|
||||||
|
"size": 200000,
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Subfolder 2",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 2",
|
||||||
|
"subfolders": 0,
|
||||||
|
"size": 150000,
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Subfolder 3",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 3",
|
||||||
|
"subfolders": 1,
|
||||||
|
"size": 200000,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "Subfolder 3.1",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "/Subfolder 3/Subfolder 3.1",
|
||||||
|
"subfolders": 0,
|
||||||
|
"size": 50000,
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
38
src-tauri/Cargo.lock
generated
@ -1158,6 +1158,25 @@ dependencies = [
|
|||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "file-tree"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tauri",
|
||||||
|
"tauri-build",
|
||||||
|
"tauri-plugin-clipboard-manager",
|
||||||
|
"tauri-plugin-dialog",
|
||||||
|
"tauri-plugin-fs",
|
||||||
|
"tauri-plugin-global-shortcut",
|
||||||
|
"tauri-plugin-http",
|
||||||
|
"tauri-plugin-notification",
|
||||||
|
"tauri-plugin-os",
|
||||||
|
"tauri-plugin-process",
|
||||||
|
"tauri-plugin-shell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.35"
|
version = "1.0.35"
|
||||||
@ -2428,25 +2447,6 @@ version = "1.0.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nextauri"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"tauri",
|
|
||||||
"tauri-build",
|
|
||||||
"tauri-plugin-clipboard-manager",
|
|
||||||
"tauri-plugin-dialog",
|
|
||||||
"tauri-plugin-fs",
|
|
||||||
"tauri-plugin-global-shortcut",
|
|
||||||
"tauri-plugin-http",
|
|
||||||
"tauri-plugin-notification",
|
|
||||||
"tauri-plugin-os",
|
|
||||||
"tauri-plugin-process",
|
|
||||||
"tauri-plugin-shell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.29.0"
|
version = "0.29.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nextauri"
|
name = "file-tree"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
description = "A Tauri App"
|
description = "A application for determining what is using your storage."
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
license = ""
|
license = ""
|
||||||
repository = ""
|
repository = ""
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 974 B After Width: | Height: | Size: 2.4 KiB |
BIN
src-tauri/icons/64x64.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
src-tauri/icons/android/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src-tauri/icons/android/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 116 KiB |
BIN
src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 148 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@1x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@2x-1.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@2x.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-20x20@3x.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@1x.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@2x-1.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@2x.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
src-tauri/icons/ios/AppIcon-29x29@3x.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@1x.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@2x-1.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@2x.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src-tauri/icons/ios/AppIcon-40x40@3x.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src-tauri/icons/ios/AppIcon-512@2x.png
Normal file
After Width: | Height: | Size: 388 KiB |
BIN
src-tauri/icons/ios/AppIcon-60x60@2x.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src-tauri/icons/ios/AppIcon-60x60@3x.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
src-tauri/icons/ios/AppIcon-76x76@1x.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/ios/AppIcon-76x76@2x.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png
Normal file
After Width: | Height: | Size: 28 KiB |
@ -15,5 +15,5 @@ fn main() {
|
|||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application!");
|
||||||
}
|
}
|
||||||
|