fix: resolve 401 Unauthorized in Gemini editUVLayer by properly passing auth token, update loading UI with grayscale/blur, fix WebGLShadowMap deprecation warnings
Build and Deploy / build-and-push (push) Successful in 28s
Build and Deploy / build-and-push (push) Successful in 28s
This commit is contained in:
@@ -29,7 +29,7 @@ const ModelPreview = ({ url }: { url: string }) => {
|
|||||||
if (!model) return <div className="absolute inset-0 flex items-center justify-center"><Loader2 className="w-8 h-8 animate-spin text-zinc-500" /></div>;
|
if (!model) return <div className="absolute inset-0 flex items-center justify-center"><Loader2 className="w-8 h-8 animate-spin text-zinc-500" /></div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Canvas shadows camera={{ position: [0, 1.5, 3], fov: 45 }}>
|
<Canvas shadows={{ type: THREE.PCFShadowMap }} camera={{ position: [0, 1.5, 3], fov: 45 }}>
|
||||||
<Stage environment="studio" intensity={0.5}>
|
<Stage environment="studio" intensity={0.5}>
|
||||||
<primitive object={model} />
|
<primitive object={model} />
|
||||||
</Stage>
|
</Stage>
|
||||||
@@ -39,7 +39,7 @@ const ModelPreview = ({ url }: { url: string }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ImageTo3DModal: React.FC<ImageTo3DModalProps> = ({ isOpen, onClose, onPushToApp }) => {
|
export const ImageTo3DModal: React.FC<ImageTo3DModalProps> = ({ isOpen, onClose, onPushToApp }) => {
|
||||||
const { profile, setProfile, token } = useAuthStore();
|
const { profile, setProfile } = useAuthStore();
|
||||||
const [meshyApiKey, setMeshyApiKey] = useState('');
|
const [meshyApiKey, setMeshyApiKey] = useState('');
|
||||||
|
|
||||||
// Image states
|
// Image states
|
||||||
@@ -97,6 +97,7 @@ export const ImageTo3DModal: React.FC<ImageTo3DModalProps> = ({ isOpen, onClose,
|
|||||||
setCleanedImagePreview(null);
|
setCleanedImagePreview(null);
|
||||||
try {
|
try {
|
||||||
const base64 = await fileToDataUrl(fileToClean);
|
const base64 = await fileToDataUrl(fileToClean);
|
||||||
|
const token = localStorage.getItem('auth_token') || '';
|
||||||
const newUrl = await editUVLayer("Remove the background and make it solid transparent or white. Also carefully remove all text, labels, logos, and stickers, keeping the product as a perfectly clean, plain, unbranded object.", base64, token);
|
const newUrl = await editUVLayer("Remove the background and make it solid transparent or white. Also carefully remove all text, labels, logos, and stickers, keeping the product as a perfectly clean, plain, unbranded object.", base64, token);
|
||||||
|
|
||||||
const res = await fetch(newUrl);
|
const res = await fetch(newUrl);
|
||||||
@@ -300,10 +301,13 @@ export const ImageTo3DModal: React.FC<ImageTo3DModalProps> = ({ isOpen, onClose,
|
|||||||
{/* Cleaned Image */}
|
{/* Cleaned Image */}
|
||||||
<div className="flex-1 relative border-2 border-solid border-zinc-700 rounded-xl overflow-hidden bg-zinc-900/50 flex items-center justify-center group">
|
<div className="flex-1 relative border-2 border-solid border-zinc-700 rounded-xl overflow-hidden bg-zinc-900/50 flex items-center justify-center group">
|
||||||
{isCleaningImage ? (
|
{isCleaningImage ? (
|
||||||
<div className="flex flex-col items-center text-zinc-400 gap-3">
|
<>
|
||||||
<Loader2 size={28} className="animate-spin text-blue-500" />
|
<img src={originalImagePreview} alt="Original Grayscale" className="absolute inset-0 w-full h-full object-contain p-2 opacity-30 grayscale blur-sm" />
|
||||||
<span className="text-sm font-medium">AI Cleaning...</span>
|
<div className="absolute inset-0 flex flex-col items-center justify-center text-zinc-300 gap-3 bg-black/40 z-10">
|
||||||
</div>
|
<Loader2 size={28} className="animate-spin text-blue-500" />
|
||||||
|
<span className="text-sm font-medium">AI Cleaning Image...</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
) : cleanedImagePreview ? (
|
) : cleanedImagePreview ? (
|
||||||
<>
|
<>
|
||||||
<img src={cleanedImagePreview} alt="Cleaned" className="w-full h-full object-contain p-2" />
|
<img src={cleanedImagePreview} alt="Cleaned" className="w-full h-full object-contain p-2" />
|
||||||
@@ -405,22 +409,23 @@ export const ImageTo3DModal: React.FC<ImageTo3DModalProps> = ({ isOpen, onClose,
|
|||||||
<h3 className="text-sm font-bold text-zinc-200">3D Preview</h3>
|
<h3 className="text-sm font-bold text-zinc-200">3D Preview</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 relative flex items-center justify-center">
|
<div className="flex-1 relative flex items-center justify-center overflow-hidden">
|
||||||
{generatedModelUrl ? (
|
{isGenerating ? (
|
||||||
|
<>
|
||||||
|
{cleanedImagePreview || originalImagePreview ? (
|
||||||
|
<img src={(cleanedImagePreview || originalImagePreview) as string} alt="Generating Base" className="absolute inset-0 w-full h-full object-contain p-8 opacity-20 grayscale blur-md scale-110" />
|
||||||
|
) : null}
|
||||||
|
<div className="absolute inset-0 flex flex-col items-center justify-center text-zinc-300 bg-black/60 z-20">
|
||||||
|
<Loader2 size={36} className="animate-spin text-blue-500 mb-4" />
|
||||||
|
<p className="text-sm font-medium text-zinc-200">{progressMessage}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : generatedModelUrl ? (
|
||||||
<ModelPreview url={generatedModelUrl} />
|
<ModelPreview url={generatedModelUrl} />
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col items-center justify-center text-zinc-600 p-6 text-center">
|
<div className="flex flex-col items-center justify-center text-zinc-600 p-6 text-center">
|
||||||
{isGenerating ? (
|
<Box size={32} className="mb-3 opacity-50" />
|
||||||
<>
|
<p className="text-sm">Your 3D model will appear here</p>
|
||||||
<Loader2 size={32} className="animate-spin text-blue-500 mb-4" />
|
|
||||||
<p className="text-sm font-medium text-zinc-300">{progressMessage}</p>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Box size={32} className="mb-3 opacity-50" />
|
|
||||||
<p className="text-sm">Your 3D model will appear here</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function UVEditor({ onClose, onSave, targetObject, loadedModel, sceneObje
|
|||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
const dragRef = useRef<{ handle: Handle; startX: number; startY: number; layer: Layer } | null>(null);
|
const dragRef = useRef<{ handle: Handle; startX: number; startY: number; layer: Layer } | null>(null);
|
||||||
|
|
||||||
const token = useAuthStore(state => state.token);
|
const token = localStorage.getItem('auth_token') || '';
|
||||||
const [aiPrompt, setAiPrompt] = useState("");
|
const [aiPrompt, setAiPrompt] = useState("");
|
||||||
const [isEditingLayer, setIsEditingLayer] = useState(false);
|
const [isEditingLayer, setIsEditingLayer] = useState(false);
|
||||||
const [aiPreviewUrl, setAiPreviewUrl] = useState<string | null>(null);
|
const [aiPreviewUrl, setAiPreviewUrl] = useState<string | null>(null);
|
||||||
@@ -596,7 +596,7 @@ export function UVEditor({ onClose, onSave, targetObject, loadedModel, sceneObje
|
|||||||
<span className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">3D Preview</span>
|
<span className="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">3D Preview</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full aspect-square bg-zinc-950 rounded-xl overflow-hidden border border-zinc-800">
|
<div className="w-full aspect-square bg-zinc-950 rounded-xl overflow-hidden border border-zinc-800">
|
||||||
<Canvas shadows camera={{ position: [2, 2, 2], fov: 45 }}>
|
<Canvas shadows={{ type: THREE.PCFShadowMap }} camera={{ position: [2, 2, 2], fov: 45 }}>
|
||||||
<ambientLight intensity={0.5} />
|
<ambientLight intensity={0.5} />
|
||||||
<directionalLight position={[5, 5, 5]} intensity={1} castShadow />
|
<directionalLight position={[5, 5, 5]} intensity={1} castShadow />
|
||||||
<Environment preset="studio" />
|
<Environment preset="studio" />
|
||||||
|
|||||||
@@ -2451,7 +2451,7 @@ export default function Editor() {
|
|||||||
<div className="flex-1 relative bg-zinc-950">
|
<div className="flex-1 relative bg-zinc-950">
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Canvas
|
<Canvas
|
||||||
shadows
|
shadows={{ type: THREE.PCFShadowMap }}
|
||||||
dpr={[1, 2]}
|
dpr={[1, 2]}
|
||||||
gl={{ preserveDrawingBuffer: true, alpha: true }}
|
gl={{ preserveDrawingBuffer: true, alpha: true }}
|
||||||
performance={{ min: 0.5 }}
|
performance={{ min: 0.5 }}
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ export default function SparkPlug() {
|
|||||||
) : (
|
) : (
|
||||||
<div className="w-full h-[400px] bg-zinc-900 rounded-xl overflow-hidden relative border border-zinc-800 flex flex-col items-center justify-center">
|
<div className="w-full h-[400px] bg-zinc-900 rounded-xl overflow-hidden relative border border-zinc-800 flex flex-col items-center justify-center">
|
||||||
{generatedGlbUrl ? (
|
{generatedGlbUrl ? (
|
||||||
<Canvas shadows dpr={[1, 2]} camera={{ position: [0, 0, 4], fov: 45 }}>
|
<Canvas shadows={{ type: THREE.PCFShadowMap }} dpr={[1, 2]} camera={{ position: [0, 0, 4], fov: 45 }}>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<Stage environment="studio" intensity={0.5}>
|
<Stage environment="studio" intensity={0.5}>
|
||||||
<ModelPreview url={generatedGlbUrl} />
|
<ModelPreview url={generatedGlbUrl} />
|
||||||
|
|||||||
Reference in New Issue
Block a user