{isLoading ? (
-
- ) : translatedImages ? (
+
+ ) : translatedImages.length > 0 ? (
currentImage && (
@@ -147,7 +162,11 @@ const CollectionView: React.FC = ({ collection }) => {
src={currentImage.image_url}
alt="Collection Image"
className="w-full select-none"
- style={{ marginBottom: "230px" }}
+ style={
+ currentImage.transcriptions.length != 0
+ ? { marginBottom: "230px" }
+ : {}
+ }
onClick={handlePhotoClick}
/>
@@ -194,7 +213,9 @@ const CollectionView: React.FC
= ({ collection }) => {
/>
>
) : (
- No transcript
+
+ No transcript
+
)}
diff --git a/frontend/src/hooks/theme.tsx b/frontend/src/hooks/theme.tsx
index 34123f8..7affcdc 100644
--- a/frontend/src/hooks/theme.tsx
+++ b/frontend/src/hooks/theme.tsx
@@ -1,3 +1,4 @@
+import throttle from "lodash/throttle";
import {
createContext,
ReactNode,
@@ -61,25 +62,59 @@ export const ThemeProvider = (props: ThemeProviderProps) => {
setThemeWithLocalStorage(theme);
};
- const scrollSpeed = 10; // Increase this value to make scrolling faster
+ // const scrollSpeed = 200; // Increase this value to make scrolling faster
+
+ // useEffect(() => {
+ // const handleWheel = (event: WheelEvent) => {
+ // event.preventDefault(); // Prevent default scroll behavior
+ // window.scrollBy({
+ // top: event.deltaY * scrollSpeed, // Multiply the scroll amount
+ // left: 0,
+ // behavior: "smooth", // Use smooth scrolling
+ // });
+ // };
+
+ // window.addEventListener("wheel", handleWheel, { passive: false });
+
+ // // Clean up the event listener on component unmount
+ // return () => {
+ // window.removeEventListener("wheel", handleWheel);
+ // };
+ // }, []); // Empty dependency array ensures this runs only on mount and unmount
+
+ const handleKey = throttle((event: KeyboardEvent) => {
+ switch (event.key) {
+ case "ArrowUp":
+ window.scrollBy({
+ top: -600,
+ left: 0,
+ behavior: "smooth",
+ });
+ break;
+ case "ArrowDown":
+ window.scrollBy({
+ top: 600,
+ left: 0,
+ behavior: "smooth",
+ });
+ break;
+ }
+ }, 300);
useEffect(() => {
- const handleWheel = (event: WheelEvent) => {
- event.preventDefault(); // Prevent default scroll behavior
- window.scrollBy({
- top: event.deltaY * scrollSpeed, // Multiply the scroll amount
- left: 0,
- behavior: "smooth", // Use smooth scrolling
- });
- };
-
- window.addEventListener("wheel", handleWheel, { passive: false });
-
- // Clean up the event listener on component unmount
+ const throttledHandleKey = (event: KeyboardEvent) => {
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
+ event.preventDefault(); // Prevent the default behavior for arrow keys.
+ handleKey(event);
+ }
+ }; // Adjust the throttle delay (200ms here) as needed.
+
+ window.addEventListener("keydown", throttledHandleKey);
return () => {
- window.removeEventListener("wheel", handleWheel);
+ window.removeEventListener("keydown", throttledHandleKey);
+ handleKey.cancel(); // Clean up the throttling
};
- }, []); // Empty dependency array ensures this runs only on mount and unmount
+ }, []);
useEffect(() => {
document.body.setAttribute("data-bs-theme", theme);
diff --git a/frontend/src/pages/Collection.tsx b/frontend/src/pages/Collection.tsx
index 00571c5..9708765 100644
--- a/frontend/src/pages/Collection.tsx
+++ b/frontend/src/pages/Collection.tsx
@@ -2,7 +2,6 @@ import CollectionEdit from "components/collection/Edit";
import CollectionNew from "components/collection/New";
import CollectionView from "components/collection/View";
import { useAuth } from "contexts/AuthContext";
-import { useLoading } from "contexts/LoadingContext";
import { useAlertQueue } from "hooks/alerts";
import React, { useEffect, useMemo, useState } from "react";
import { useLocation, useParams } from "react-router-dom";
@@ -14,9 +13,8 @@ const CollectionPage: React.FC = () => {
const [collection, setCollection] = useState
(
undefined,
);
- const { auth, client } = useAuth();
+ const { client } = useAuth();
const { addAlert } = useAlertQueue();
- const { startLoading, stopLoading } = useLoading();
// Helper to check if it's an edit action
const isEditAction = useMemo(
() => location.search.includes("Action=edit"),
@@ -25,20 +23,18 @@ const CollectionPage: React.FC = () => {
// Simulate fetching data for the edit page (mocking API call)
useEffect(() => {
- if (id && auth?.is_auth) {
+ if (id) {
const asyncfunction = async () => {
- startLoading();
const { data: collection, error } = await client.GET(
"/get_collection",
{ params: { query: { id } } },
);
if (error) addAlert(error.detail?.toString(), "error");
else setCollection(collection);
- stopLoading();
};
asyncfunction();
}
- }, [id, auth]);
+ }, [id]);
// Return button handler
// const handleReturn = () => {
@@ -81,13 +77,13 @@ const CollectionPage: React.FC = () => {
return ;
}
// Rendering Edit Collection Page
- if (id && isEditAction && collection) {
+ if (id && isEditAction) {
return (
);
}
// Rendering Collection Detail Page
- if (id && !isEditAction && collection) {
+ if (id && !isEditAction) {
return ;
}
//skeleton
diff --git a/linguaphoto/api/collection.py b/linguaphoto/api/collection.py
index 0af5640..79ea951 100644
--- a/linguaphoto/api/collection.py
+++ b/linguaphoto/api/collection.py
@@ -35,9 +35,7 @@ async def create(
@router.get("/get_collection", response_model=Collection)
-async def getcollection(
- id: str, user_id: str = Depends(get_current_user_id), collection_crud: CollectionCrud = Depends()
-) -> Collection:
+async def getcollection(id: str, collection_crud: CollectionCrud = Depends()) -> Collection:
async with collection_crud:
collection = await collection_crud.get_collection(id)
if collection is None:
diff --git a/linguaphoto/api/image.py b/linguaphoto/api/image.py
index c5667f8..1bc5023 100644
--- a/linguaphoto/api/image.py
+++ b/linguaphoto/api/image.py
@@ -43,11 +43,9 @@ async def upload_image(
@router.get("/get_images", response_model=List[Image])
-async def get_images(
- collection_id: str, user_id: str = Depends(get_current_user_id), image_crud: ImageCrud = Depends()
-) -> List[Image]:
+async def get_images(collection_id: str, image_crud: ImageCrud = Depends()) -> List[Image]:
async with image_crud:
- images = await image_crud.get_images(collection_id=collection_id, user_id=user_id)
+ images = await image_crud.get_images(collection_id=collection_id)
return images
diff --git a/linguaphoto/crud/image.py b/linguaphoto/crud/image.py
index 9c8a8bf..beceaf2 100644
--- a/linguaphoto/crud/image.py
+++ b/linguaphoto/crud/image.py
@@ -6,7 +6,6 @@
from typing import List
import requests
-from boto3.dynamodb.conditions import Key
from fastapi import HTTPException, UploadFile
from openai import AsyncOpenAI
@@ -69,8 +68,7 @@ async def create_audio(self, audio_source: BytesIO) -> str:
# Return the signed S3 URL
return s3_url
- async def get_images(self, collection_id: str, user_id: str) -> List[Image]:
- images = await self._get_items_from_secondary_index("user", user_id, Image, Key("collection").eq(collection_id))
+ async def get_images(self, collection_id: str) -> List[Image]:
images = await self._list_items(
item_class=Image,
filter_expression="#collection=:collection",
diff --git a/linguaphoto/main.py b/linguaphoto/main.py
index 6673296..20eb8bc 100644
--- a/linguaphoto/main.py
+++ b/linguaphoto/main.py
@@ -4,7 +4,6 @@
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
-import socketio
from linguaphoto.api.api import router
from linguaphoto.socket_manager import (
diff --git a/linguaphoto/socket_manager.py b/linguaphoto/socket_manager.py
index 80395ae..18dfa94 100644
--- a/linguaphoto/socket_manager.py
+++ b/linguaphoto/socket_manager.py
@@ -7,9 +7,7 @@
# Create a new Socket.IO server with CORS enabled
sio = socketio.AsyncServer(
async_mode="asgi",
- cors_allowed_origins=[
- settings.homepage_url
- ], # Update this to match your frontend URL
+ cors_allowed_origins=[settings.homepage_url], # Update this to match your frontend URL
)
# Dictionary to store connected users by their socket ID
connected_users: dict[str, str] = {}