prithivMLmods commited on
Commit
e813108
·
verified ·
1 Parent(s): ababc57

update app

Browse files
Files changed (1) hide show
  1. Home.tsx +94 -10
Home.tsx CHANGED
@@ -21,7 +21,7 @@ import {
21
  } from 'lucide-react';
22
  import {useState, useRef, useEffect} from 'react';
23
 
24
- const ai = new GoogleGenAI({apiKey: process.env.API_KEY});
25
 
26
  const aspectRatios = ['1:1', '16:9', '9:16', '4:3', '3:4'];
27
 
@@ -59,6 +59,13 @@ export default function Home() {
59
  const dropdownRef = useRef<HTMLDivElement>(null);
60
  const fileInputRef = useRef<HTMLInputElement>(null);
61
 
 
 
 
 
 
 
 
62
  // Canvas state
63
  const canvasRef = useRef<HTMLCanvasElement>(null);
64
  const [isDrawing, setIsDrawing] = useState(false);
@@ -341,6 +348,43 @@ export default function Home() {
341
 
342
  const handleSubmit = async (e: React.FormEvent) => {
343
  e.preventDefault();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  if (!prompt) {
345
  setErrorMessage('Please enter a prompt to continue.');
346
  return;
@@ -356,6 +400,7 @@ export default function Home() {
356
  setErrorMessage('');
357
 
358
  try {
 
359
  if ((mode === 'image-to-image' && sourceImages.length > 0) || mode === 'draw-to-image') {
360
 
361
  const parts = [];
@@ -378,16 +423,18 @@ export default function Home() {
378
  parts.push(textPart);
379
 
380
  const response = await ai.models.generateContent({
381
- model: 'gemini-2.5-flash-image',
382
  contents: {parts},
383
  config: {
384
- responseModalities: [Modality.IMAGE, Modality.TEXT],
385
  },
386
  });
387
-
388
  let foundImage = false;
389
- if(response.candidates && response.candidates[0].content.parts) {
390
- for (const part of response.candidates[0].content.parts) {
 
 
391
  if (part.inlineData) {
392
  const imageUrl = `data:${part.inlineData.mimeType};base64,${part.inlineData.data}`;
393
  setResultImages([imageUrl]);
@@ -398,7 +445,7 @@ export default function Home() {
398
  }
399
 
400
  if (!foundImage) {
401
- const textMessage = response.text;
402
  setErrorMessage(
403
  textMessage ||
404
  'The model did not return an image. Please try a different prompt.',
@@ -406,7 +453,7 @@ export default function Home() {
406
  }
407
  } else { // Text-to-image
408
  const response = await ai.models.generateImages({
409
- model: 'imagen-4.0-generate-001',
410
  prompt: prompt,
411
  config: {
412
  numberOfImages: numberOfImages,
@@ -644,7 +691,7 @@ export default function Home() {
644
  <div className="info-tooltip-container">
645
  <Info className="w-4 h-4 info-icon" />
646
  <span className="info-tooltip">
647
- The model used for this mode is <code>imagen-4.0-generate-001</code>.
648
  </span>
649
  </div>
650
  )}
@@ -652,7 +699,7 @@ export default function Home() {
652
  <div className="info-tooltip-container">
653
  <Info className="w-4 h-4 info-icon" />
654
  <span className="info-tooltip">
655
- The model used for image editing is <code>gemini-2.5-flash-image</code>.
656
  </span>
657
  </div>
658
  )}
@@ -858,6 +905,43 @@ export default function Home() {
858
  </div>
859
  </div>
860
  )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
861
  </div>
862
  );
863
  }
 
21
  } from 'lucide-react';
22
  import {useState, useRef, useEffect} from 'react';
23
 
24
+ // REMOVED: const ai = new GoogleGenAI({apiKey: process.env.API_KEY});
25
 
26
  const aspectRatios = ['1:1', '16:9', '9:16', '4:3', '3:4'];
27
 
 
59
  const dropdownRef = useRef<HTMLDivElement>(null);
60
  const fileInputRef = useRef<HTMLInputElement>(null);
61
 
62
+ // New state for API Key management
63
+ const [apiKey, setApiKey] = useState('');
64
+ const [showApiKeyModal, setShowApiKeyModal] = useState(false);
65
+ const [tempApiKey, setTempApiKey] = useState('');
66
+ const [isSubmitting, setIsSubmitting] = useState(false);
67
+
68
+
69
  // Canvas state
70
  const canvasRef = useRef<HTMLCanvasElement>(null);
71
  const [isDrawing, setIsDrawing] = useState(false);
 
348
 
349
  const handleSubmit = async (e: React.FormEvent) => {
350
  e.preventDefault();
351
+ if (!apiKey) {
352
+ setShowApiKeyModal(true);
353
+ return;
354
+ }
355
+
356
+ if (isSubmitting) return;
357
+ setIsSubmitting(true);
358
+ await generateOrEditImage();
359
+ setIsSubmitting(false);
360
+
361
+ }
362
+
363
+ const handleApiKeySubmit = async (e: React.FormEvent) => {
364
+ e.preventDefault();
365
+ if (!tempApiKey) {
366
+ setErrorMessage("Please enter an API key.");
367
+ return;
368
+ }
369
+ setApiKey(tempApiKey);
370
+ setShowApiKeyModal(false);
371
+
372
+ // Use a timeout to allow state to update before triggering generation
373
+ setTimeout(() => {
374
+ if (isSubmitting) return;
375
+ setIsSubmitting(true);
376
+ generateOrEditImage(tempApiKey).finally(() => setIsSubmitting(false));
377
+ }, 0);
378
+ };
379
+
380
+
381
+ const generateOrEditImage = async (currentApiKey?: string) => {
382
+ const keyToUse = currentApiKey || apiKey;
383
+ if (!keyToUse) {
384
+ setShowApiKeyModal(true);
385
+ return;
386
+ }
387
+
388
  if (!prompt) {
389
  setErrorMessage('Please enter a prompt to continue.');
390
  return;
 
400
  setErrorMessage('');
401
 
402
  try {
403
+ const ai = new GoogleGenAI({apiKey: keyToUse});
404
  if ((mode === 'image-to-image' && sourceImages.length > 0) || mode === 'draw-to-image') {
405
 
406
  const parts = [];
 
423
  parts.push(textPart);
424
 
425
  const response = await ai.models.generateContent({
426
+ model: 'gemini-1.5-flash-latest',
427
  contents: {parts},
428
  config: {
429
+ responseMimeType: 'application/json',
430
  },
431
  });
432
+
433
  let foundImage = false;
434
+ const parsedResponse = JSON.parse(response.text);
435
+
436
+ if(parsedResponse.candidates && parsedResponse.candidates[0].content.parts) {
437
+ for (const part of parsedResponse.candidates[0].content.parts) {
438
  if (part.inlineData) {
439
  const imageUrl = `data:${part.inlineData.mimeType};base64,${part.inlineData.data}`;
440
  setResultImages([imageUrl]);
 
445
  }
446
 
447
  if (!foundImage) {
448
+ const textMessage = parsedResponse.text;
449
  setErrorMessage(
450
  textMessage ||
451
  'The model did not return an image. Please try a different prompt.',
 
453
  }
454
  } else { // Text-to-image
455
  const response = await ai.models.generateImages({
456
+ model: 'imagen-3.0-generate-001',
457
  prompt: prompt,
458
  config: {
459
  numberOfImages: numberOfImages,
 
691
  <div className="info-tooltip-container">
692
  <Info className="w-4 h-4 info-icon" />
693
  <span className="info-tooltip">
694
+ The model used for this mode is <code>imagen-3.0-generate-001</code>.
695
  </span>
696
  </div>
697
  )}
 
699
  <div className="info-tooltip-container">
700
  <Info className="w-4 h-4 info-icon" />
701
  <span className="info-tooltip">
702
+ The model used for image editing is <code>gemini-1.5-flash-latest</code>.
703
  </span>
704
  </div>
705
  )}
 
905
  </div>
906
  </div>
907
  )}
908
+
909
+ {showApiKeyModal && (
910
+ <div className="modal-backdrop">
911
+ <div className="card modal-card api-key-modal">
912
+ <div className="head">
913
+ <span>Add Your Gemini API Key</span>
914
+ <button
915
+ onClick={() => setShowApiKeyModal(false)}
916
+ className="modal-close-button">
917
+ <X className="w-5 h-5" />
918
+ </button>
919
+ </div>
920
+ <div className="content">
921
+ <p className="api-key-info">
922
+ Your API key is only stored for this session and will be lost when you reload or exit the page. It is not shared or exposed anywhere.
923
+ </p>
924
+ <form onSubmit={handleApiKeySubmit} className="api-key-form">
925
+ <input
926
+ type="password"
927
+ value={tempApiKey}
928
+ onChange={(e) => setTempApiKey(e.target.value)}
929
+ className="input"
930
+ placeholder="Enter your Gemini API Key"
931
+ required
932
+ />
933
+ <button type="submit" className="button primary" disabled={isLoading}>
934
+ {isLoading ? (
935
+ <LoaderCircle className="w-5 h-5 animate-spin" />
936
+ ) : (
937
+ "Submit & Run"
938
+ )}
939
+ </button>
940
+ </form>
941
+ </div>
942
+ </div>
943
+ </div>
944
+ )}
945
  </div>
946
  );
947
  }