- Split app.py into route blueprints (files, layers, images, polygon, mask, krita) - Create services layer (polygon_storage, comfyui, file_browser) - Extract config constants to config.py - Split templates into Jinja partials (base, components, modals) - Add browse dialog for visual file navigation - Add /api/browse endpoint for directory listing
76 lines
2.5 KiB
Python
76 lines
2.5 KiB
Python
"""File browsing service for project directory navigation."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
class FileBrowserService:
|
|
"""Service for browsing project files and directories."""
|
|
|
|
SUPPORTED_EXTENSIONS = {'.png', '.ora'}
|
|
|
|
def __init__(self, project_root: Path):
|
|
self.project_root = project_root
|
|
|
|
def list_directory(self, relative_path: str = "") -> dict[str, Any]:
|
|
"""List contents of a directory relative to project root."""
|
|
if relative_path:
|
|
dir_path = self.project_root / relative_path
|
|
else:
|
|
dir_path = self.project_root
|
|
|
|
if not dir_path.exists() or not dir_path.is_dir():
|
|
return {
|
|
'success': False,
|
|
'error': f'Directory not found: {relative_path}'
|
|
}
|
|
|
|
directories = []
|
|
files = []
|
|
|
|
try:
|
|
for entry in sorted(dir_path.iterdir(), key=lambda e: (not e.is_dir(), e.name.lower())):
|
|
if entry.name.startswith('.'):
|
|
continue
|
|
|
|
if entry.is_dir():
|
|
rel_path = str(entry.relative_to(self.project_root))
|
|
directories.append({
|
|
'name': entry.name,
|
|
'path': rel_path
|
|
})
|
|
elif entry.is_file():
|
|
suffix = entry.suffix.lower()
|
|
if suffix in self.SUPPORTED_EXTENSIONS:
|
|
rel_path = str(entry.relative_to(self.project_root))
|
|
files.append({
|
|
'name': entry.name,
|
|
'path': rel_path,
|
|
'type': suffix[1:]
|
|
})
|
|
|
|
parent_path = None
|
|
if relative_path:
|
|
parent = Path(relative_path).parent
|
|
parent_path = str(parent) if parent != Path('.') else ""
|
|
|
|
return {
|
|
'success': True,
|
|
'current_path': relative_path,
|
|
'parent_path': parent_path,
|
|
'directories': directories,
|
|
'files': files
|
|
}
|
|
|
|
except PermissionError:
|
|
return {
|
|
'success': False,
|
|
'error': f'Permission denied: {relative_path}'
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|