import * as React from 'react'; import { PermissionsAndroid, View, Platform, NativeModules, requireNativeComponent, findNodeHandle, } from 'react-native'; const RNMegacool: any = requireNativeComponent('RNMegacool'); interface MegacoolProps { /** Edit the default sharing text to make it more personal and customized for each place you use it. */ sharingText?: string; /** Set numbers of frames to record per second. Recommended range: 1 - 10. The default is 10: */ frameRate?: number; /** Set the number of frames per second when playing the GIF. The default is 10 frames / second. The GIF will be exported with this frame rate and it doesn't affect the recording frame rate. */ playbackFrameRate?: number; /** Max number of frames to record, default is 50 frames. */ maxFrames?: number; /** Set a delay (in milliseconds) for the last frame of the GIF. The default is 1 second to give a natural break before the GIF loops again. */ lastFrameDelay?: number; onStartedRecording?: () => void; onStoppedRecording?: () => void; onCapturedFrame?: () => void; onStartedSharing?: () => void; } // Wrap a native callback and return the value for the key const wrap = (f, key: string = null) => !f ? undefined : (ev) => f(!!key ? ev.nativeEvent[key] : ev.nativeEvent); interface State { url: string; } export class Megacool extends React.Component { state: State = { url: null }; view: View; static init(apiKey: string) { this.runCommand('init', [apiKey]); } startRecording() { return this.runCommand('startRecording'); } captureFrame() { return this.runCommand('captureFrame'); } stopRecording() { return this.runCommand('stopRecording'); } hidePreview() { return this.runCommand('hidePreview'); } presentMegacoolShare() { return this.runCommand('presentMegacoolShare'); } presentImageShare() { return this.runCommand('presentImageShare'); } async presentVideoShare() { const url = await this.videoUrl(); return this.runCommand('presentVideoShare', [url]); } async saveImageToCameraRoll() { await this.requestSavePermission(); return this.runCommand('saveImageToCameraRoll'); } async saveVideoToCameraRoll() { const url = await this.videoUrl(); await this.requestSavePermission(); return this.runCommand('saveVideoToCameraRoll', [url]); } async videoUrl(): Promise { if (!!this.state.url) return this.state.url; const url = await this.runCommand('videoUrl'); this.setState({ url }); return url; } // Handling in Android is absolute bullshit... It's slightly nicer by using // React Native's AndroidPermissions native module. But still embarrassingly ugly private async requestSavePermission() { if (Platform.OS !== 'android') return; const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE); if (granted !== PermissionsAndroid.RESULTS.GRANTED) { throw new Error('Saving to camera permission not granted') } } private handle() { return findNodeHandle(this.view); } private runCommand(name: string, args: any[] = []) { return Megacool.runCommand(name, [this.handle(), ...args]); } private static runCommand(name: string, args: any[] = []) { return NativeModules.RNMegacoolManager[name](...args); } render() { return ( this.view = ref} {...this.props} /> ); } }