Skip to content

Commit

Permalink
Refactor layout resizing hack for Android native module
Browse files Browse the repository at this point in the history
  • Loading branch information
davidohayon669 committed Sep 3, 2019
1 parent 736fb09 commit c9a0c38
Showing 1 changed file with 39 additions and 19 deletions.
58 changes: 39 additions & 19 deletions YouTube.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,14 @@ export default class YouTube extends React.Component {
BackHandler.addEventListener('hardwareBackPress', this._backPress);

this.state = {
moduleMargin: StyleSheet.hairlineWidth * 2,
fullscreen: props.fullscreen,
resizingHackFlag: false,
};
}

// Periodically triggeting a forced unnoticable layout rendering until onReady to make sure the
// native loading progress is shown
this._interval = setInterval(() => {
this.setState({ moduleMargin: Math.random() / 2 });
}, 250);
componentDidMount() {
// Make sure the Loading indication is displayed so use this hack before the video loads
this._fireResizingHack();
}

componentDidUpdate(prevProps) {
Expand All @@ -76,34 +75,53 @@ export default class YouTube extends React.Component {

componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this._backPress);

clearInterval(this._timeout);
}

// The Android YouTube native module is pretty problematic when it comes to mounting correctly
// and rendering inside React-Native's views hierarchy. For now we must trigger some layout
// changes to force a real render on it so it will respotision it's controls after several
// specific events
_fireResizingHack() {
clearInterval(this._timeout);

let wait = 0.2;

const next = () => {
this.setState(state => ({ resizingHackFlag: !state.resizingHackFlag }));

wait = wait >= 1.5 ? 1.5 : wait * 1.4;
this._timeout = setTimeout(next, wait * 1000);
};

next();
}

_backPress = () => {
if (this.state.fullscreen) {
this.setState({ fullscreen: false });

return true;
}

return false;
};

_onLayout = () => {
// When the Native player changes it's layout, we should also force a resizing hack to make
// sure the controls are in their correct place
this._fireResizingHack();
};

_onError = event => {
if (this.props.onError) {
this.props.onError(event.nativeEvent);
}
};

_onReady = event => {
clearInterval(this._interval);

// The Android YouTube native module is pretty problematic when it comes to mounting correctly
// and rendering inside React-Native's views hierarchy. For now we must trigger some layout
// changes to force a real render on it so it will smoothly appear after ready and show
// controls. We also use the minimal margin to avoid `UNAUTHORIZED_OVERLAY` error from the
// native module that is very sensitive to being covered or even touching its containing view.
setTimeout(() => {
this.setState({ moduleMargin: StyleSheet.hairlineWidth });
}, 250);
this._fireResizingHack();

if (this.props.onReady) {
this.props.onReady(event.nativeEvent);
Expand Down Expand Up @@ -182,13 +200,15 @@ export default class YouTube extends React.Component {

render() {
return (
<View style={[styles.container, this.props.style]}>
<View onLayout={this._onLayout} style={[styles.container, this.props.style]}>
<RCTYouTube
ref={this._nativeComponentRef}
{...this.props}
fullscreen={this.state.fullscreen}
style={[styles.module, { margin: this.state.moduleMargin }]}
onYouTubeError={this._onError}
style={[
styles.module,
{ marginRight: this.state.resizingHackFlag ? StyleSheet.hairlineWidth : 0 },
]}
onYouTubeReady={this._onReady}
onYouTubeChangeState={this._onChangeState}
onYouTubeChangeQuality={this._onChangeQuality}
Expand Down

0 comments on commit c9a0c38

Please sign in to comment.