# File Tree Architecture

## Overview

File Tree是MarkBase的核心模組，提供檔案樹管理功能。

**Location:** `src/filetree/`

**Total Lines:** 1234行

---

## Module Structure

```
src/filetree/
├── mod.rs        (553行) -核心CRUD操作
├── convert.rs    (253行) -檔案轉換功能
├── mode.rs       (43行)  - DisplayMode trait定義
├── node.rs       (82行)  -節點資料結構
└── modes/
    ├── tree.rs   (57行)  -樹狀顯示模式
    ├── list.rs   (87行)  -列表顯示模式
    ├── grid_sm.rs (72行) -小格狀顯示模式
    ├── grid_lg.rs (83行) -大格狀顯示模式
    └── mod.rs    (4行)   -模式匯出
```

---

## Database Design

### SQLite Tables

**Location:** `data/users/<user_id>.sqlite`

|Table |Purpose |
|------|--------|
| file_registry |檔案註冊資訊 |
| file_nodes |檔案樹節點 |
| file_locations |檔案位置記錄 |

### file_nodes Schema

```sql
CREATE TABLE file_nodes (
    node_id TEXT PRIMARY KEY,
    label TEXT NOT NULL,
    aliases_json TEXT NOT NULL DEFAULT '{}',
    file_uuid TEXT,
    sha256 TEXT,
    parent_id TEXT,
    children_json TEXT NOT NULL DEFAULT '[]',
    node_type TEXT NOT NULL DEFAULT 'folder',
    icon TEXT,
    color TEXT,
    bg_color TEXT,
    file_size INTEGER,
    registered_at TEXT,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    sort_order INTEGER NOT NULL DEFAULT 0
);
```

### Node Types

- **folder** -資料夾節點（可包含子節點）
- **file** -檔案節點（指向實體檔案）

---

## Public API（13 Functions）

### CRUD Operations（mod.rs）

|Function |Location |Description |
|----------|----------|-------------|
| user_db_path | 58 |取得資料庫路徑 |
| init_user_db | 62 |初始化資料庫 |
| open_user_db | 74 |開啟資料庫連接 |
| load | 79 |載入檔案樹 |
| insert_node | 120 |插入節點 |
| update_node | 149 |更新節點屬性 |
| update_node_alias | 187 |更新多語言別名 |
| delete_node | 214 |刪除節點 |
| move_node | 220 |移動節點位置 |
| build_tree | 240 |建立樹狀結構 |

### Node Creation（node.rs）

|Function |Location |Description |
|----------|----------|-------------|
| new_folder | 27 |建立資料夾節點 |
| new_file_node | 300 |建立檔案節點 |

### Utilities

|Function |Location |Description |
|----------|----------|-------------|
| add_location | 346 |新增檔案位置 |
| get_file_info | 359 |取得檔案資訊 |

---

## REST API（7 Routes）

### Endpoints

|Route |Method |Function |server.rs |
|------|--------|----------|-----------|
| `/api/v2/tree/:user_id` | GET | get_tree | 61 |
| `/api/v2/tree/:user_id` | DELETE | delete_all_nodes | 64 |
| `/api/v2/tree/:user_id/node` | POST | create_node | 62 |
| `/api/v2/tree/:user_id/node/:node_id` | PUT | update_node | 63 |
| `/api/v2/tree/:user_id/node/:node_id` | DELETE | delete_node | 63 |
| `/api/v2/tree/:user_id/node/:node_id/move` | PUT | move_node | 71 |
| `/api/v2/tree/:user_id/node/:node_id/alias` | PATCH | update_alias | 72 |
| `/api/v2/tree/:user_id/restore` | POST | restore_tree | 65 |

### Query Parameters

- `mode` -顯示模式（tree, list, grid_sm, grid_lg）

### Examples

```bash
#取得檔案樹（樹狀顯示）
curl http://localhost:11438/api/v2/tree/demo?mode=tree

#取得檔案樹（列表顯示）
curl http://localhost:11438/api/v2/tree/demo?mode=list

#建立節點
curl -X POST http://localhost:11438/api/v2/tree/demo/node \
  -H "Content-Type: application/json" \
  -d '{"label":"NewFolder", "node_type":"folder"}'

#更新別名
curl -X PATCH http://localhost:11438/api/v2/tree/demo/node/<node_id>/alias \
  -H "Content-Type: application/json" \
  -d '{"lang":"zh_tw", "value":"新資料夾"}'
```

---

## DisplayMode Trait

### Definition（mode.rs:19）

```rust
pub trait DisplayMode: Send + Sync {
    fn name(&self) -> &'static str;
    fn render(&self, tree: &FileTree) -> Value;
    fn sort_options(&self) -> Vec<SortOption>;
    fn filter_options(&self) -> Vec<FilterOption>;
}
```

### Implementations

|Mode |File |Purpose |
|------|------|---------|
| Tree | modes/tree.rs |層級樹狀結構顯示 |
| List | modes/list.rs |簡潔列表顯示 |
| GridSm | modes/grid_sm.rs |緊湊格狀顯示 |
| GridLg | modes/grid_lg.rs |寬鬆格狀顯示 |

### Usage

```rust
//取得顯示模式
let mode = filetree::mode::get_mode("tree");

//渲染檔案樹
let rendered = mode.render(&tree);

//取得排序選項
let sort_options = mode.sort_options();

//取得過濾選項
let filter_options = mode.filter_options();
```

---

## File Conversion（convert.rs）

### Supported Formats

|Tool |Formats |
|------|---------|
| textutil（macOS） | doc, docx, rtf |
| macOS Tools | pages, key, numbers |
| soffice/qlmanage | pptx, ppt, xlsx, xls, odt, epub |

### Functions

- `is_document_ext(ext)` - 檢查是否為文檔格式
- `is_textutil_ext(ext)` - 檢查是否為textutil支援格式
- `is_apple_format_ext(ext)` - 檢查是否為Apple格式
- `get_cached_preview(file_uuid, ext)` - 生成緩存預覽

### Cache Directory

**Location:** `data/cache/`

---

## Testing

### Current Tests（7 Tests）

|Test |Status |Description |
|------|--------|-------------|
| test_init_and_load_empty_tree | ✅ OK |初始化空檔案樹 |
| test_insert_and_load_node | ✅ OK |插入節點 |
| test_update_node | ✅ OK |更新節點屬性 |
| test_delete_node | ✅ OK |刪除節點 |
| test_move_node | ✅ OK |移動節點位置 |
| test_update_alias | ✅ OK |更新多語別別名 |
| test_build_tree | ✅ OK |建立樹狀結構 |

### Missing Tests

- ❌ convert.rs -檔案轉換功能
- ❌ modes/*.rs - DisplayMode渲染
- ❌ REST API - endpoint測試

### Test Cleanup

Tests create temporary databases: `data/users/test_*.sqlite`

```bash
#清理暫存資料庫
rm data/users/test_*.sqlite
```

---

## Development Examples

### Create Folder

```rust
use crate::filetree::{FileTree, FileNode};

//建立資料夾節點
let folder = FileTree::new_folder("Videos", None);

//插入到資料庫
let conn = FileTree::open_user_db("demo")?;
let mut tree = FileTree::load(&conn, "demo")?;
tree.insert_node(&conn, &folder)?;
```

### Create File Node

```rust
//建立檔案節點
let (file_node, register_sql) = FileTree::new_file_node(
    "demo.mp4",
    "abc123def456...",      // file_uuid
    Some("sha256hash"),     // sha256
    "demo.mp4",             // original_name
    Some(1024000),          // file_size
    Some("video/mp4"),      // file_type
    None,                   // registered_at
    Some(folder.node_id),   // parent_id
);

//插入到資料庫
tree.insert_node(&conn, &file_node)?;
```

### Load and Query

```rust
//載入檔案樹
let conn = FileTree::open_user_db("demo")?;
let tree = FileTree::load(&conn, "demo")?;

//建立樹狀結構
let roots = tree.build_tree();

//取得特定顯示模式
let mode = filetree::mode::get_mode("tree");
let rendered = mode.render(&tree);
```

### Update Alias

```rust
//更新多語言別名
tree.update_node_alias(&conn, &node_id, "zh_tw", "影片")?;
tree.update_node_alias(&conn, &node_id, "en_us", "Videos")?;
tree.update_node_alias(&conn, &node_id, "ja_jp", "動画")?;
```

---

## Demo Database

**Location:** `data/users/demo.sqlite`

**Statistics:**
- Total Nodes: 50
- Folders: 5
- Files: 45

**Structure:**
```
Home（根資料夾）
├── Movies（9個檔案）
│   ├── view7.mp4
│   ├── Charade_YouTube_24fps.mp4
│   └── ...
├── Marketing（26個檔案）
│   ├── Screenshot *.png
│   ├── diagram-*.svg
│   └── ...
├── Cartoons（5個檔案）
│   ├── animal11.jpg
│   ├── animal10.jpg
│   └── ...
└── Other（4個檔案）
    ├── people.jpg
    └── ...
```

---

## Architecture Diagram

```
┌─────────────────────────────────────┐
│         server.rs                    │
│  REST API Handlers（Axum）          │
└─────────────────────────────────────┘
                ↓
┌─────────────────────────────────────┐
│      filetree/mod.rs                │
│  FileTree CRUD Operations           │
└─────────────────────────────────────┘
                ↓
┌─────────────────────────────────────┐
│      SQLite Database                │
│  data/users/<user_id>.sqlite        │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│      filetree/mode.rs               │
│  DisplayMode Trait                  │
└─────────────────────────────────────┘
                ↓
┌─────────────────────────────────────┐
│      filetree/modes/*.rs            │
│  Tree, List, GridSm, GridLg         │
└─────────────────────────────────────┘
```

---

## Best Practices

### Database Management

- Each user has independent database
- Use UUID for node_id
- Maintain parent-child relationships via parent_id
- Update updated_at timestamp on modifications

### Performance

- Use spawn_blocking for SQLite operations（Axum async）
- Cache file_tree in memory if frequently accessed
- Batch operations when possible

### Security

- Validate node_type before insertion
- Check parent_id existence before moving
- Sanitize aliases_json input

---

## Future Improvements

### Planned Features

- Pagination for large file trees
- Search and filter functionality
- File versioning
- Trash bin（soft delete）
- Batch import/export

### Performance Optimization

- Database connection pooling
- Caching layer（Redis）
- Async SQLite driver（tokio-rusqlite）

### Testing Coverage

- convert.rs tests
- DisplayMode tests
- REST API integration tests
- Performance benchmarks

---

**Last Updated:** 2026-05-16
**Version:** 1.0