akhaliq HF Staff commited on
Commit
bef7bcd
·
1 Parent(s): db72a16

add image upload

Browse files
frontend/src/app/page.tsx CHANGED
@@ -59,6 +59,7 @@ export default function Home() {
59
  const loadModels = async () => {
60
  try {
61
  const modelsList = await apiClient.getModels();
 
62
  setModels(modelsList);
63
  } catch (error) {
64
  console.error('Failed to load models:', error);
@@ -67,6 +68,13 @@ export default function Home() {
67
 
68
  // Check if current model supports images
69
  const currentModelSupportsImages = models.find(m => m.id === selectedModel)?.supports_images || false;
 
 
 
 
 
 
 
70
 
71
  // Load messages from localStorage on mount (client-side only to avoid hydration issues)
72
  useEffect(() => {
 
59
  const loadModels = async () => {
60
  try {
61
  const modelsList = await apiClient.getModels();
62
+ console.log('[Models] Loaded models:', modelsList);
63
  setModels(modelsList);
64
  } catch (error) {
65
  console.error('Failed to load models:', error);
 
68
 
69
  // Check if current model supports images
70
  const currentModelSupportsImages = models.find(m => m.id === selectedModel)?.supports_images || false;
71
+
72
+ // Debug log for image support
73
+ useEffect(() => {
74
+ console.log('[Image Support] Selected model:', selectedModel);
75
+ console.log('[Image Support] Models loaded:', models.length);
76
+ console.log('[Image Support] Supports images:', currentModelSupportsImages);
77
+ }, [selectedModel, models, currentModelSupportsImages]);
78
 
79
  // Load messages from localStorage on mount (client-side only to avoid hydration issues)
80
  useEffect(() => {
frontend/src/components/LandingPage.tsx CHANGED
@@ -1,6 +1,7 @@
1
  'use client';
2
 
3
  import { useState, useEffect, useRef } from 'react';
 
4
  import { apiClient } from '@/lib/api';
5
  import {
6
  initializeOAuth,
@@ -30,7 +31,7 @@ export default function LandingPage({
30
  onImport,
31
  isAuthenticated,
32
  initialLanguage = 'html',
33
- initialModel = 'deepseek-ai/DeepSeek-V3.2-Exp',
34
  onAuthChange,
35
  setPendingPR,
36
  pendingPRRef
@@ -74,6 +75,10 @@ export default function LandingPage({
74
  const [isRedesigning, setIsRedesigning] = useState(false);
75
  const [redesignError, setRedesignError] = useState('');
76
  const [createPR, setCreatePR] = useState(false); // Default to normal redesign (not PR)
 
 
 
 
77
 
78
  // Debug effect for dropdown state
79
  useEffect(() => {
@@ -211,6 +216,9 @@ export default function LandingPage({
211
  console.error('Failed to load languages:', error);
212
  }
213
  };
 
 
 
214
 
215
  const loadTrendingApps = async () => {
216
  try {
@@ -225,10 +233,31 @@ export default function LandingPage({
225
  e.preventDefault();
226
  if (prompt.trim() && isAuthenticated) {
227
  onStart(prompt.trim(), selectedLanguage, selectedModel);
 
 
228
  } else if (!isAuthenticated) {
229
  alert('Please sign in with HuggingFace first!');
230
  }
231
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
 
233
  const formatLanguageName = (lang: Language) => {
234
  if (lang === 'html') return 'HTML';
@@ -645,6 +674,29 @@ Note: After generating the redesign, I will create a Pull Request on the origina
645
  {/* Simple prompt form */}
646
  <form onSubmit={handleSubmit} className="relative w-full mb-8">
647
  <div className="relative bg-[#2d2d30] rounded-2xl border border-[#424245] shadow-2xl">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  {/* Textarea */}
649
  <textarea
650
  value={prompt}
@@ -1012,6 +1064,31 @@ Note: After generating the redesign, I will create a Pull Request on the origina
1012
  </div>
1013
  </div>
1014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1015
  {/* Send button on the right - Apple style */}
1016
  <button
1017
  type="submit"
 
1
  'use client';
2
 
3
  import { useState, useEffect, useRef } from 'react';
4
+ import Image from 'next/image';
5
  import { apiClient } from '@/lib/api';
6
  import {
7
  initializeOAuth,
 
31
  onImport,
32
  isAuthenticated,
33
  initialLanguage = 'html',
34
+ initialModel = 'zai-org/GLM-4.6V:zai-org',
35
  onAuthChange,
36
  setPendingPR,
37
  pendingPRRef
 
75
  const [isRedesigning, setIsRedesigning] = useState(false);
76
  const [redesignError, setRedesignError] = useState('');
77
  const [createPR, setCreatePR] = useState(false); // Default to normal redesign (not PR)
78
+
79
+ // Image upload state
80
+ const [uploadedImageUrl, setUploadedImageUrl] = useState<string | null>(null);
81
+ const fileInputRef = useRef<HTMLInputElement>(null);
82
 
83
  // Debug effect for dropdown state
84
  useEffect(() => {
 
216
  console.error('Failed to load languages:', error);
217
  }
218
  };
219
+
220
+ // Check if current model supports images
221
+ const currentModelSupportsImages = models.find(m => m.id === selectedModel)?.supports_images || false;
222
 
223
  const loadTrendingApps = async () => {
224
  try {
 
233
  e.preventDefault();
234
  if (prompt.trim() && isAuthenticated) {
235
  onStart(prompt.trim(), selectedLanguage, selectedModel);
236
+ // Clear image after sending
237
+ setUploadedImageUrl(null);
238
  } else if (!isAuthenticated) {
239
  alert('Please sign in with HuggingFace first!');
240
  }
241
  };
242
+
243
+ const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
244
+ const file = e.target.files?.[0];
245
+ if (file) {
246
+ const reader = new FileReader();
247
+ reader.onload = (event) => {
248
+ const imageUrl = event.target?.result as string;
249
+ setUploadedImageUrl(imageUrl);
250
+ };
251
+ reader.readAsDataURL(file);
252
+ }
253
+ };
254
+
255
+ const removeImage = () => {
256
+ setUploadedImageUrl(null);
257
+ if (fileInputRef.current) {
258
+ fileInputRef.current.value = '';
259
+ }
260
+ };
261
 
262
  const formatLanguageName = (lang: Language) => {
263
  if (lang === 'html') return 'HTML';
 
674
  {/* Simple prompt form */}
675
  <form onSubmit={handleSubmit} className="relative w-full mb-8">
676
  <div className="relative bg-[#2d2d30] rounded-2xl border border-[#424245] shadow-2xl">
677
+ {/* Image Preview */}
678
+ {uploadedImageUrl && (
679
+ <div className="px-4 pt-3">
680
+ <div className="relative inline-block">
681
+ <Image
682
+ src={uploadedImageUrl}
683
+ alt="Upload preview"
684
+ width={120}
685
+ height={120}
686
+ className="rounded-lg object-cover"
687
+ unoptimized
688
+ />
689
+ <button
690
+ type="button"
691
+ onClick={removeImage}
692
+ className="absolute -top-2 -right-2 w-6 h-6 bg-red-500 text-white rounded-full hover:bg-red-600 transition-all flex items-center justify-center text-xs font-bold"
693
+ >
694
+ ×
695
+ </button>
696
+ </div>
697
+ </div>
698
+ )}
699
+
700
  {/* Textarea */}
701
  <textarea
702
  value={prompt}
 
1064
  </div>
1065
  </div>
1066
 
1067
+ {/* Image Upload Button (only if model supports images) */}
1068
+ {currentModelSupportsImages && (
1069
+ <>
1070
+ <input
1071
+ ref={fileInputRef}
1072
+ type="file"
1073
+ accept="image/*"
1074
+ onChange={handleImageUpload}
1075
+ className="hidden"
1076
+ disabled={!isAuthenticated}
1077
+ />
1078
+ <button
1079
+ type="button"
1080
+ onClick={() => fileInputRef.current?.click()}
1081
+ disabled={!isAuthenticated}
1082
+ className="p-2 bg-[#1d1d1f] text-[#f5f5f7] rounded-full hover:bg-[#424245] disabled:opacity-30 disabled:cursor-not-allowed transition-all active:scale-95"
1083
+ title="Upload image"
1084
+ >
1085
+ <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2.5}>
1086
+ <path strokeLinecap="round" strokeLinejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" />
1087
+ </svg>
1088
+ </button>
1089
+ </>
1090
+ )}
1091
+
1092
  {/* Send button on the right - Apple style */}
1093
  <button
1094
  type="submit"