GLCanvas.js 3.7 KB
Newer Older
1
import invariant from "invariant";
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
2
import React, {Component} from "react";
3
  import {requireNativeComponent, findNodeHandle} from "react-native";
4 5
import defer from "promise-defer";
import captureFrame from "./GLCanvas.captureFrame";
6

7 8 9
const serializeOption = config =>
config.format + ":" + config.type + ":" + config.quality;

10 11 12 13 14
const GLCanvasNative = requireNativeComponent("GLCanvas", GLCanvas, {
  nativeOnly: {
    onGLChange: true,
    onGLProgress: true,
    onGLCaptureFrame: true
15
  }
16 17 18
});

class GLCanvas extends Component {
19

20 21 22 23
  viewConfig = {
    uiViewClassName: "GLCanvas"
  };

24 25 26 27 28 29 30 31 32 33
  componentWillMount () {
    this._pendingCaptureFrame = {};
  }

  componentWillUnmount () {
    Object.keys(this._pendingCaptureFrame).forEach(key =>
      this._pendingCaptureFrame[key].reject(new Error("GLCanvas is unmounting")));
    this._pendingCaptureFrame = null;
  }

34 35 36 37 38
  setNativeProps (props) {
    this.refs.native.setNativeProps(props);
  }

  _addPendingCaptureFrame (config) {
39 40
    const key = serializeOption(config);
    return this._pendingCaptureFrame[key] || (
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
41
      (captureFrame(findNodeHandle(this.refs.native), config),
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
      this._pendingCaptureFrame[key] = defer())
    );
  }

  captureFrame (configArg) {
    let config;
    if (configArg) {
      invariant(typeof configArg==="object", "captureFrame takes an object option in parameter");
      let nb = 0;
      if ("format" in configArg) {
        invariant(
          typeof configArg.format === "string",
          "captureFrame({format}): format must be a string (e.g: 'base64'), Got: '%s'",
          configArg.format);
        if (configArg.format === "file") invariant(
          typeof configArg.filePath === "string" && configArg.filePath,
          "captureFrame({filePath}): filePath must be defined when using 'file' format and be an non-empty string, Got: '%s'",
          configArg.filePath);
        nb ++;
      }
      if ("type" in configArg) {
        invariant(
          typeof configArg.type === "string",
          "captureFrame({type}): type must be a string (e.g: 'png', 'jpg'), Got: '%s'",
          configArg.type);
        nb ++;
      }
      if ("quality" in configArg) {
        invariant(
          typeof configArg.quality === "number" &&
          configArg.quality >= 0 &&
          configArg.quality <= 1,
          "captureFrame({quality}): quality must be a number between 0 and 1, Got: '%s'",
          configArg.quality);
        nb ++;
      }
      if ("filePath" in configArg) {
        nb ++;
      }
      const keys = Object.keys(configArg);
      invariant(keys.length === nb, "captureFrame(config): config must be an object with {format, type, quality, filePath}, found some invalid keys in '%s'", keys);
      config = configArg;
84
    }
85
    return this._addPendingCaptureFrame({
86 87 88 89 90 91
      format: "base64",
      type: "png",
      quality: 1,
      filePath: "",
      ...config
    }).promise;
92
  }
93 94 95 96 97 98 99 100 101 102 103

  onGLCaptureFrame = ({ nativeEvent: { error, result, config } }) => {
    const key = serializeOption(config);
    invariant(key in this._pendingCaptureFrame, "capture '%s' is not scheduled in this._pendingCaptureFrame", key);
    if (error) {
      this._pendingCaptureFrame[key].reject(error);
    }
    else {
      this._pendingCaptureFrame[key].resolve(result);
    }
    delete this._pendingCaptureFrame[key];
104
  };
105

106
  render () {
107
    const {
108
      width, height,
109 110
      onLoad, onProgress, eventsThrough,
      ...restProps } = this.props;
111

112 113 114
    return <GLCanvasNative
      ref="native"
      {...restProps}
115
      style={{ width, height }}
116 117 118 119
      onGLLoad={onLoad ? onLoad : null}
      onGLProgress={onProgress ? onProgress : null}
      onGLCaptureFrame={this.onGLCaptureFrame}
      pointerEvents={eventsThrough ? "none" : "auto"}
120 121 122 123 124
    />;
  }
}

module.exports = GLCanvas;