mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-02-15 21:27:35 +00:00
refactor: extract device detection into hook and localize PWA handling to Sidebar
- Add new `useDeviceSettings` hook (`src/hooks/useDeviceSettings.ts`) to centralize
device-related state:
- exposes `isMobile` and `isPWA`
- supports options: `mobileBreakpoint`, `trackMobile`, `trackPWA`
- listens to window resize for mobile updates
- listens to `display-mode: standalone` changes for PWA updates
- includes `matchMedia.addListener/removeListener` fallback for older environments
- Update `AppContent` (`src/App.jsx`) to consume `isMobile` from
`useDeviceSettings({ trackPWA: false })`:
- remove local `isMobile` state/effect
- remove local `isPWA` state/effect
- keep existing `isMobile` behavior for layout and mobile sidebar flow
- stop passing `isPWA` into `Sidebar` props
- Update `Sidebar` (`src/components/Sidebar.jsx`) to own PWA detection:
- consume `isPWA` from `useDeviceSettings({ trackMobile: false })`
- add effect to toggle `pwa-mode` class on `document.documentElement` and `document.body`
- retain use of `isMobile` prop from `App` for sidebar/mobile rendering decisions
Why:
- removes duplicated device-detection logic from `AppContent`
- makes device-state logic reusable and easier to maintain
- keeps PWA-specific behavior where it is actually used (`Sidebar`)
This commit is contained in:
48
src/App.jsx
48
src/App.jsx
@@ -32,6 +32,7 @@ import { TaskMasterProvider } from './contexts/TaskMasterContext';
|
||||
import { TasksSettingsProvider } from './contexts/TasksSettingsContext';
|
||||
import { WebSocketProvider, useWebSocket } from './contexts/WebSocketContext';
|
||||
import ProtectedRoute from './components/ProtectedRoute';
|
||||
import { useDeviceSettings } from './hooks/useDeviceSettings';
|
||||
import { api, authenticatedFetch } from './utils/api';
|
||||
import { I18nextProvider, useTranslation } from 'react-i18next';
|
||||
import i18n from './i18n/config.js';
|
||||
@@ -51,7 +52,7 @@ function AppContent() {
|
||||
const [selectedProject, setSelectedProject] = useState(null);
|
||||
const [selectedSession, setSelectedSession] = useState(null);
|
||||
const [activeTab, setActiveTab] = useState('chat'); // 'chat' or 'files'
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const { isMobile } = useDeviceSettings({ trackPWA: false });
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [isLoadingProjects, setIsLoadingProjects] = useState(true);
|
||||
const [loadingProgress, setLoadingProgress] = useState(null); // { phase, current, total, currentProject }
|
||||
@@ -77,49 +78,6 @@ function AppContent() {
|
||||
// Ref to track loading progress timeout for cleanup
|
||||
const loadingProgressTimeoutRef = useRef(null);
|
||||
|
||||
// Detect if running as PWA
|
||||
const [isPWA, setIsPWA] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if running in standalone mode (PWA)
|
||||
const checkPWA = () => {
|
||||
const isStandalone = window.matchMedia('(display-mode: standalone)').matches ||
|
||||
window.navigator.standalone ||
|
||||
document.referrer.includes('android-app://');
|
||||
setIsPWA(isStandalone);
|
||||
document.addEventListener('touchstart', {});
|
||||
|
||||
// Add class to html and body for CSS targeting
|
||||
if (isStandalone) {
|
||||
document.documentElement.classList.add('pwa-mode');
|
||||
document.body.classList.add('pwa-mode');
|
||||
} else {
|
||||
document.documentElement.classList.remove('pwa-mode');
|
||||
document.body.classList.remove('pwa-mode');
|
||||
}
|
||||
};
|
||||
|
||||
checkPWA();
|
||||
|
||||
// Listen for changes
|
||||
window.matchMedia('(display-mode: standalone)').addEventListener('change', checkPWA);
|
||||
|
||||
return () => {
|
||||
window.matchMedia('(display-mode: standalone)').removeEventListener('change', checkPWA);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth < 768);
|
||||
};
|
||||
|
||||
checkMobile();
|
||||
window.addEventListener('resize', checkMobile);
|
||||
|
||||
return () => window.removeEventListener('resize', checkMobile);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch projects on component mount
|
||||
fetchProjects();
|
||||
@@ -584,7 +542,6 @@ function AppContent() {
|
||||
loadingProgress,
|
||||
onRefresh: handleSidebarRefresh,
|
||||
onShowSettings: handleShowSettings,
|
||||
isPWA,
|
||||
isMobile
|
||||
}), [
|
||||
projects,
|
||||
@@ -599,7 +556,6 @@ function AppContent() {
|
||||
loadingProgress,
|
||||
handleSidebarRefresh,
|
||||
handleShowSettings,
|
||||
isPWA,
|
||||
isMobile
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user