From 836285dbd565d8b543508e7196c077bc3cf6ce7f Mon Sep 17 00:00:00 2001 From: zimplexing Date: Fri, 15 Aug 2025 22:41:18 +0800 Subject: [PATCH] feat(player): enhance video playback with SSL error fallback and performance optimizations - Add comprehensive SSL certificate error detection and automatic source switching - Implement smart video source fallback strategy with failed source tracking - Enhance video component with optimized event handlers and useCallback patterns - Add explicit playAsync() call in onLoad to improve auto-play reliability - Integrate performance monitoring with detailed logging throughout playback chain - Optimize Video component props with useMemo and custom useVideoHandlers hook - Add source matching fixes for fallback scenarios in DetailStore - Enhance error handling with user-friendly messages and recovery strategies --- app/play.tsx | 170 ++++++++++++++--------- hooks/useVideoHandlers.ts | 131 ++++++++++++++++++ services/api.ts | 3 +- services/m3u8.ts | 22 ++- services/storage.ts | 37 ++++- stores/detailStore.ts | 284 +++++++++++++++++++++++++++++++++----- stores/playerStore.ts | 230 ++++++++++++++++++++++++++++-- 7 files changed, 761 insertions(+), 116 deletions(-) create mode 100644 hooks/useVideoHandlers.ts diff --git a/app/play.tsx b/app/play.tsx index e994a80..3e9a8f7 100644 --- a/app/play.tsx +++ b/app/play.tsx @@ -1,7 +1,7 @@ -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef, useCallback, memo, useMemo } from "react"; import { StyleSheet, TouchableOpacity, BackHandler, AppState, AppStateStatus, View } from "react-native"; import { useLocalSearchParams, useRouter } from "expo-router"; -import { Video, ResizeMode } from "expo-av"; +import { Video } from "expo-av"; import { useKeepAwake } from "expo-keep-awake"; import { ThemedView } from "@/components/ThemedView"; import { PlayerControls } from "@/components/PlayerControls"; @@ -16,6 +16,55 @@ import { useTVRemoteHandler } from "@/hooks/useTVRemoteHandler"; import Toast from "react-native-toast-message"; import usePlayerStore, { selectCurrentEpisode } from "@/stores/playerStore"; import { useResponsiveLayout } from "@/hooks/useResponsiveLayout"; +import { useVideoHandlers } from "@/hooks/useVideoHandlers"; + +// 优化的加载动画组件 +const LoadingContainer = memo( + ({ style, currentEpisode }: { style: any; currentEpisode: { url: string; title: string } | undefined }) => { + console.info( + `[PERF] Video component NOT rendered - waiting for valid URL. currentEpisode: ${!!currentEpisode}, url: ${ + currentEpisode?.url ? "exists" : "missing" + }` + ); + return ( + + + + ); + } +); + +LoadingContainer.displayName = "LoadingContainer"; + +// 移到组件外部避免重复创建 +const createResponsiveStyles = (deviceType: string) => { + const isMobile = deviceType === "mobile"; + const isTablet = deviceType === "tablet"; + + return StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "black", + // 移动端和平板端可能需要状态栏处理 + ...(isMobile || isTablet ? { paddingTop: 0 } : {}), + }, + videoContainer: { + ...StyleSheet.absoluteFillObject, + // 为触摸设备添加更多的交互区域 + ...(isMobile || isTablet ? { zIndex: 1 } : {}), + }, + videoPlayer: { + ...StyleSheet.absoluteFillObject, + }, + loadingContainer: { + ...StyleSheet.absoluteFillObject, + backgroundColor: "rgba(0, 0, 0, 0.8)", + justifyContent: "center", + alignItems: "center", + zIndex: 10, + }, + }); +}; export default function PlayScreen() { const videoRef = useRef