Skip to content

Commit ddf3dab

Browse files
committed
feat: Implemented progress tracking for in app player
1 parent 97e6f14 commit ddf3dab

File tree

21 files changed

+273
-78
lines changed

21 files changed

+273
-78
lines changed

android/app/src/main/java/com/popcorn/VlcPlayer/VlcPlayerView.java

-3
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,6 @@ public void seek(long pos) {
258258
mMediaPlayer.pause();
259259

260260
} else {
261-
Log.d("TYCHO", "go to " + pos);
262-
Log.d("TYCHO", "length is " + mMediaPlayer.getLength());
263-
Log.d("TYCHO", "check " + mMediaPlayer.isSeekable());
264261
mMediaPlayer.setTime((long) pos);
265262
}
266263
}

app/components/Card/Card.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export const Card = ({
4949
forceOverlay,
5050
overlayVariant,
5151
overlayWithAnimation,
52+
overlayAllowed,
5253
children,
5354
...rest
5455
}) => (
@@ -71,7 +72,7 @@ export const Card = ({
7172
: item.images
7273
} />
7374

74-
{(item?.watched?.complete || forceOverlay) && (
75+
{(item?.watched?.complete || forceOverlay) && overlayAllowed && (
7576
<Overlay
7677
withAnimation={overlayWithAnimation}
7778
variant={overlayVariant} />
@@ -102,6 +103,7 @@ Card.defaultProps = {
102103
elevation: 1,
103104
variant: 'default',
104105
forceOverlay: false,
106+
overlayAllowed: true,
105107
overlayVariant: 'dark',
106108
overlayWithAnimation: false,
107109
hide: false,

app/mobile/components/ItemInfo/ItemInfo.js

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const ItemInfo = ({ item, quality, status, variant, style, truncateSynops
4545
<View style={[styles.root, style]}>
4646
{variant === 'default' && (
4747
<Card
48+
overlayAllowed={false}
4849
elevation={0}
4950
empty={empty}
5051
item={

app/mobile/components/MainCover/MainCover.js

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ export const MainCover = ({ empty, item, handleItemOpen }) => {
141141
style={styles.poster}
142142
empty={empty}
143143
item={item}
144+
overlayAllowed={false}
144145
onPress={() => {
145146
if (!empty && handleItemOpen) {
146147
handleItemOpen(item)

app/mobile/screens/Home/HomeScreen.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ export const Home = ({ navigation }) => {
6767
// Filter out bookmarks, when adding then this data is updated
6868
const movies = noMoviesYet
6969
? null
70-
: moviesData.movies.filter(movie => !movie.bookmarked)
70+
: moviesData.movies
71+
.filter(movie => !movie.bookmarked)
72+
.filter(movie => !movie.watched.complete)
7173

7274
return (
7375
<ScrollViewWithStatusBar>

app/mobile/screens/Item/ItemScreen.js

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
import Typography from 'components/Typography'
21
import React, { useEffect } from 'react'
32
import { StyleSheet, View, InteractionManager, Linking } from 'react-native'
43
import { useLazyQuery } from '@apollo/react-hooks'
54
import Orientation from 'react-native-orientation'
65

7-
import colors from 'modules/colors'
86
import dimensions from 'modules/dimensions'
97
import constants from 'modules/constants'
108

119
import Container from 'components/Container'
1210
import ScrollViewWithStatusBar from 'components/ScrollViewWithStatusBar'
1311
import IconButton from 'components/IconButton'
12+
import Typography from 'components/Typography'
1413
import QualitySelector from 'mobile/components/QualitySelector'
1514
import MainCover from 'mobile/components/MainCover'
1615

1716
import { MovieQuery, ShowQuery } from './ItemGraphQL'
1817

1918
import Bookmarked from './Bookmarked'
2019
import SeasonsAndEpisodes from './SeasonsAndEpisodes'
20+
import WatchedBar from './WatchedBar'
2121

2222
const styles = StyleSheet.create({
2323

@@ -50,6 +50,7 @@ const styles = StyleSheet.create({
5050
marginLeft: dimensions.UNIT * 2,
5151
marginRight: dimensions.UNIT * 2,
5252
},
53+
5354
})
5455

5556
export const Item = ({ route: { params } }) => {
@@ -133,6 +134,8 @@ export const Item = ({ route: { params } }) => {
133134
)}
134135
</View>
135136

137+
<WatchedBar item={item} />
138+
136139
{/* /!*{!loading && item.type === constants.TYPE_MOVIE && (*!/*/}
137140
{/* /!* <IconButton*!/*/}
138141
{/* /!* animatable={{*!/*/}
@@ -151,13 +154,11 @@ export const Item = ({ route: { params } }) => {
151154
{/* /!* </IconButton>*!/*/}
152155
{/* /!*)}*!/*/}
153156

154-
{item && (
155-
<View style={styles.synopsis}>
156-
<Typography variant={'body2'}>
157-
{item.synopsis}
158-
</Typography>
159-
</View>
160-
)}
157+
<View style={styles.synopsis}>
158+
<Typography variant={'body2'}>
159+
{item?.synopsis}
160+
</Typography>
161+
</View>
161162

162163
{item && item.type === constants.TYPE_SHOW && item.seasons.length > 0 && (
163164
<SeasonsAndEpisodes

app/mobile/screens/Item/SeasonsAndEpisodes/Episode/Episode.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { StyleSheet, View } from 'react-native'
44

55
import dimensions from 'modules/dimensions'
66
import constants from 'modules/constants'
7+
import colors from 'modules/colors'
78

89
import Typography from 'components/Typography'
910
import Overlay from 'components/Overlay'
@@ -63,11 +64,19 @@ export const styles = StyleSheet.create({
6364
textAlign: 'center',
6465
},
6566

67+
progress: {
68+
position: 'absolute',
69+
bottom: 0,
70+
left: 0,
71+
backgroundColor: colors.PRIMARY_COLOR_200,
72+
width: 0,
73+
height: 2,
74+
},
6675
})
6776

6877
export const Episode = (props) => {
6978
const [showQualitySelector, toggleSelecting] = useState(false)
70-
const { title, synopsis, number, hasAired, images, firstAired } = props
79+
const { title, synopsis, number, hasAired, images, firstAired, watched } = props
7180

7281
const getAirsDate = () => {
7382
const airs = new Date()
@@ -105,6 +114,13 @@ export const Episode = (props) => {
105114
{getAirsDate()}
106115
</Typography>
107116
)}
117+
118+
{watched.progress > 0 && (
119+
<View style={{
120+
...styles.progress,
121+
width: `${watched.progress || 0}%`,
122+
}} />
123+
)}
108124
</View>
109125
</View>
110126
</BaseButton>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import React from 'react'
2+
import PropTypes from 'prop-types'
3+
import { View } from 'react-native'
4+
5+
import dimensions from 'modules/dimensions'
6+
import colors from 'modules/colors'
7+
import i18n from 'modules/i18n'
8+
9+
import Typography from 'components/Typography'
10+
11+
const styles = {
12+
13+
root: {
14+
marginBottom: dimensions.UNIT * 4,
15+
height: 2,
16+
},
17+
18+
progressBar: {
19+
backgroundColor: colors.PRIMARY_COLOR_200,
20+
width: 0,
21+
height: 2,
22+
},
23+
24+
container: {
25+
flex: 1,
26+
alignItems: 'center',
27+
},
28+
29+
}
30+
31+
export const WatchedBar = ({ item }) => {
32+
const watchedPercentage = item?.watched?.progress ?? 0
33+
34+
if (watchedPercentage === 0) {
35+
return null
36+
}
37+
38+
return (
39+
<View style={styles.root}>
40+
<View style={{
41+
...styles.progressBar,
42+
width: `${watchedPercentage}%`,
43+
}} />
44+
45+
{(watchedPercentage < 100) && (
46+
<View style={{
47+
...styles.container,
48+
width: `${watchedPercentage}%`,
49+
}}>
50+
<Typography variant={'captionSmall'}>
51+
{i18n.t('Watched: {{percentage}}%', { percentage: watchedPercentage })}
52+
</Typography>
53+
</View>
54+
)}
55+
</View>
56+
)
57+
}
58+
59+
WatchedBar.propTypes = {}
60+
61+
WatchedBar.defaultProps = {}
62+
63+
export default WatchedBar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './WatchedBar'

app/mobile/screens/Player/Player.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export const Player = ({ route: { params: { item, playQuality } } }) => {
122122
isBuffering={isBuffering}
123123
style={styles.root}>
124124

125-
{({ casting, renderCastButton, mediaUrl, setProgress }) => (
125+
{({ casting, renderCastButton, mediaUrl, setProgress, startPosition }) => (
126126
<React.Fragment>
127127
{(isBuffering || casting) && (
128128
<View style={[styles.fullScreen, styles.bufferingContainer]}>
@@ -188,6 +188,7 @@ export const Player = ({ route: { params: { item, playQuality } } }) => {
188188
<VideoAndControls
189189
item={item}
190190
url={mediaUrl}
191+
startPosition={startPosition}
191192
setProgress={setProgress}
192193
playOtherEpisode={playItem}>
193194

@@ -202,8 +203,8 @@ export const Player = ({ route: { params: { item, playQuality } } }) => {
202203
/>
203204

204205
{renderCastButton({
205-
right: dimensions.UNIT * 12,
206-
bottom: dimensions.UNIT * 2,
206+
right: dimensions.UNIT * 10,
207+
bottom: dimensions.UNIT * 2.4,
207208
})}
208209

209210
</VideoAndControls>

app/mobile/screens/Player/PlayerManager/PlayerManager.js

+40-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { StyleSheet, View } from 'react-native'
44
import GoogleCast, { CastButton } from 'react-native-google-cast'
55
import Orientation from 'react-native-orientation'
66

7+
import withApollo from 'modules/GraphQL/withApollo'
8+
import { progrssMutation } from 'modules/GraphQL/ProgressGraphQL'
79
import withIpFinder from 'modules/IpFinder/withIpFinder'
810
import dimensions from 'modules/dimensions'
911
import colors from 'modules/colors'
@@ -26,6 +28,7 @@ const styles = StyleSheet.create({
2628
})
2729

2830
@withIpFinder
31+
@withApollo
2932
export default class PlayerManager extends React.Component {
3033

3134
constructor(props) {
@@ -37,6 +40,7 @@ export default class PlayerManager extends React.Component {
3740
mediaUrl: `http://${ipFinder.host}/watch/${item._id}`,
3841
progress: 0,
3942
casting: false,
43+
lastProgressSend: 0,
4044
}
4145
}
4246

@@ -137,12 +141,42 @@ export default class PlayerManager extends React.Component {
137141
}
138142

139143
handleSetProgress = ({ currentTime, duration, progress }) => {
144+
const { lastProgressSend } = this.state
145+
146+
let newLastProgressSend = lastProgressSend
147+
148+
// We don't want to spam the graph api
149+
if ((lastProgressSend + 0.001) < progress) {
150+
const progressToSend = parseFloat(`${progress * 100}`).toFixed(2)
151+
152+
newLastProgressSend = progress
153+
154+
// After 95 we don't update anymore
155+
if (progressToSend > 95) {
156+
newLastProgressSend = 100
157+
}
158+
159+
this.doProgressUpdateMutation(progressToSend)
160+
}
161+
140162
this.setState({
141163
currentTime,
142164
duration,
143165
progress,
144-
}, () => {
145-
// console.log('progress',progress)
166+
lastProgressSend: newLastProgressSend,
167+
})
168+
}
169+
170+
doProgressUpdateMutation = async(progress) => {
171+
const { apollo, item } = this.props
172+
173+
await apollo.mutate({
174+
variables: {
175+
_id: item._id,
176+
type: item.type,
177+
progress: parseFloat(progress),
178+
},
179+
mutation: progrssMutation,
146180
})
147181
}
148182

@@ -157,7 +191,7 @@ export default class PlayerManager extends React.Component {
157191
}
158192

159193
render() {
160-
const { style, children } = this.props
194+
const { style, children, item } = this.props
161195
const { casting, mediaUrl } = this.state
162196

163197
return (
@@ -166,6 +200,9 @@ export default class PlayerManager extends React.Component {
166200
{children({
167201
casting,
168202
mediaUrl,
203+
startPosition: item.watched.progress === 100
204+
? 0
205+
: item.watched.progress,
169206
renderCastButton: this.renderCastButton,
170207
setProgress: this.handleSetProgress,
171208
})}

app/mobile/screens/Player/VideoAndControls/ResizeMode/ResizeMode.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const ResizeMode = ({ activeMode, changeResizeMode, toggleControls }) =>
4040
}}
4141
name={'cellphone-screenshot'}
4242
color={'primary'}
43-
size={dimensions.ICON_SIZE_DEFAULT}>
43+
size={dimensions.ICON_SIZE_MEDIUM}>
4444
{activeMode}
4545
</IconButton>
4646

app/mobile/screens/Player/VideoAndControls/SeekBar/SeekBar.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const styles = {
1818
},
1919

2020
slider: {
21-
width: dimensions.SCREEN_HEIGHT - dimensions.UNIT * 14,
21+
width: dimensions.SCREEN_HEIGHT - dimensions.UNIT * 20,
2222
},
2323

2424
track: {

0 commit comments

Comments
 (0)