mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
added web linking
This commit is contained in:
parent
215ea9ebe0
commit
ca3c790900
3 changed files with 145 additions and 1 deletions
26
App.tsx
26
App.tsx
|
|
@ -203,13 +203,37 @@ const ThemedApp = () => {
|
|||
const shouldShowApp = isAppReady && hasCompletedOnboarding !== null;
|
||||
const initialRouteName = hasCompletedOnboarding ? 'MainTabs' : 'Onboarding';
|
||||
|
||||
// Linking configuration for web browser history integration
|
||||
// Using 'enabled' with 'web' to enable basic web history navigation
|
||||
const linking = Platform.OS === 'web' ? {
|
||||
prefixes: [window?.location?.origin || '/'],
|
||||
config: {
|
||||
screens: {
|
||||
MainTabs: '',
|
||||
Onboarding: 'onboarding',
|
||||
Metadata: 'metadata',
|
||||
Streams: 'streams',
|
||||
PlayerAndroid: 'player',
|
||||
PlayerIOS: 'player',
|
||||
Catalog: 'catalog',
|
||||
Addons: 'addons',
|
||||
CatalogSettings: 'catalog-settings',
|
||||
TraktSettings: 'trakt-settings',
|
||||
PlayerSettings: 'player-settings',
|
||||
ThemeSettings: 'theme-settings',
|
||||
ScraperSettings: 'scraper-settings',
|
||||
AISettings: 'ai-settings',
|
||||
} as const,
|
||||
},
|
||||
} : undefined;
|
||||
|
||||
return (
|
||||
<AccountProvider>
|
||||
<PaperProvider theme={customDarkTheme}>
|
||||
<NavigationContainer
|
||||
ref={navigationRef}
|
||||
theme={customNavigationTheme}
|
||||
linking={undefined}
|
||||
linking={linking}
|
||||
>
|
||||
<DownloadsProvider>
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
|
|
|
|||
|
|
@ -359,6 +359,78 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
const firstFrameAtRef = useRef<number | null>(null);
|
||||
const controlsTimeout = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Web keyboard shortcuts
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== 'web') return;
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
// Prevent default for media keys
|
||||
if (['Space', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.code)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
switch (e.code) {
|
||||
case 'Space':
|
||||
// Toggle play/pause
|
||||
controlsHook.togglePlayback();
|
||||
playerState.setShowControls(true);
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
// Skip backward 10 seconds
|
||||
controlsHook.skip(-10);
|
||||
playerState.setShowControls(true);
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
// Skip forward 10 seconds
|
||||
controlsHook.skip(10);
|
||||
playerState.setShowControls(true);
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
// Increase volume
|
||||
setVolume(v => Math.min(1, v + 0.1));
|
||||
playerState.setShowControls(true);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
// Decrease volume
|
||||
setVolume(v => Math.max(0, v - 0.1));
|
||||
playerState.setShowControls(true);
|
||||
break;
|
||||
case 'KeyF':
|
||||
// Toggle fullscreen (handled by PlayerControls)
|
||||
break;
|
||||
case 'Escape':
|
||||
// Already handled by browser for fullscreen exit
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, [controlsHook, setVolume]);
|
||||
|
||||
// Auto-hide controls after 3 seconds
|
||||
useEffect(() => {
|
||||
if (playerState.showControls && !playerState.paused) {
|
||||
// Clear any existing timeout
|
||||
if (controlsTimeout.current) {
|
||||
clearTimeout(controlsTimeout.current);
|
||||
}
|
||||
|
||||
// Set new timeout to hide controls
|
||||
controlsTimeout.current = setTimeout(() => {
|
||||
if (!playerState.isDragging.current) {
|
||||
playerState.setShowControls(false);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (controlsTimeout.current) {
|
||||
clearTimeout(controlsTimeout.current);
|
||||
}
|
||||
};
|
||||
}, [playerState.showControls, playerState.paused]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (navigation.canGoBack()) navigation.goBack();
|
||||
else navigation.reset({ index: 0, routes: [{ name: 'Home' }] } as any);
|
||||
|
|
|
|||
|
|
@ -177,6 +177,40 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
}) => {
|
||||
const { currentTheme } = useTheme();
|
||||
|
||||
// Web fullscreen state
|
||||
const [isFullscreen, setIsFullscreen] = React.useState(false);
|
||||
|
||||
// Listen for fullscreen changes
|
||||
React.useEffect(() => {
|
||||
if (Platform.OS !== 'web') return;
|
||||
|
||||
const handleFullscreenChange = () => {
|
||||
setIsFullscreen(!!document.fullscreenElement);
|
||||
};
|
||||
|
||||
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
||||
return () => {
|
||||
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Toggle fullscreen function for web
|
||||
const toggleFullscreen = React.useCallback(() => {
|
||||
if (Platform.OS !== 'web') return;
|
||||
|
||||
if (!document.fullscreenElement) {
|
||||
// Enter fullscreen
|
||||
document.documentElement.requestFullscreen().catch(err => {
|
||||
console.log('[PlayerControls] Fullscreen request failed:', err);
|
||||
});
|
||||
} else {
|
||||
// Exit fullscreen
|
||||
document.exitFullscreen().catch(err => {
|
||||
console.log('[PlayerControls] Exit fullscreen failed:', err);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
/* Responsive Spacing */
|
||||
const screenWidth = Dimensions.get('window').width;
|
||||
|
|
@ -677,6 +711,20 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
<Ionicons name="list" size={24} color="white" />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
{/* Web Fullscreen Button */}
|
||||
{Platform.OS === 'web' && (
|
||||
<TouchableOpacity
|
||||
style={styles.iconButton}
|
||||
onPress={toggleFullscreen}
|
||||
>
|
||||
<Ionicons
|
||||
name={isFullscreen ? "contract-outline" : "scan-outline"}
|
||||
size={24}
|
||||
color="white"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
|
|
|
|||
Loading…
Reference in a new issue