Quick Snap: use native camera/gallery input instead of custom camera
The custom in-app CameraCapture failed on the native APK ("Could not open
the camera") due to Capacitor camera permission plumbing, and a single
photo is all a spot snap needs. Replace the Quick Snap flow on the map with
a hidden native file input (accept="image/*" capture="environment"): one
tap opens the OS camera/gallery, the chosen photo feeds the existing upload
→ create-spot flow unchanged. Works identically on web and native, no
plugin/permission fragility. Removes the CameraCapture usage + import from
MapPage (component still used by CreateSpotPage).
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
cc2e35f569
commit
87c710bf4a
1 changed files with 26 additions and 13 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { useState, useMemo, useEffect, lazy, Suspense } from 'react';
|
import { useState, useMemo, useEffect, useRef, lazy, Suspense } from 'react';
|
||||||
import { useSeoMeta } from '@unhead/react';
|
import { useSeoMeta } from '@unhead/react';
|
||||||
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
|
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
import { Layout } from '@/components/Layout';
|
import { Layout } from '@/components/Layout';
|
||||||
|
|
@ -77,7 +77,6 @@ import {
|
||||||
Calendar,
|
Calendar,
|
||||||
MessageCircle,
|
MessageCircle,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { CameraCapture } from '@/components/CameraCapture';
|
|
||||||
import { SpotChat } from '@/components/SpotChat';
|
import { SpotChat } from '@/components/SpotChat';
|
||||||
import { useUploadFile } from '@/hooks/useUploadFile';
|
import { useUploadFile } from '@/hooks/useUploadFile';
|
||||||
import { useToast } from '@/hooks/useToast';
|
import { useToast } from '@/hooks/useToast';
|
||||||
|
|
@ -605,8 +604,11 @@ export default function MapPage() {
|
||||||
// Mobile layers popover
|
// Mobile layers popover
|
||||||
const [layersOpen, setLayersOpen] = useState(false);
|
const [layersOpen, setLayersOpen] = useState(false);
|
||||||
|
|
||||||
// Quick camera capture
|
// Quick Snap — uses the native OS camera/gallery picker via a file input.
|
||||||
const [showQuickCamera, setShowQuickCamera] = useState(false);
|
// This is more robust than a custom in-app camera (no Capacitor camera
|
||||||
|
// permission plumbing) and works identically on web and native. A single
|
||||||
|
// photo is all a spot snap needs.
|
||||||
|
const quickSnapInputRef = useRef<HTMLInputElement>(null);
|
||||||
const { mutateAsync: uploadFile, isPending: isUploadingQuickPhoto } = useUploadFile();
|
const { mutateAsync: uploadFile, isPending: isUploadingQuickPhoto } = useUploadFile();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
|
@ -760,13 +762,20 @@ export default function MapPage() {
|
||||||
navigate(`/create-spot?lat=${lat.toFixed(6)}&lng=${lng.toFixed(6)}`);
|
navigate(`/create-spot?lat=${lat.toFixed(6)}&lng=${lng.toFixed(6)}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Native file-input change → hand the chosen photo to the upload flow.
|
||||||
|
const handleQuickSnapInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
// Reset the input so picking the same file again still fires onChange.
|
||||||
|
e.target.value = '';
|
||||||
|
if (file) handleQuickCameraCapture(file);
|
||||||
|
};
|
||||||
|
|
||||||
// Handle quick camera capture - upload and navigate to create spot
|
// Handle quick camera capture - upload and navigate to create spot
|
||||||
const handleQuickCameraCapture = async (file: File) => {
|
const handleQuickCameraCapture = async (file: File) => {
|
||||||
try {
|
try {
|
||||||
const tags = await uploadFile(file);
|
const tags = await uploadFile(file);
|
||||||
const url = tags[0]?.[1];
|
const url = tags[0]?.[1];
|
||||||
if (url) {
|
if (url) {
|
||||||
setShowQuickCamera(false);
|
|
||||||
// Store the captured image URL in sessionStorage for the create spot page
|
// Store the captured image URL in sessionStorage for the create spot page
|
||||||
sessionStorage.setItem('quickCaptureImage', url);
|
sessionStorage.setItem('quickCaptureImage', url);
|
||||||
// Get current location and navigate to create spot
|
// Get current location and navigate to create spot
|
||||||
|
|
@ -1700,9 +1709,9 @@ export default function MapPage() {
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
{/* Quick Snap */}
|
{/* Quick Snap — opens the native camera/gallery picker */}
|
||||||
<button
|
<button
|
||||||
onClick={() => { setAddDialOpen(false); setShowQuickCamera(true); }}
|
onClick={() => { setAddDialOpen(false); quickSnapInputRef.current?.click(); }}
|
||||||
className="flex items-center gap-2.5 animate-in fade-in slide-in-from-bottom-2 duration-200"
|
className="flex items-center gap-2.5 animate-in fade-in slide-in-from-bottom-2 duration-200"
|
||||||
style={{ animationDelay: '200ms' }}
|
style={{ animationDelay: '200ms' }}
|
||||||
>
|
>
|
||||||
|
|
@ -1793,12 +1802,16 @@ export default function MapPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Quick Camera Capture Dialog */}
|
{/* Quick Snap — hidden native camera/gallery input.
|
||||||
<CameraCapture
|
`capture="environment"` hints the rear camera on phones; on desktop
|
||||||
open={showQuickCamera}
|
it falls back to a normal file picker. Single photo is all we need. */}
|
||||||
onOpenChange={setShowQuickCamera}
|
<input
|
||||||
onCapture={handleQuickCameraCapture}
|
ref={quickSnapInputRef}
|
||||||
isUploading={isUploadingQuickPhoto}
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
capture="environment"
|
||||||
|
className="hidden"
|
||||||
|
onChange={handleQuickSnapInput}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Spot Bottom Sheet — slides up when a marker is tapped, map stays visible */}
|
{/* Spot Bottom Sheet — slides up when a marker is tapped, map stays visible */}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue