AOSSIE-Org / AOSSIE-Org/PictoPy

Feat: Allow Manual Deletion of Face Clusters

Aberta
#1,177 4 comentários 0 reações 0 responsáveis Ver no GitHub
Linguagem predominante
Python
Estrelas
283
Forks
679
Merge médio
7d 2h
PRs com merge (30d)
3

Descrição

### Describe the feature

## Description
Inside the AI Tagging section of PictoPy, there should be an option to delete specific Face Clusters so that users can remove unwanted Face Clusters. Currently, no such option is available.

## Current Problem
- No option to delete or hide specific automatically generated face clusters.
- In my previous attempts of deletion (setting `cluster_id` to `NULL`) would have been resulted in re-discover and re-display the same unwanted group during the next 24-hour full reclustering cycle.

## Expected Solution
- Users should be able to remove Face Clusters.
- A Delete button should be visible when a user opens any Face Cluster.
- Concept of Soft Deletion.

## Implementation
### Backend
### 1. Database Schema Enhancements
Added a column `is_deleted` to both tables `face_clusters` and `faces` to enable "Soft Delete" logic.
- **`face_clusters` table:** Added `is_deleted BOOLEAN DEFAULT FALSE`.
- **`faces` table:** Added `is_deleted BOOLEAN DEFAULT FALSE`.

### 2. Implementation Logic

#### **Soft Delete Operation**
The system now executes a transaction-safe update rather than deleting rows permanently. This hides it from the user while maintaining the internal grouping data for the AI.
```python
# Updated deletion logic in db_delete_cluster_by_cluster_id
cursor.execute("UPDATE faces SET is_deleted = TRUE WHERE cluster_id = ?")
cursor.execute("UPDATE face_clusters SET is_deleted = TRUE WHERE cluster_id = ?")
```

#### **Majority Voting (Reclustering Logic)**
This is the main concept. When full reclustering occurs (every 24 hours):
1. The system creates brand new clusters for all faces.
2. For each new cluster, it checks the previous `is_deleted` status of its constituent faces.
3. **Inheritance:** If a majority of faces in a new cluster were previously marked as deleted, the new cluster automatically inherits `is_deleted = TRUE`.
4. This ensures that manually hidden people stay hidden even if the underlying `cluster_id` changes.

#### **When fetching clusters**
The retrieval endpoints are updated to automatically exclude clusters marked with the `is_deleted` flag:
```python
# API Logic
clusters = [c for c in clusters_data if not c.get("is_deleted", False)]
```

- **Frontend**
- `UI:` Added Delete Button and defined `handleDeleteCluster`
```tsx
import { Check, Pencil, ArrowLeft, Trash2 } from 'lucide-react';


Delete Cluster

```

- `API Route:` Added `DELETE /face-clusters/delete-cluster/${clusterId}` in `apiEndpoint.ts`
- `Response Handling:` The message from the backend is displayed regardless of the success status, ensuring the user sees the specific feedback provided by the server.
- `Lint Fix:` Ensured the mutation call is type-safe by passing `undefined` for operations requiring no payload.

### Add ScreenShots

## Screenshots
### Delete Endpoint working properly.

Image

### Delete Button not available (Before)

Image

### Delete Button now available (After)

Image

### Demo video (After)

https://github.com/user-attachments/assets/9a20c731-71eb-4f40-b6c0-6cc99cd5ccc4

## Tests Performed
### test_face_clusters.py

Image

### test_albums.py

Image

### test_folders.py

Image

### test_user_preferences.py

Image

### Record

- [x] I agree to follow this project's Code of Conduct
- [x] I want to work on this issue

Guia de contribuição

Abrir o guia de contribuição

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.