fix(DeviceDetailOverlay): notify parent on browsing state changes and improve portal usage in DeviceCard
This commit is contained in:
parent
3088f1801c
commit
7c25680091
|
|
@ -1,4 +1,5 @@
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
import { SettingsInput } from './ui/settings-input';
|
import { SettingsInput } from './ui/settings-input';
|
||||||
import { X, Printer, HardDrive, Network, Box, FolderOpen, MoreVertical, RotateCcw } from 'lucide-react';
|
import { X, Printer, HardDrive, Network, Box, FolderOpen, MoreVertical, RotateCcw } from 'lucide-react';
|
||||||
import { motion, AnimatePresence } from 'motion/react';
|
import { motion, AnimatePresence } from 'motion/react';
|
||||||
|
|
@ -48,13 +49,19 @@ interface DeviceCardProps {
|
||||||
config: any;
|
config: any;
|
||||||
setConfig: (c: any) => void;
|
setConfig: (c: any) => void;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
onBrowsingChange?: (browsing: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeviceCard({ device, config, setConfig, isActive }: DeviceCardProps) {
|
function DeviceCard({ device, config, setConfig, isActive, onBrowsingChange }: DeviceCardProps) {
|
||||||
const [browsingField, setBrowsingField] = useState<'url' | 'base_url' | 'cache' | null>(null);
|
const [browsingField, setBrowsingField] = useState<'url' | 'base_url' | 'cache' | null>(null);
|
||||||
const [mediaSetFiles, setMediaSetFiles] = useState<MediaSetEntry[] | null>(null);
|
const [mediaSetFiles, setMediaSetFiles] = useState<MediaSetEntry[] | null>(null);
|
||||||
const detectTokenRef = useRef(0);
|
const detectTokenRef = useRef(0);
|
||||||
|
|
||||||
|
// Notify parent when browser opens/closes so it can lock slide scroll.
|
||||||
|
useEffect(() => {
|
||||||
|
onBrowsingChange?.(browsingField !== null);
|
||||||
|
}, [browsingField, onBrowsingChange]);
|
||||||
|
|
||||||
// Close any open browser when swiped away.
|
// Close any open browser when swiped away.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isActive) setBrowsingField(null);
|
if (!isActive) setBrowsingField(null);
|
||||||
|
|
@ -332,7 +339,7 @@ function DeviceCard({ device, config, setConfig, isActive }: DeviceCardProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{browsingField && (
|
{browsingField && createPortal(
|
||||||
<MediaBrowser
|
<MediaBrowser
|
||||||
currentPath={
|
currentPath={
|
||||||
browsingField === 'cache' ? (deviceData.cache || '/') :
|
browsingField === 'cache' ? (deviceData.cache || '/') :
|
||||||
|
|
@ -348,7 +355,8 @@ function DeviceCard({ device, config, setConfig, isActive }: DeviceCardProps) {
|
||||||
setBrowsingField(null);
|
setBrowsingField(null);
|
||||||
}}
|
}}
|
||||||
onClose={() => setBrowsingField(null)}
|
onClose={() => setBrowsingField(null)}
|
||||||
/>
|
/>,
|
||||||
|
document.body
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
@ -366,6 +374,7 @@ export default function DeviceDetailOverlay({
|
||||||
}: DeviceDetailOverlayProps) {
|
}: DeviceDetailOverlayProps) {
|
||||||
const [activeIndex, setActiveIndex] = useState(initialIndex);
|
const [activeIndex, setActiveIndex] = useState(initialIndex);
|
||||||
const [showCommandMenu, setShowCommandMenu] = useState(false);
|
const [showCommandMenu, setShowCommandMenu] = useState(false);
|
||||||
|
const [isBrowsing, setIsBrowsing] = useState(false);
|
||||||
const swiperRef = useRef<SwiperType | null>(null);
|
const swiperRef = useRef<SwiperType | null>(null);
|
||||||
|
|
||||||
const activeDevice = devices[activeIndex] ?? devices[0];
|
const activeDevice = devices[activeIndex] ?? devices[0];
|
||||||
|
|
@ -461,12 +470,13 @@ export default function DeviceDetailOverlay({
|
||||||
style={{ height: '100%' }}
|
style={{ height: '100%' }}
|
||||||
>
|
>
|
||||||
{devices.map((device, i) => (
|
{devices.map((device, i) => (
|
||||||
<SwiperSlide key={device.id} style={{ overflowY: 'auto', height: '100%' }}>
|
<SwiperSlide key={device.id} style={{ overflowY: isBrowsing && i === activeIndex ? 'hidden' : 'auto', height: '100%' }}>
|
||||||
<DeviceCard
|
<DeviceCard
|
||||||
device={device}
|
device={device}
|
||||||
config={config}
|
config={config}
|
||||||
setConfig={setConfig}
|
setConfig={setConfig}
|
||||||
isActive={i === activeIndex}
|
isActive={i === activeIndex}
|
||||||
|
onBrowsingChange={i === activeIndex ? setIsBrowsing : undefined}
|
||||||
/>
|
/>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ export default function MediaBrowser({ currentPath, onSelect, onClose }: MediaBr
|
||||||
const pathParts = (path ?? '').split('/').filter(Boolean);
|
const pathParts = (path ?? '').split('/').filter(Boolean);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="fixed inset-0 bg-black/50 z-50 flex items-end" onClick={onClose}>
|
<div className="fixed inset-0 bg-black/50 z-50 flex items-end" onClick={onClose}>
|
||||||
<div className="bg-white w-full max-h-[80vh] rounded-t-xl flex flex-col" onClick={e => e.stopPropagation()}>
|
<div className="bg-white w-full max-h-[80vh] rounded-t-xl flex flex-col" onClick={e => e.stopPropagation()}>
|
||||||
<div className="sticky top-0 bg-white border-b border-neutral-200 p-4">
|
<div className="sticky top-0 bg-white border-b border-neutral-200 p-4">
|
||||||
|
|
@ -219,6 +220,8 @@ export default function MediaBrowser({ currentPath, onSelect, onClose }: MediaBr
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
open={confirm !== null}
|
open={confirm !== null}
|
||||||
{...(confirm ?? { title: '', onConfirm: () => {} })}
|
{...(confirm ?? { title: '', onConfirm: () => {} })}
|
||||||
|
|
@ -254,6 +257,6 @@ export default function MediaBrowser({ currentPath, onSelect, onClose }: MediaBr
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user