@bit.rhplus/device
v0.0.13
Published
Modul pro detekci a přepínání mezi mobilní a desktop verzí aplikace s podporou pro iOS "Request Desktop Site".
Readme
Device Detection Module
Modul pro detekci a přepínání mezi mobilní a desktop verzí aplikace s podporou pro iOS "Request Desktop Site".
Problém, který řeší
iOS Safari/Chrome chování
Když uživatel na iOS použije "Request Desktop Site":
- ❌ Starý systém: User-Agent zůstává mobilní → zobrazuje se stále mobilní verze
- ✅ Nový systém: Kombinuje User-Agent + viewport šířku → zobrazí se desktop verze
Android Chrome chování
- ✅ User-Agent se mění při přepnutí na desktop verzi → funguje správně
Nová funkcionalita
1. Kombinovaná detekce
// Priorita detekce:
1. localStorage override (manuální volba uživatele)
2. Viewport šířka (>= 768px) + User-Agent
3. Standardní User-Agent detekce2. Dynamická reakce na změny
- Poslouchá
window.resizeudálosti - Automaticky přepne verzi při změně velikosti viewportu
- Řeší iOS "Request Desktop Site" změny
3. Manuální override
Uživatel si může sám vybrat, kterou verzi chce zobrazit:
- localStorage persistence (přetrvává po refreshi)
- Možnost vrátit se k automatické detekci
Použití
Basic - Detekce typu zařízení
import { useDeviceType } from '@bit.rhplus/device';
function MyComponent() {
const deviceType = useDeviceType(); // 'mobile' nebo 'desktop'
return (
<div>
Aktuální verze: {deviceType}
</div>
);
}Podmíněné zobrazení komponent
import { Desktop, Mobile } from '@bit.rhplus/device';
function MyPage() {
return (
<>
<Desktop>
<DesktopLayout />
</Desktop>
<Mobile>
<MobileLayout />
</Mobile>
</>
);
}Manuální přepínání verzí
import { useDeviceControl } from '@bit.rhplus/device';
function SettingsPage() {
const { deviceType, setDeviceOverride } = useDeviceControl();
return (
<div>
<p>Aktuální verze: {deviceType}</p>
<button onClick={() => setDeviceOverride('mobile')}>
Mobilní verze
</button>
<button onClick={() => setDeviceOverride('desktop')}>
Desktop verze
</button>
<button onClick={() => setDeviceOverride('auto')}>
Automatická detekce
</button>
</div>
);
}UI komponenty pro přepínání
Varianta 1: Select dropdown
import { DeviceToggle } from '@bit.rhplus/device';
function SettingsPage() {
return (
<div>
<h2>Nastavení zobrazení</h2>
<DeviceToggle variant="select" />
</div>
);
}Varianta 2: Toggle switch
import { DeviceToggle } from '@bit.rhplus/device';
function Header() {
return (
<div className="header">
<DeviceToggle variant="toggle" />
</div>
);
}Varianta 3: Button group
import { DeviceToggle } from '@bit.rhplus/device';
function SettingsPage() {
return (
<div>
<DeviceToggle variant="button" />
</div>
);
}Varianta 4: Plovoucí tlačítko (Development)
import { FloatingDeviceToggle } from '@bit.rhplus/device';
function PlatformApp() {
return (
<div>
{/* Vaše aplikace */}
{/* Plovoucí tlačítko v pravém dolním rohu */}
<FloatingDeviceToggle />
{/* Nebo zobrazit i v produkci */}
<FloatingDeviceToggle showInProduction={true} />
</div>
);
}Příklad integrace do PlatformApp.jsx
import { useDeviceType, FloatingDeviceToggle } from '@bit.rhplus/device';
const PlatformApp = (props) => {
const deviceType = useDeviceType();
return (
<StyleProvider hashPriority="high">
<App routes={routes}>
<div className="app-container">
{/* Sidebar pouze pro desktop */}
{deviceType === 'desktop' && (
<Sidebar
modules={safeModules}
// ... props
/>
)}
{/* Hlavní obsah */}
<div className={`app-content ${deviceType === 'mobile' ? 'app-content-full-width' : ''}`}>
<View
url="/"
main={true}
// ... props
>
<UpdateNotification />
</View>
</div>
</div>
{/* Development: Plovoucí tlačítko pro testování */}
{process.env.NODE_ENV === 'development' && (
<FloatingDeviceToggle />
)}
</App>
</StyleProvider>
);
};Testování na iOS
Před úpravou (problém):
- Otevři aplikaci na iOS Safari/Chrome
- Klikni na "AA" → "Request Desktop Site"
- ❌ Aplikace stále zobrazuje mobilní verzi
Po úpravě (řešení):
- Otevři aplikaci na iOS Safari/Chrome
- Klikni na "AA" → "Request Desktop Site"
- ✅ Aplikace automaticky přepne na desktop verzi (viewport >= 768px)
Manuální override (nová funkce):
- Otevři aplikaci na iOS
- Klikni na plovoucí tlačítko (development) nebo přejdi do nastavení
- Vyber "Desktop verze"
- ✅ Aplikace zobrazí desktop verzi bez ohledu na viewport
- Preference se uloží do localStorage (přetrvává po refreshi)
Technické detaily
DeviceProvider
<DeviceProvider deviceType="auto">
{/* Aplikace */}
</DeviceProvider>Props:
deviceType:'auto'|'mobile'|'desktop''auto'(default): Automatická detekce'mobile': Vždy mobilní verze'desktop': Vždy desktop verze
Context hodnota
{
deviceType: 'mobile' | 'desktop',
setDeviceOverride: (type: 'mobile' | 'desktop' | 'auto' | null) => void
}localStorage klíč
'rhplus_device_override'Hodnoty:
'mobile': Uživatel preferuje mobilní verzi'desktop': Uživatel preferuje desktop verzinullneboundefined: Automatická detekce
Viewport breakpoint
const VIEWPORT_BREAKPOINT = 768; // pxPokud window.innerWidth >= 768px a zařízení má mobilní User-Agent, preferuje se desktop verze (iOS use case).
API Reference
Hooks
useDeviceType()
Vrací aktuální typ zařízení.
const deviceType = useDeviceType(); // 'mobile' | 'desktop'useDeviceControl()
Vrací deviceType + funkci pro manuální override.
const { deviceType, setDeviceOverride } = useDeviceControl();
setDeviceOverride('desktop'); // Přepne na desktop
setDeviceOverride('mobile'); // Přepne na mobile
setDeviceOverride('auto'); // Automatická detekce
setDeviceOverride(null); // Automatická detekceKomponenty
<Desktop>{children}</Desktop>
Zobrazí obsah pouze na desktop verzi.
<Mobile>{children}</Mobile>
Zobrazí obsah pouze na mobilní verzi.
<ShowAt device="mobile|desktop">{children}</ShowAt>
Podmíněné zobrazení na základě typu zařízení.
<DeviceToggle variant="button|select|toggle" />
UI komponenta pro přepínání verzí.
Props:
variant:'button'|'select'|'toggle'className: CSS třída pro custom styling
<FloatingDeviceToggle showInProduction={false} />
Plovoucí tlačítko v pravém dolním rohu.
Props:
showInProduction:boolean- Zobrazit i v produkci (default:false)
Migrace z původního systému
Před (starý kód):
const deviceType = useDeviceType(); // Pouze User-Agent detekcePo (nový kód):
const deviceType = useDeviceType(); // User-Agent + viewport detekce✅ Žádná změna v kódu není nutná! API zůstává zpětně kompatibilní.
Nové funkce (volitelné):
// Manuální override
const { deviceType, setDeviceOverride } = useDeviceControl();
// UI komponenty pro přepínání
<DeviceToggle variant="select" />
<FloatingDeviceToggle />FAQ
Q: Proč iOS "Request Desktop Site" nefungoval?
A: iOS nemění User-Agent string při přepnutí na desktop režim. Nový systém kombinuje User-Agent s viewport šířkou.
Q: Jak změnit breakpoint pro desktop verzi?
A: Uprav konstantu VIEWPORT_BREAKPOINT v DeviceProvider.jsx (default: 768px).
Q: Jak přidat manuální přepínač do nastavení?
A: Použij <DeviceToggle variant="select" /> komponentu.
Q: Preference se neuloží po refreshi
A: Zkontroluj, že localStorage není blokován v prohlížeči.
Q: Chci zobrazit plovoucí tlačítko i v produkci
A: Použij <FloatingDeviceToggle showInProduction={true} />.
Optimalizace
- ✅ Memoizace context hodnoty (
useMemo) - ✅ Debounce resize eventů (inherent v React state updates)
- ✅ localStorage cache pro persistence
- ✅ Cleanup listeners při unmount
- ✅ Minimální re-rendery (pouze při změně deviceType)
Browser podpora
- ✅ iOS Safari 13+
- ✅ iOS Chrome 13+
- ✅ Android Chrome 80+
- ✅ Desktop Chrome/Firefox/Safari/Edge
- ✅ localStorage support required
