+
+
+
+
+
+ {folder.folder_path}
+
+
+
- if (isGeneratingThumbnails || isDeletingThumbnails || isLoading) {
- return (
-
-
-
- );
- }
+
+
+
+ AI Tagging
+
+ handleToggleAITagging(folder)}
+ disabled={
+ enableAITaggingPending || disableAITaggingPending
+ }
+ />
+
- return (
-
-
-
-
- Current Folder Paths
-
- {currentPaths.length > 0 ? (
- currentPaths.map((path, index) => (
-
- {path}
-
-
- ))
+
+
+
+
+ ))}
+
) : (
-
- No folder paths selected
+
+
+
+ No folders configured
+
+
+ Add your first photo library folder to get started
+
)}
+
+
+
+
-
-
-
-
- {isProd() && (
+ {/* Application Controls Card */}
+
+
+
+
+
+ Application Controls
+
+
+ Manage updates and server operations
+
+
+
+
+
- )}
-
-
-
-
- WARNING: It may impact performance, restart for changes to take
- effect.
-
+ {true && (
+
+ )}
+
-
setErrorDialogContent(null)}
- />
{
- const [currentPaths] = useLocalStorage('folderPaths', []);
- const { videos, loading } = useVideos(currentPaths);
-
- if (loading)
+ return (
-
;
-
- return (
- <>
-
- >
+
);
};
diff --git a/frontend/src/pages/__tests__/allPages.test.tsx b/frontend/src/pages/__tests__/allPages.test.tsx
index 69b419b72..2f1e2d241 100644
--- a/frontend/src/pages/__tests__/allPages.test.tsx
+++ b/frontend/src/pages/__tests__/allPages.test.tsx
@@ -1,9 +1,8 @@
import { render } from '@testing-library/react';
-import AITagging from '../AITagging/AITagging';
+import { AITagging } from '@/pages/AITagging/AITagging';
import Album from '../Album/Album';
-import Dashboard from '../Dashboard/Dashboard';
+import { Home } from '@/pages/Home/Home';
import Memories from '../Memories/Memories';
-import SecureFolder from '../SecureFolderPage/SecureFolder';
import Settings from '../SettingsPage/Settings';
import Videos from '../VideosPage/Videos';
import { ROUTES } from '@/constants/routes';
@@ -25,13 +24,12 @@ beforeAll(() => {
});
const pages = [
- { path: ROUTES.LAYOUT.HOME, Component: Dashboard },
- { path: ROUTES.LAYOUT.VIDEOS, Component: Videos },
- { path: ROUTES.LAYOUT.SETTINGS, Component: Settings },
- { path: ROUTES.LAYOUT.AI, Component: AITagging },
- { path: ROUTES.LAYOUT.ALBUMS, Component: Album },
- { path: ROUTES.LAYOUT.SECURE_FOLDER, Component: SecureFolder },
- { path: ROUTES.LAYOUT.MEMORIES, Component: Memories },
+ { path: ROUTES.HOME, Component: Home },
+ { path: ROUTES.VIDEOS, Component: Videos },
+ { path: ROUTES.SETTINGS, Component: Settings },
+ { path: ROUTES.AI, Component: AITagging },
+ { path: ROUTES.ALBUMS, Component: Album },
+ { path: ROUTES.MEMORIES, Component: Memories },
];
describe('Page rendering tests', () => {
diff --git a/frontend/src/routes/AppRoutes.tsx b/frontend/src/routes/AppRoutes.tsx
index 905e60a28..dc86524aa 100644
--- a/frontend/src/routes/AppRoutes.tsx
+++ b/frontend/src/routes/AppRoutes.tsx
@@ -1,29 +1,25 @@
import React from 'react';
import { Routes, Route } from 'react-router';
+import { ROUTES } from '@/constants/routes';
import Layout from '@/layout/layout';
import { InitialSteps } from '@/pages/InitialSteps/InitialSteps';
-// Layout Components
-import { ROUTES } from '@/constants/routes';
-import AITagging from '@/pages/AITagging/AITagging';
-import Album from '@/pages/Album/Album';
-import Dashboard from '@/pages/Dashboard/Dashboard';
-import SecureFolder from '@/pages/SecureFolderPage/SecureFolder';
-import Memories from '@/pages/Memories/Memories';
import Settings from '@/pages/SettingsPage/Settings';
-import Videos from '@/pages/VideosPage/Videos';
+import { Home } from '@/pages/Home/Home';
+import { AITagging } from '@/pages/AITagging/AITagging';
+import { PersonImages } from '@/pages/PersonImages/PersonImages';
export const AppRoutes: React.FC = () => {
return (
} />
}>
- } />
- } />
- } />
- } />
- } />
- } />
- } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
);
diff --git a/frontend/src/services/cacheService.ts b/frontend/src/services/cacheService.ts
deleted file mode 100644
index 7f0ca7e4d..000000000
--- a/frontend/src/services/cacheService.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { invoke } from '@tauri-apps/api/core';
-
-export async function deleteCache() {
- try {
- const result = await invoke('delete_cache');
- return result;
- } catch (error) {
- console.error('Error deleting cache:', error);
- throw error;
- }
-}
diff --git a/frontend/src/types/image.ts b/frontend/src/types/API.ts
similarity index 52%
rename from frontend/src/types/image.ts
rename to frontend/src/types/API.ts
index 3374e15bc..d94682128 100644
--- a/frontend/src/types/image.ts
+++ b/frontend/src/types/API.ts
@@ -1,12 +1,5 @@
-export interface Image {
- title: string;
- url: string;
- tags: any;
- thumbnailUrl: string;
-}
-
export interface APIResponse {
- data: {
+ data?: {
[key: string]: any;
};
success: boolean;
diff --git a/frontend/src/types/Folder.ts b/frontend/src/types/Folder.ts
new file mode 100644
index 000000000..34a9f9c58
--- /dev/null
+++ b/frontend/src/types/Folder.ts
@@ -0,0 +1,13 @@
+export interface FolderDetails {
+ folder_id: string;
+ folder_path: string;
+ parent_folder_id?: string;
+ last_modified_time: number;
+ AI_Tagging: boolean;
+ taggingCompleted?: boolean;
+}
+
+export interface GetAllFoldersData {
+ folders: FolderDetails[];
+ total_count: number;
+}
diff --git a/frontend/src/types/Media.ts b/frontend/src/types/Media.ts
index bb5b99ad4..07c64b28d 100644
--- a/frontend/src/types/Media.ts
+++ b/frontend/src/types/Media.ts
@@ -1,51 +1,46 @@
-export interface MediaItem {
- original?: string;
- url: string;
- thumbnailUrl?: string;
- date?: string;
- title?: string;
+export interface Image {
+ id: string;
+ path: string;
+ thumbnailPath: string;
+ folder_id: string;
+ isTagged: boolean;
+ metadata?: string;
tags?: string[];
- imagePath?: string;
+ bboxes?: { x: number; y: number; width: number; height: number }[];
}
-export interface MediaCardProps {
- item: MediaItem;
- type: 'image' | 'video';
+export interface ImageCardProps {
+ item: Image;
}
-export interface MediaGalleryProps {
- mediaItems: MediaItem[];
+export interface ImageGalleryProps {
+ mediaItems: Image[];
title?: string;
- type: 'image' | 'video';
}
-export interface MediaGridProps {
- mediaItems: MediaItem[];
+export interface ImageGridProps {
+ mediaItems: Image[];
itemsPerRow: number;
openMediaViewer: (index: number) => void;
- type: 'image' | 'video';
}
export interface MediaViewProps {
- initialIndex: number;
- onClose: () => void;
- allMedia: { url: string; path?: string; thumbnailUrl?: string }[];
- currentPage: number;
- itemsPerPage: number;
- type: 'image' | 'video';
- isSecureFolder?: boolean;
-}
-
-export interface YearOption {
- value: string;
- label: string;
+ onClose?: () => void;
+ type?: string;
}
export interface SortingControlsProps {
sortBy: string;
setSortBy: (value: string) => void;
- mediaItems: MediaItem[];
+ mediaItems: Image[];
}
export interface PaginationControlsProps {
currentPage: number;
totalPages: number;
onPageChange: (page: number) => void;
}
+
+export interface Cluster {
+ cluster_id: string;
+ cluster_name: string;
+ face_count: number;
+ face_image_base64?: string;
+}
diff --git a/frontend/src/utils/Media.ts b/frontend/src/utils/Media.ts
deleted file mode 100644
index cdfc8c79d..000000000
--- a/frontend/src/utils/Media.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-// Media.ts
-
-import { MediaItem } from '@/types/Media';
-
-export function sortMedia(
- mediaItems: MediaItem[],
- sortBy: string[],
-): MediaItem[] {
- return [...mediaItems].sort((a, b) => {
- for (const criterion of sortBy) {
- const aDate = a.date ? new Date(a.date) : new Date();
- const bDate = b.date ? new Date(b.date) : new Date();
-
- switch (criterion) {
- case 'date':
- // Sort by date (most recent first)
- if (bDate.getTime() !== aDate.getTime()) {
- return bDate.getTime() - aDate.getTime();
- }
- break;
-
- case 'name':
- case 'asc':
- // Sort alphabetically by file name
- //@ts-ignore
- const nameCompareAsc = a.title.localeCompare(b.title);
- if (nameCompareAsc !== 0) return nameCompareAsc;
- break;
-
- case 'desc':
- // Sort alphabetically by file name in descending order
- //@ts-ignore
-
- const nameCompareDesc = b.title.localeCompare(a.title);
- if (nameCompareDesc !== 0) return nameCompareDesc;
- break;
-
- case 'size':
- // Assuming `size` is a property in MediaItem (in bytes, KB, etc.)
- //@ts-ignore
-
- if (a.size && b.size && a.size !== b.size) {
- //@ts-ignore
-
- return a.size - b.size;
- }
- break;
-
- case 'type':
- // Assuming `type` refers to file extension or media type
- const aType = a.original?.split('.').pop()?.toLowerCase() || '';
- const bType = b.original?.split('.').pop()?.toLowerCase() || '';
- const typeCompare = aType.localeCompare(bType);
- if (typeCompare !== 0) return typeCompare;
- break;
-
- default:
- console.warn(`Invalid sortBy option: ${criterion}. Skipping.`);
- break;
- }
- }
- // If all criteria result in equality, maintain original order
- return 0;
- });
-}
diff --git a/frontend/src/utils/serverUtils.ts b/frontend/src/utils/serverUtils.ts
index 749616261..66656f601 100644
--- a/frontend/src/utils/serverUtils.ts
+++ b/frontend/src/utils/serverUtils.ts
@@ -53,16 +53,13 @@ export const stopServer = async () => {
}
};
-export const restartServer = async (setIsLoading: (val: boolean) => void) => {
+export const restartServer = async () => {
try {
- setIsLoading(true);
await stopServer();
setTimeout(async () => {
await startServer();
- setIsLoading(false);
}, 2000);
} catch (error) {
- setIsLoading(false);
console.error('Error restarting server:', error);
throw error;
}
diff --git a/sync-microservice/app/config/settings.py b/sync-microservice/app/config/settings.py
index 00d1ab6c5..266ba420a 100644
--- a/sync-microservice/app/config/settings.py
+++ b/sync-microservice/app/config/settings.py
@@ -1,7 +1,7 @@
# Model Exports Path
MODEL_EXPORTS_PATH = "app/models/ONNX_Exports"
PRIMARY_BACKEND_URL = "http://localhost:8000"
-SYNC_MICROSERVICE_URL = "http://localhost:8001"
+SYNC_MICROSERVICE_URL = "http://localhost:8001/api/v1"
# Object Detection Models:
SMALL_OBJ_DETECTION_MODEL = f"{MODEL_EXPORTS_PATH}/YOLOv11_Small.onnx"