GLCanvas.js 3.62 KB
Newer Older
1 2
import invariant from "invariant";
import React, {
3
  Component,
4
  requireNativeComponent,
5 6 7
} from "react-native";
import defer from "promise-defer";
import captureFrame from "./GLCanvas.captureFrame";
8

9 10 11
const serializeOption = config =>
config.format + ":" + config.type + ":" + config.quality;

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

class GLCanvas extends Component {
21 22 23 24 25 26 27 28 29 30 31

  componentWillMount () {
    this._pendingCaptureFrame = {};
  }

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

32 33 34 35 36
  setNativeProps (props) {
    this.refs.native.setNativeProps(props);
  }

  _addPendingCaptureFrame (config) {
37 38 39 40 41 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
    const key = serializeOption(config);
    return this._pendingCaptureFrame[key] || (
      (captureFrame(React.findNodeHandle(this.refs.native), config),
      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;
82
    }
83
    return this._addPendingCaptureFrame({
84 85 86 87 88 89
      format: "base64",
      type: "png",
      quality: 1,
      filePath: "",
      ...config
    }).promise;
90
  }
91 92 93 94 95 96 97 98 99 100 101

  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];
102
  };
103

104
  render () {
105
    const {
106
      width, height,
107 108
      onLoad, onProgress, eventsThrough,
      ...restProps } = this.props;
109 110 111
    return <GLCanvasNative
      ref="native"
      {...restProps}
112
      style={{ width, height }}
113 114 115 116
      onGLLoad={onLoad ? onLoad : null}
      onGLProgress={onProgress ? onProgress : null}
      onGLCaptureFrame={this.onGLCaptureFrame}
      pointerEvents={eventsThrough ? "none" : "auto"}
117 118 119 120 121
    />;
  }
}

module.exports = GLCanvas;