Skip to content

Commit 42d9580

Browse files
authored
Merge pull request #8 from sheeshcake/chore/code-cleanup
chore: code cleanup on details screen
2 parents b9e9b8b + 9887382 commit 42d9580

File tree

12 files changed

+590
-1124
lines changed

12 files changed

+590
-1124
lines changed
80.3 MB
Binary file not shown.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Flickv4",
3-
"version": "1.2.0",
3+
"version": "1.2.1",
44
"private": true,
55
"scripts": {
66
"clean:android": "cd android && ./gradlew clean",

src/components/MediaPlayer/SubtitleOverlay.tsx

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,25 @@ interface SubtitleOverlayProps {
1212
subtitleContent: string | null;
1313
currentTime: number;
1414
isVideoFullscreen: boolean;
15-
delay?: number; // Delay in seconds (positive = subtitles later, negative = subtitles earlier)
16-
style?: SubtitleStyle; // Custom subtitle style from settings
15+
delay?: number;
16+
style?: SubtitleStyle;
1717
}
1818

1919
const parseSRT = (srtContent: string): SubtitleCue[] => {
2020
const cues: SubtitleCue[] = [];
2121

22-
// Split by double newline to get subtitle blocks
2322
const blocks = srtContent.trim().split(/\r?\n\r?\n/);
2423

2524
for (const block of blocks) {
2625
const lines = block.trim().split(/\r?\n/);
2726
if (lines.length < 3) continue;
2827

29-
// Find the timestamp line (contains -->)
3028
const timestampIndex = lines.findIndex(line => line.includes('-->'));
3129
if (timestampIndex === -1) continue;
3230

3331
const timestampLine = lines[timestampIndex];
3432
const textLines = lines.slice(timestampIndex + 1);
3533

36-
// Parse SRT timestamps: 00:00:01,000 --> 00:00:03,500
3734
const match = timestampLine.match(/(\d{2}):(\d{2}):(\d{2}),(\d{3})\s*-->\s*(\d{2}):(\d{2}):(\d{2}),(\d{3})/);
3835
if (!match) continue;
3936

@@ -47,10 +44,9 @@ const parseSRT = (srtContent: string): SubtitleCue[] => {
4744
const start = startHours * 3600 + startMinutes * 60 + startSeconds;
4845
const end = endHours * 3600 + endMinutes * 60 + endSeconds;
4946

50-
// Clean text (remove tags and extra whitespace)
5147
const text = textLines
5248
.join('\n')
53-
.replace(/<[^>]*>/g, '') // Remove HTML tags
49+
.replace(/<[^>]*>/g, '')
5450
.trim();
5551

5652
if (text) {
@@ -71,7 +67,6 @@ export const SubtitleOverlay: React.FC<SubtitleOverlayProps> = ({
7167
const [cues, setCues] = useState<SubtitleCue[]>([]);
7268
const [currentCue, setCurrentCue] = useState<string | null>(null);
7369

74-
// Compute font size based on style setting and fullscreen mode
7570
const computedFontSize = useMemo(() => {
7671
const baseSizes = {
7772
small: isVideoFullscreen ? 14 : 10,
@@ -82,7 +77,6 @@ export const SubtitleOverlay: React.FC<SubtitleOverlayProps> = ({
8277
return baseSizes[style.fontSize] || baseSizes.medium;
8378
}, [style.fontSize, isVideoFullscreen]);
8479

85-
// Compute background color with opacity
8680
const computedBackgroundColor = useMemo(() => {
8781
if (style.backgroundOpacity === 0) return 'transparent';
8882
const hex = style.backgroundColor.replace('#', '');
@@ -92,16 +86,13 @@ export const SubtitleOverlay: React.FC<SubtitleOverlayProps> = ({
9286
return `rgba(${r}, ${g}, ${b}, ${style.backgroundOpacity})`;
9387
}, [style.backgroundColor, style.backgroundOpacity]);
9488

95-
// Dynamic container style based on position
9689
const containerStyle: ViewStyle = useMemo(() => ({
9790
position: 'absolute',
9891
alignItems: 'center',
9992
paddingHorizontal: 20,
100-
// backgroundColor: 'red', // For debugging
10193
...(style.position === 'top' ? { top: 50 } : { bottom: isVideoFullscreen ? -70 : 20 }),
10294
}), [style.position, isVideoFullscreen]);
10395

104-
// Dynamic text style
10596
const textStyle: TextStyle = useMemo(() => ({
10697
color: style.fontColor,
10798
textAlign: 'center',
@@ -112,7 +103,6 @@ export const SubtitleOverlay: React.FC<SubtitleOverlayProps> = ({
112103
textShadowRadius: style.textShadow ? 2 : 0,
113104
}), [style.fontColor, style.fontWeight, style.textShadow, computedFontSize]);
114105

115-
// Dynamic text container style
116106
const textContainerStyle: ViewStyle = useMemo(() => ({
117107
backgroundColor: computedBackgroundColor,
118108
paddingVertical: 8,
@@ -126,9 +116,7 @@ export const SubtitleOverlay: React.FC<SubtitleOverlayProps> = ({
126116
try {
127117
const parsedCues = parseSRT(subtitleContent);
128118
setCues(parsedCues);
129-
console.log('[SubtitleOverlay] Parsed SRT cues:', parsedCues.length);
130-
} catch (error) {
131-
console.error('[SubtitleOverlay] Failed to parse SRT:', error);
119+
} catch {
132120
}
133121
} else {
134122
setCues([]);
@@ -142,8 +130,6 @@ export const SubtitleOverlay: React.FC<SubtitleOverlayProps> = ({
142130
return;
143131
}
144132

145-
// Apply delay: positive delay means subtitles appear later (subtract from currentTime)
146-
// negative delay means subtitles appear earlier (add to currentTime)
147133
const adjustedTime = currentTime - delay + 0.5;
148134
const activeCue = cues.find(
149135
cue => adjustedTime >= cue.start && adjustedTime <= cue.end

src/components/MediaPlayer/controls/Controls.tsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,6 @@ import type { ControlsProps, VideoStatus } from './types';
2424
const loadingMessagesModule = require('../../../constants/loadingmessage.js');
2525
const loadingMessages: string[] = loadingMessagesModule?.default ?? [];
2626

27-
/**
28-
* Optimized Controls Component
29-
* Features:
30-
* - Better memoization to prevent unnecessary re-renders
31-
* - Improved auto-hide logic with proper cleanup
32-
* - Cleaner state management
33-
*/
3427
const ControlsComponent: React.FC<ControlsProps> = ({
3528
hide,
3629
title,
@@ -64,19 +57,16 @@ const ControlsComponent: React.FC<ControlsProps> = ({
6457

6558
const messageTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
6659

67-
// Update time label when not seeking
6860
useEffect(() => {
6961
if (!isSeeking) {
7062
setTimeLabel(formatTime(currentPosition));
7163
}
7264
}, [currentPosition, isSeeking]);
7365

74-
// Update status
7566
useEffect(() => {
7667
setStatus(videoStatus as VideoStatus);
7768
}, [videoStatus]);
7869

79-
// Loading message rotation
8070
useEffect(() => {
8171
if (videoStatus === 'loading' && loadingMessages.length > 0) {
8272
if (messageTimeoutRef.current) {
@@ -96,37 +86,30 @@ const ControlsComponent: React.FC<ControlsProps> = ({
9686
}
9787
}, [videoStatus]);
9888

99-
// Handle seeking state changes
10089
const handleSeekingStateChange = useCallback((isCurrentlySeeking: boolean) => {
10190
setIsSeeking(isCurrentlySeeking);
10291
onSeekingStateChange?.(isCurrentlySeeking);
10392
}, [onSeekingStateChange]);
10493

105-
// Auto-hide is now handled by the useControlsVisibility hook in MediaPlayer
106-
// This component no longer manages its own auto-hide timer
107-
108-
// Time preview handler for progress bar
10994
const handleTimePreview = useCallback((newTime: number) => {
11095
setTimeLabel(formatTime(newTime));
11196
}, []);
11297

113-
// Seek with offset
11498
const handleSeekOffset = useCallback((seconds: number) => {
11599
const newTime = Math.max(0, Math.min(currentPosition + seconds, duration));
116100
onSeek(newTime);
117101
}, [currentPosition, duration, onSeek]);
118102

119-
// Back button handler
120103
const handleBackPress = useCallback(() => {
121-
Orientation.lockToPortrait();
122104
if (fullscreen) {
123105
onFullscreen();
124106
} else {
107+
Orientation.lockToPortrait();
108+
setTimeout(() => Orientation.unlockAllOrientations(), 300);
125109
navigation.goBack();
126110
}
127111
}, [fullscreen, navigation, onFullscreen]);
128112

129-
// Play/Pause toggle
130113
const handlePlayPause = useCallback(() => {
131114
if (playing) {
132115
onPause();
@@ -135,13 +118,11 @@ const ControlsComponent: React.FC<ControlsProps> = ({
135118
}
136119
}, [onPause, onPlay, playing]);
137120

138-
// Memoize container dimensions
139121
const containerDimensions = useMemo(() => ({
140122
width: fullscreen ? sizes.height : sizes.width,
141123
height: fullscreen ? sizes.width : sizes.height * 0.3,
142124
}), [fullscreen]);
143125

144-
// Memoize controls visibility
145126
const isControlsHidden = useMemo(() => hide && !isSeeking, [hide, isSeeking]);
146127

147128
return (

src/components/MediaPlayer/controls/ProgressBar.tsx

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@ import { ProgressBarProps } from './types';
55

66
const clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(value, max));
77

8-
/**
9-
* Optimized ProgressBar Component
10-
* Features:
11-
* - Better performance with refs to avoid unnecessary renders
12-
* - Smoother dragging with optimized pan responder
13-
* - Accurate progress tracking
14-
*/
158
const ProgressBarComponent: React.FC<ProgressBarProps> = ({
169
currentPosition,
1710
duration,
@@ -27,27 +20,23 @@ const ProgressBarComponent: React.FC<ProgressBarProps> = ({
2720
const dragPercentageRef = useRef(0);
2821
const trackRef = useRef<View>(null);
2922

30-
// Calculate progress percentage
3123
const progressPercentage = useMemo(() => {
3224
if (!duration || duration === 0) return 0;
3325
return clamp(currentPosition / duration, 0, 1);
3426
}, [currentPosition, duration]);
3527

36-
// Calculate buffered percentage
3728
const bufferedPercentage = useMemo(() => {
3829
if (!duration || duration === 0) return 0;
3930
return clamp(bufferedPosition / duration, 0, 1);
4031
}, [bufferedPosition, duration]);
4132

42-
// Sync drag percentage with actual progress when not dragging
4333
useEffect(() => {
4434
if (!isDragging) {
4535
dragPercentageRef.current = progressPercentage;
4636
setDragPercentage(progressPercentage);
4737
}
4838
}, [isDragging, progressPercentage]);
4939

50-
// Update position from touch location
5140
const updateFromLocation = useCallback((pageX: number) => {
5241
if (!trackWidth || !duration || !trackRef.current) return;
5342

@@ -65,15 +54,13 @@ const ProgressBarComponent: React.FC<ProgressBarProps> = ({
6554
});
6655
}, [duration, onTimePreview, trackWidth]);
6756

68-
// Commit seek when drag ends
6957
const commitSeek = useCallback(() => {
7058
if (!duration) return;
7159

7260
const newTime = dragPercentageRef.current * duration;
7361
onSeek(newTime);
7462
}, [duration, onSeek]);
7563

76-
// Pan responder for touch handling
7764
const panResponder = useMemo(() => PanResponder.create({
7865
onStartShouldSetPanResponder: () => true,
7966
onMoveShouldSetPanResponder: () => true,
@@ -97,15 +84,12 @@ const ProgressBarComponent: React.FC<ProgressBarProps> = ({
9784
},
9885
}), [commitSeek, onSeekingStateChange, updateFromLocation]);
9986

100-
// Track width measurement
10187
const handleLayout = useCallback((event: LayoutChangeEvent) => {
10288
setTrackWidth(event.nativeEvent.layout.width);
10389
}, []);
10490

105-
// Display percentage (use drag when dragging, otherwise use actual progress)
10691
const displayPercentage = isDragging ? dragPercentage : progressPercentage;
10792

108-
// Memoized styles for performance
10993
const bufferedStyle = useMemo(() => ({
11094
width: bufferedPercentage * trackWidth,
11195
}), [bufferedPercentage, trackWidth]);

src/components/MediaPlayer/hooks/useControlsVisibility.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { useCallback, useEffect, useRef, useState } from 'react';
22

3-
const AUTO_HIDE_DELAY = 3000; // 3 seconds
3+
const AUTO_HIDE_DELAY = 3000;
44

5-
/**
6-
* Custom hook for managing controls visibility with auto-hide
7-
*/
85
export const useControlsVisibility = (isPlaying: boolean, isSeeking?: boolean) => {
96
const [controlsVisible, setControlsVisible] = useState(true);
107
const hideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

src/components/MediaPlayer/hooks/useFullscreen.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,18 @@
11
import { useCallback, useEffect, useState } from 'react';
22
import Orientation from 'react-native-orientation-locker';
3-
import { StatusBar } from 'react-native';
3+
import { StatusBar, InteractionManager } from 'react-native';
44

5-
/**
6-
* Custom hook for managing fullscreen mode
7-
* @param onFullscreenChange - Callback when fullscreen state changes
8-
* @param initialFullscreen - Initial fullscreen state (default: false)
9-
*/
105
export const useFullscreen = (
116
onFullscreenChange?: (isFullscreen: boolean) => void,
127
initialFullscreen: boolean = false
138
) => {
149
const [isFullscreen, setIsFullscreen] = useState(initialFullscreen);
1510

16-
// Apply initial fullscreen state on mount
1711
useEffect(() => {
1812
if (initialFullscreen) {
1913
Orientation.lockToLandscape();
2014
StatusBar.setHidden(true, 'fade');
21-
console.log('[useFullscreen] Initial fullscreen enabled');
2215
}
23-
// Only run on mount
2416
// eslint-disable-next-line react-hooks/exhaustive-deps
2517
}, []);
2618

@@ -31,22 +23,27 @@ export const useFullscreen = (
3123
Orientation.lockToLandscape();
3224
StatusBar.setHidden(true, 'fade');
3325
} else {
34-
Orientation.lockToPortrait();
3526
StatusBar.setHidden(false, 'fade');
27+
InteractionManager.runAfterInteractions(() => {
28+
Orientation.lockToPortrait();
29+
setTimeout(() => {
30+
Orientation.unlockAllOrientations();
31+
}, 300);
32+
});
3633
}
3734

3835
setIsFullscreen(newState);
3936
onFullscreenChange?.(newState);
40-
41-
console.log('[useFullscreen] Fullscreen:', newState);
4237
}, [isFullscreen, onFullscreenChange]);
4338

44-
// Cleanup on unmount
4539
useEffect(() => {
4640
return () => {
4741
if (isFullscreen) {
48-
Orientation.lockToPortrait();
4942
StatusBar.setHidden(false, 'fade');
43+
Orientation.lockToPortrait();
44+
setTimeout(() => {
45+
Orientation.unlockAllOrientations();
46+
}, 300);
5047
}
5148
};
5249
}, [isFullscreen]);

0 commit comments

Comments
 (0)