icons
BIN
app-icon.png
Normal file
After Width: | Height: | Size: 247 KiB |
@ -21,7 +21,8 @@
|
||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
||||
"next": "^15.1.7",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
"react-dom": "^19.0.0",
|
||||
"tauri": "^0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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() {
|
||||
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;
|
||||
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",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "flate2"
|
||||
version = "1.0.35"
|
||||
@ -2428,25 +2447,6 @@ version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "nextauri"
|
||||
name = "file-tree"
|
||||
version = "0.0.0"
|
||||
description = "A Tauri App"
|
||||
description = "A application for determining what is using your storage."
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
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_dialog::init())
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
.expect("error while running tauri application!");
|
||||
}
|
||||
|