Skip to content

Commit

Permalink
Merge pull request #252 from priyanshuverma-dev/feat-image-gen-modal
Browse files Browse the repository at this point in the history
feat: Image generation modal with enhanced feature
  • Loading branch information
kom-senapati authored Nov 3, 2024
2 parents 548f666 + 81763c1 commit 73395e8
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 12 deletions.
1 change: 0 additions & 1 deletion app/api_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,6 @@ def api_create_image() -> Response:
else:
data = request.get_json()
prompt: str = data.get("query")
print(prompt, user.id)
image: Image = Image(
prompt=prompt,
user_id=user.id,
Expand Down
Binary file modified client/bun.lockb
Binary file not shown.
6 changes: 1 addition & 5 deletions client/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ export default function Navbar() {
Hub
</Link>
</li>
<li>
<Link to="/imagine" className="py-2">
Imagine
</Link>
</li>

{user == null ? (
<>
<li className="w-full">
Expand Down
9 changes: 3 additions & 6 deletions client/src/components/modals/command-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from "lucide-react";
import {
useCreateChatbotModal,
useImagineModal,
useSettingsModal,
useTranslateMagicModal,
useTtsMagicModal,
Expand All @@ -34,6 +35,7 @@ export function CommandModal() {

const createBotModal = useCreateChatbotModal();
const settingsModal = useSettingsModal();
const imagineModal = useImagineModal();
const ttsModal = useTtsMagicModal();
const translateModal = useTranslateMagicModal();
const navigate = useNavigate();
Expand Down Expand Up @@ -80,12 +82,7 @@ export function CommandModal() {
<Languages />
<span>Translate Magic</span>
</CommandItem>
<CommandItem
onSelect={() => {
setOpen(false);
navigate("/imagine");
}}
>
<CommandItem onSelect={() => imagineModal.onOpen()}>
<Image />
<span>Generate Images</span>
</CommandItem>
Expand Down
166 changes: 166 additions & 0 deletions client/src/components/modals/imgine-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { imageSrc, SERVER_URL } from "@/lib/utils";
import { useImagineModal } from "@/stores/modal-store";
import axios from "axios";
import { Button } from "../ui/button";
import toast from "react-hot-toast";
import { Textarea } from "../ui/textarea";
import { Pickaxe, X } from "lucide-react";
import { useState } from "react";
import { Skeleton } from "../ui/skeleton";

export default function ImagineModal() {
const modal = useImagineModal();
const [text, setText] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
const [generated, setGenerated] = useState<boolean>(false);
const [imagePrompt, setImagePrompt] = useState<string | null>(null);

const GenerateImage = async () => {
if (text.length <= 3) {
toast.error("Come on write something unique.");
return;
}
setGenerated(false);
setImagePrompt("");
setImagePrompt(text);
setGenerated(true);
};

const SaveImage = async () => {
setLoading(true);
try {
if (imagePrompt && imagePrompt.length <= 3) {
toast.error("Come on write something unique.");
return;
}
const token = localStorage.getItem("token");

const authHeaders = {
Authorization: `Bearer ${token || ""}`,
};
const response = await axios.post(
`${SERVER_URL}/api/imagine`,
{
query: imagePrompt,
},
{
headers: authHeaders,
}
);
if (response.data.success) {
setImagePrompt("");
setGenerated(false);
setText("");
} else {
toast.error("Error in saving image");
}
} catch (error: any) {
const errorMessage =
error.response?.data?.message ||
error.message ||
"An unexpected error occurred.";
toast.error(errorMessage);
console.log("[GENERATION_ERROR]", error);
} finally {
setLoading(false);
}
};

return (
<AlertDialog open={modal.isOpen} onOpenChange={() => modal.onClose()}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
<div className="flex items-center justify-between">
<p>Imgine a image and generate it</p>
<Button
variant={"outline"}
size={"icon"}
className="rounded-full"
onClick={() => modal.onClose()}
>
<X />
</Button>
</div>
</AlertDialogTitle>
<AlertDialogDescription>
Let's see how you imagination is. I know you are creative enough.
</AlertDialogDescription>
<div className="my-4 space-y-2">
{generated && imagePrompt && (
<div className="relative aspect-square">
<ImageWithLoading key={imagePrompt} imagePrompt={imagePrompt} />
</div>
)}
<div className="relative">
<Textarea
disabled={loading}
value={text}
onChange={(e) => setText(e.target.value)} // Update state on change
rows={5}
className="w-full p-2 border rounded"
placeholder="Enter your imagination prompt here..."
/>
<Button
onClick={GenerateImage} // Function to handle icon generation
className="absolute bottom-2 right-2 rounded-full"
variant={"outline"}
size={"icon"}
disabled={loading} // Disable button when loading
aria-label="Generate Icon"
>
<Pickaxe />
</Button>
</div>
</div>
</AlertDialogHeader>
<AlertDialogFooter>
<div className="flex items-center justify-between w-full">
<p className="text-muted-foreground text-sm px-2">
If you want to save this Image in database then Click 'Capture'
</p>
<Button
disabled={loading}
onClick={SaveImage}
className="btn btn-primary"
>
Capture
</Button>
</div>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}

function ImageWithLoading({ imagePrompt }: { imagePrompt: string }) {
const [loading, setLoading] = useState(true);
// Handle when image loads
const handleImageLoad = () => {
setLoading(false); // Hide loader
};
return (
<div className="relative w-full h-full">
{loading && (
<div className="absolute inset-0 flex items-center justify-center rounded-full">
<Skeleton className="w-full h-full rounded-t-lg" />
</div>
)}
<img
key={imagePrompt}
className="rounded-t-lg"
alt={imagePrompt}
src={imageSrc(imagePrompt)}
onLoad={handleImageLoad}
/>
</div>
);
}
2 changes: 2 additions & 0 deletions client/src/contexts/modals.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import CreateChatbotModal from "@/components/modals/create-chatbot-modal";
import DeleteChatbotModal from "@/components/modals/delete-chatbot-modal";
import ImagineModal from "@/components/modals/imgine-modal";
import SettingsModal from "@/components/modals/settings-modal";
import ShareModal from "@/components/modals/share-modal";
import TranslateMagicModal from "@/components/modals/translate-magic-modal";
Expand All @@ -17,6 +18,7 @@ export default function Modals() {
<ShareModal />
<TtsMagicModal />
<TranslateMagicModal />
<ImagineModal />
<DeleteChatbotModal />
</>
);
Expand Down
1 change: 1 addition & 0 deletions client/src/stores/modal-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const useSettingsModal = create<DefaultModal>(defaultModalValues);
export const useShareModal = create<DefaultModal>(defaultModalValues);
export const useTtsMagicModal = create<DefaultModal>(defaultModalValues);
export const useTranslateMagicModal = create<DefaultModal>(defaultModalValues);
export const useImagineModal = create<DefaultModal>(defaultModalValues);

0 comments on commit 73395e8

Please sign in to comment.