Tina Tarighian
commited on
Commit
·
7fecabc
1
Parent(s):
060842a
fixing mobile
Browse files- components/MainContent.js +2 -2
- components/PromptEditor.js +56 -47
- hooks/useDeviceAndCanvas.js +10 -1
- pages/index.js +5 -3
components/MainContent.js
CHANGED
|
@@ -34,7 +34,7 @@ const MainContent = ({
|
|
| 34 |
createPopParticles
|
| 35 |
}) => {
|
| 36 |
return (
|
| 37 |
-
|
| 38 |
{/* Conditionally render Prompt Editor based on device */}
|
| 39 |
{!isMobile && (
|
| 40 |
<PromptEditor
|
|
@@ -102,7 +102,7 @@ const MainContent = ({
|
|
| 102 |
isMobile={isMobile}
|
| 103 |
/>
|
| 104 |
)}
|
| 105 |
-
|
| 106 |
);
|
| 107 |
};
|
| 108 |
|
|
|
|
| 34 |
createPopParticles
|
| 35 |
}) => {
|
| 36 |
return (
|
| 37 |
+
<div className="w-full flex flex-col items-center space-y-2">
|
| 38 |
{/* Conditionally render Prompt Editor based on device */}
|
| 39 |
{!isMobile && (
|
| 40 |
<PromptEditor
|
|
|
|
| 102 |
isMobile={isMobile}
|
| 103 |
/>
|
| 104 |
)}
|
| 105 |
+
</div>
|
| 106 |
);
|
| 107 |
};
|
| 108 |
|
components/PromptEditor.js
CHANGED
|
@@ -2,15 +2,20 @@ import { useState } from 'react';
|
|
| 2 |
|
| 3 |
const PromptEditor = ({ customPrompt, setCustomPrompt, isMac, isMobile }) => {
|
| 4 |
const [isEditingPrompt, setIsEditingPrompt] = useState(false);
|
|
|
|
| 5 |
const [tempPrompt, setTempPrompt] = useState("");
|
| 6 |
|
| 7 |
return (
|
| 8 |
-
<div className={`w-full max-w-4xl ${isMobile ? 'mt-
|
| 9 |
<div className="flex justify-between items-center mb-1">
|
| 10 |
-
<label
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
</label>
|
| 13 |
-
{!isEditingPrompt ? (
|
| 14 |
<button
|
| 15 |
onClick={() => {
|
| 16 |
setTempPrompt(customPrompt);
|
|
@@ -26,49 +31,53 @@ const PromptEditor = ({ customPrompt, setCustomPrompt, isMac, isMobile }) => {
|
|
| 26 |
) : null}
|
| 27 |
</div>
|
| 28 |
|
| 29 |
-
{
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
)}
|
| 73 |
</div>
|
| 74 |
);
|
|
|
|
| 2 |
|
| 3 |
const PromptEditor = ({ customPrompt, setCustomPrompt, isMac, isMobile }) => {
|
| 4 |
const [isEditingPrompt, setIsEditingPrompt] = useState(false);
|
| 5 |
+
const [isCollapsed, setIsCollapsed] = useState(isMobile); // Collapsed by default on mobile
|
| 6 |
const [tempPrompt, setTempPrompt] = useState("");
|
| 7 |
|
| 8 |
return (
|
| 9 |
+
<div className={`w-full max-w-4xl ${isMobile ? 'mt-2 mb-4' : 'mb-4'}`}>
|
| 10 |
<div className="flex justify-between items-center mb-1">
|
| 11 |
+
<label
|
| 12 |
+
htmlFor="system-prompt"
|
| 13 |
+
className={`block ${isMobile ? 'text-xs' : 'text-sm'} font-medium text-gray-700 cursor-pointer`}
|
| 14 |
+
onClick={() => isMobile && setIsCollapsed(!isCollapsed)}
|
| 15 |
+
>
|
| 16 |
+
System Prompt {isMobile && (isCollapsed ? '▼' : '▲')}
|
| 17 |
</label>
|
| 18 |
+
{!isEditingPrompt && !isCollapsed ? (
|
| 19 |
<button
|
| 20 |
onClick={() => {
|
| 21 |
setTempPrompt(customPrompt);
|
|
|
|
| 31 |
) : null}
|
| 32 |
</div>
|
| 33 |
|
| 34 |
+
{!isCollapsed && (
|
| 35 |
+
<>
|
| 36 |
+
{isEditingPrompt ? (
|
| 37 |
+
<div>
|
| 38 |
+
<textarea
|
| 39 |
+
id="system-prompt"
|
| 40 |
+
value={tempPrompt}
|
| 41 |
+
onChange={(e) => setTempPrompt(e.target.value)}
|
| 42 |
+
onKeyDown={(e) => {
|
| 43 |
+
// Save on Ctrl+Enter or Cmd+Enter
|
| 44 |
+
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
|
| 45 |
+
e.preventDefault();
|
| 46 |
+
setCustomPrompt(tempPrompt);
|
| 47 |
+
setIsEditingPrompt(false);
|
| 48 |
+
}
|
| 49 |
+
}}
|
| 50 |
+
className={`w-full p-3 border border-gray-300 rounded-lg shadow-sm focus:ring-blue-500 focus:border-blue-500 ${isMobile ? 'text-xs' : 'text-sm'}`}
|
| 51 |
+
rows={isMobile ? 3 : 4}
|
| 52 |
+
placeholder="Enter your custom prompt for Gemini..."
|
| 53 |
+
/>
|
| 54 |
+
<div className="flex justify-end mt-2 space-x-2">
|
| 55 |
+
<span className={`${isMobile ? 'text-xxs' : 'text-xs'} text-gray-500 self-center mr-auto`}>
|
| 56 |
+
Tip: Press {isMac ? '⌘' : 'Ctrl'}+Enter to save
|
| 57 |
+
</span>
|
| 58 |
+
<button
|
| 59 |
+
onClick={() => setIsEditingPrompt(false)}
|
| 60 |
+
className={`px-3 py-1 ${isMobile ? 'text-xs' : 'text-sm'} text-gray-600 border border-gray-300 rounded-md hover:bg-gray-100`}
|
| 61 |
+
>
|
| 62 |
+
Cancel
|
| 63 |
+
</button>
|
| 64 |
+
<button
|
| 65 |
+
onClick={() => {
|
| 66 |
+
setCustomPrompt(tempPrompt);
|
| 67 |
+
setIsEditingPrompt(false);
|
| 68 |
+
}}
|
| 69 |
+
className={`px-3 py-1 ${isMobile ? 'text-xs' : 'text-sm'} text-white bg-blue-600 rounded-md hover:bg-blue-700`}
|
| 70 |
+
>
|
| 71 |
+
Save
|
| 72 |
+
</button>
|
| 73 |
+
</div>
|
| 74 |
+
</div>
|
| 75 |
+
) : (
|
| 76 |
+
<div className={`p-2 bg-gray-50 border border-gray-200 rounded-lg ${isMobile ? 'text-xs' : 'text-sm'} text-gray-800 whitespace-pre-wrap ${isMobile ? 'max-h-20' : 'max-h-32'} overflow-y-auto`}>
|
| 77 |
+
{customPrompt}
|
| 78 |
+
</div>
|
| 79 |
+
)}
|
| 80 |
+
</>
|
| 81 |
)}
|
| 82 |
</div>
|
| 83 |
);
|
hooks/useDeviceAndCanvas.js
CHANGED
|
@@ -45,7 +45,16 @@ const useDeviceAndCanvas = () => {
|
|
| 45 |
const containerWidth = document.querySelector('.canvas-container')?.clientWidth || window.innerWidth;
|
| 46 |
// Set maximum width for the canvas - increased for desktop
|
| 47 |
const maxWidth = Math.min(containerWidth, isMobile ? 640 : 960);
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
setCanvasWidth(maxWidth);
|
| 51 |
setCanvasHeight(height);
|
|
|
|
| 45 |
const containerWidth = document.querySelector('.canvas-container')?.clientWidth || window.innerWidth;
|
| 46 |
// Set maximum width for the canvas - increased for desktop
|
| 47 |
const maxWidth = Math.min(containerWidth, isMobile ? 640 : 960);
|
| 48 |
+
let height = maxWidth / aspectRatio;
|
| 49 |
+
|
| 50 |
+
// Limit height on mobile to ensure system prompt is visible without scrolling
|
| 51 |
+
if (isMobile) {
|
| 52 |
+
const viewportHeight = window.innerHeight;
|
| 53 |
+
// Use a fixed height on mobile that's appropriate for most devices
|
| 54 |
+
// This ensures the camera and prompt are both visible without scrolling
|
| 55 |
+
const maxMobileHeight = Math.min(viewportHeight * 0.5, 350); // 50% of viewport or 350px max
|
| 56 |
+
height = Math.min(height, maxMobileHeight);
|
| 57 |
+
}
|
| 58 |
|
| 59 |
setCanvasWidth(maxWidth);
|
| 60 |
setCanvasHeight(height);
|
pages/index.js
CHANGED
|
@@ -11,7 +11,7 @@ const inter = Inter({ subsets: ['latin'] });
|
|
| 11 |
|
| 12 |
const Header = () => {
|
| 13 |
return (
|
| 14 |
-
<div className="sticky top-0 left-0 right-0 w-full bg-white p-
|
| 15 |
<div className="w-full flex justify-between items-center text-base max-w-7xl mx-auto">
|
| 16 |
<div className="text-gray-500">
|
| 17 |
<span className="text-black font-bold text-lg mr-2">HandSpew</span>
|
|
@@ -47,8 +47,10 @@ export default function Home() {
|
|
| 47 |
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" />
|
| 48 |
</Head>
|
| 49 |
<Header />
|
| 50 |
-
<main className="flex min-h-screen flex-col items-center justify-start p-
|
| 51 |
-
<
|
|
|
|
|
|
|
| 52 |
</main>
|
| 53 |
</>
|
| 54 |
);
|
|
|
|
| 11 |
|
| 12 |
const Header = () => {
|
| 13 |
return (
|
| 14 |
+
<div className="sticky top-0 left-0 right-0 w-full bg-white p-3 z-50 shadow-sm">
|
| 15 |
<div className="w-full flex justify-between items-center text-base max-w-7xl mx-auto">
|
| 16 |
<div className="text-gray-500">
|
| 17 |
<span className="text-black font-bold text-lg mr-2">HandSpew</span>
|
|
|
|
| 47 |
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" />
|
| 48 |
</Head>
|
| 49 |
<Header />
|
| 50 |
+
<main className="flex min-h-screen flex-col items-center justify-start p-3 bg-white font-['Google_Sans',sans-serif] pt-16">
|
| 51 |
+
<div className="w-full max-w-4xl flex flex-col items-center">
|
| 52 |
+
<HandDetector />
|
| 53 |
+
</div>
|
| 54 |
</main>
|
| 55 |
</>
|
| 56 |
);
|