No Description

App.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import React, { Component } from "react";
  2. import {
  3. StyleSheet,
  4. Text,
  5. View,
  6. ScrollView,
  7. Image,
  8. Switch,
  9. TextInput,
  10. Picker,
  11. Slider,
  12. WebView
  13. } from "react-native";
  14. import omit from "lodash/omit";
  15. import { captureRef, captureScreen } from "react-native-view-shot";
  16. import { Surface } from "gl-react-native";
  17. import GL from "gl-react";
  18. import MapView from "react-native-maps";
  19. import Video from "react-native-video";
  20. import Btn from "./Btn";
  21. const catsSource = {
  22. uri: "https://i.imgur.com/5EOyTDQ.jpg"
  23. };
  24. const shaders = GL.Shaders.create({
  25. helloGL: {
  26. frag: `
  27. precision highp float;
  28. varying vec2 uv;
  29. uniform float blue;
  30. void main () {
  31. gl_FragColor = vec4(uv.x, uv.y, blue, 1.0);
  32. }`
  33. }
  34. });
  35. const HelloGL = GL.createComponent(
  36. ({ blue }) => <GL.Node shader={shaders.helloGL} uniforms={{ blue }} />,
  37. { displayName: "HelloGL" }
  38. );
  39. export default class App extends Component {
  40. state = {
  41. previewSource: catsSource,
  42. error: null,
  43. res: null,
  44. value: {
  45. format: "png",
  46. quality: 0.9,
  47. result: "tmpfile",
  48. snapshotContentContainer: false
  49. }
  50. };
  51. snapshot = refname => () =>
  52. (refname ? captureRef(this.refs[refname], this.state.value) : captureScreen(this.state.value))
  53. .then(
  54. res =>
  55. this.state.value.result !== "tmpfile"
  56. ? res
  57. : new Promise((success, failure) =>
  58. // just a test to ensure res can be used in Image.getSize
  59. Image.getSize(
  60. res,
  61. (width, height) => (
  62. console.log(res, width, height), success(res)
  63. ),
  64. failure
  65. )
  66. )
  67. )
  68. .then(res =>
  69. this.setState({
  70. error: null,
  71. res,
  72. previewSource: {
  73. uri:
  74. this.state.value.result === "base64"
  75. ? "data:image/" + this.state.value.format + ";base64," + res
  76. : res
  77. }
  78. })
  79. )
  80. .catch(
  81. error => (
  82. console.warn(error),
  83. this.setState({ error, res: null, previewSource: null })
  84. )
  85. );
  86. render() {
  87. const { value, previewSource, error, res } = this.state;
  88. const {
  89. format,
  90. quality,
  91. width,
  92. height,
  93. result,
  94. snapshotContentContainer
  95. } = value;
  96. return (
  97. <ScrollView
  98. ref="full"
  99. style={styles.root}
  100. contentContainerStyle={styles.container}
  101. >
  102. <View ref="header" style={styles.header}>
  103. <Text style={styles.title}>😃 ViewShot Example 😜</Text>
  104. <View style={styles.p1}>
  105. <Text style={styles.text}>This is a </Text>
  106. <Text style={styles.code}>react-native-view-shot</Text>
  107. <Text style={styles.text}> showcase.</Text>
  108. </View>
  109. <View style={styles.preview}>
  110. {error ? (
  111. <Text style={styles.previewError}>
  112. {"" + (error.message || error)}
  113. </Text>
  114. ) : (
  115. <Image
  116. fadeDuration={0}
  117. resizeMode="contain"
  118. style={styles.previewImage}
  119. source={previewSource}
  120. />
  121. )}
  122. </View>
  123. <Text numberOfLines={1} style={styles.previewUriText}>
  124. {res ? res.slice(0, 200) : ""}
  125. </Text>
  126. </View>
  127. <View ref="form" style={styles.form}>
  128. <View style={styles.btns}>
  129. <Btn
  130. label="😻 Reset"
  131. onPress={() => this.setState({ previewSource: catsSource })}
  132. />
  133. <Btn label="📷 Head Section" onPress={this.snapshot("header")} />
  134. <Btn label="📷 Form" onPress={this.snapshot("form")} />
  135. <Btn
  136. label="📷 Experimental Section"
  137. onPress={this.snapshot("complex")}
  138. />
  139. <Btn label="📷 All (ScrollView)" onPress={this.snapshot("full")} />
  140. <Btn label="📷 GL React" onPress={this.snapshot("gl")} />
  141. <Btn label="📷 MapView" onPress={this.snapshot("mapview")} />
  142. <Btn label="📷 WebView" onPress={this.snapshot("webview")} />
  143. <Btn label="📷 Video" onPress={this.snapshot("video")} />
  144. <Btn label="📷 Native Screenshot" onPress={this.snapshot()}/>
  145. <Btn
  146. label="📷 Empty View (should crash)"
  147. onPress={this.snapshot("empty")}
  148. />
  149. </View>
  150. <View style={styles.field}>
  151. <Text style={styles.label}>Format</Text>
  152. <Picker
  153. style={styles.input}
  154. selectedValue={format}
  155. onValueChange={format =>
  156. this.setState({ value: { ...value, format } })}
  157. >
  158. <Picker.Item label="PNG" value="png" />
  159. <Picker.Item label="JPEG" value="jpeg" />
  160. <Picker.Item label="WEBM (android only)" value="webm" />
  161. <Picker.Item label="INVALID" value="_invalid_" />
  162. </Picker>
  163. </View>
  164. <View style={styles.field}>
  165. <Text style={styles.label}>Quality</Text>
  166. <Slider
  167. style={styles.input}
  168. value={quality}
  169. onValueChange={quality =>
  170. this.setState({ value: { ...value, quality } })}
  171. />
  172. <Text>{(quality * 100).toFixed(0)}%</Text>
  173. </View>
  174. <View style={styles.field}>
  175. <Text style={styles.label}>Size</Text>
  176. <Switch
  177. style={styles.switch}
  178. value={width !== undefined}
  179. onValueChange={checked =>
  180. this.setState({
  181. value: omit(
  182. {
  183. ...value,
  184. width: 300,
  185. height: 300
  186. },
  187. checked ? [] : ["width", "height"]
  188. )
  189. })}
  190. />
  191. {width !== undefined ? (
  192. <TextInput
  193. style={styles.inputText}
  194. value={"" + width}
  195. keyboardType="number-pad"
  196. onChangeText={txt =>
  197. !isNaN(txt) &&
  198. this.setState({
  199. value: { ...value, width: parseInt(txt, 10) }
  200. })}
  201. />
  202. ) : (
  203. <Text style={styles.inputText}>(auto)</Text>
  204. )}
  205. <Text>x</Text>
  206. {height !== undefined ? (
  207. <TextInput
  208. style={styles.inputText}
  209. value={"" + height}
  210. keyboardType="number-pad"
  211. onChangeText={txt =>
  212. !isNaN(txt) &&
  213. this.setState({
  214. value: { ...value, height: parseInt(txt, 10) }
  215. })}
  216. />
  217. ) : (
  218. <Text style={styles.inputText}>(auto)</Text>
  219. )}
  220. </View>
  221. <View style={styles.field}>
  222. <Text style={styles.label}>Result</Text>
  223. <Picker
  224. style={styles.input}
  225. selectedValue={result}
  226. onValueChange={result =>
  227. this.setState({ value: { ...value, result } })}
  228. >
  229. <Picker.Item label="tmpfile" value="tmpfile" />
  230. <Picker.Item label="base64" value="base64" />
  231. <Picker.Item label="data URI" value="data-uri" />
  232. <Picker.Item label="INVALID" value="_invalid_" />
  233. </Picker>
  234. </View>
  235. <View style={styles.field}>
  236. <Text style={styles.label}>snapshotContentContainer</Text>
  237. <Switch
  238. style={styles.switch}
  239. value={snapshotContentContainer}
  240. onValueChange={snapshotContentContainer =>
  241. this.setState({
  242. value: { ...value, snapshotContentContainer }
  243. })}
  244. />
  245. </View>
  246. </View>
  247. <View ref="empty" collapsable={false} />
  248. <View style={styles.experimental} ref="complex" collapsable={false}>
  249. <Text style={styles.experimentalTitle}>Experimental Stuff</Text>
  250. <Surface ref="gl" width={300} height={300}>
  251. <HelloGL blue={0.5} />
  252. </Surface>
  253. <MapView
  254. ref="mapview"
  255. initialRegion={{
  256. latitude: 37.78825,
  257. longitude: -122.4324,
  258. latitudeDelta: 0.0922,
  259. longitudeDelta: 0.0421
  260. }}
  261. style={{ width: 300, height: 300 }}
  262. />
  263. <View
  264. ref="webview"
  265. collapsable={false}
  266. style={{ width: 300, height: 300 }}
  267. >
  268. <WebView
  269. source={{
  270. uri: "https://github.com/gre/react-native-view-shot"
  271. }}
  272. />
  273. </View>
  274. <Video
  275. ref="video"
  276. style={{ width: 300, height: 300 }}
  277. source={require("./broadchurch.mp4")}
  278. volume={0}
  279. repeat
  280. />
  281. </View>
  282. </ScrollView>
  283. );
  284. }
  285. }
  286. const styles = StyleSheet.create({
  287. root: {
  288. flex: 1,
  289. backgroundColor: "#f6f6f6"
  290. },
  291. container: {
  292. paddingVertical: 20,
  293. backgroundColor: "#f6f6f6"
  294. },
  295. title: {
  296. fontSize: 20,
  297. textAlign: "center",
  298. margin: 10
  299. },
  300. experimental: {
  301. padding: 10,
  302. flexDirection: "column",
  303. alignItems: "center"
  304. },
  305. experimentalTitle: {
  306. fontSize: 16,
  307. margin: 10
  308. },
  309. p1: {
  310. marginBottom: 10,
  311. flexDirection: "row",
  312. flexWrap: "wrap",
  313. justifyContent: "center",
  314. alignItems: "center"
  315. },
  316. text: {
  317. color: "#333"
  318. },
  319. code: {
  320. fontWeight: "bold",
  321. color: "#000"
  322. },
  323. field: {
  324. flexDirection: "row",
  325. alignItems: "center",
  326. paddingVertical: 4,
  327. paddingHorizontal: 10
  328. },
  329. label: {
  330. minWidth: 80,
  331. fontStyle: "italic",
  332. color: "#888"
  333. },
  334. switch: {
  335. marginRight: 50
  336. },
  337. input: {
  338. flex: 1,
  339. marginHorizontal: 5
  340. },
  341. inputText: {
  342. flex: 1,
  343. marginHorizontal: 5,
  344. color: "red",
  345. textAlign: "center"
  346. },
  347. preview: {
  348. flexDirection: "row",
  349. alignItems: "center",
  350. justifyContent: "space-around"
  351. },
  352. previewImage: {
  353. width: 375,
  354. height: 300
  355. },
  356. previewUriText: {
  357. fontSize: 12,
  358. fontStyle: "italic",
  359. color: "#666",
  360. textAlign: "center",
  361. padding: 10,
  362. paddingBottom: 0
  363. },
  364. previewError: {
  365. width: 375,
  366. height: 300,
  367. paddingTop: 20,
  368. textAlign: "center",
  369. fontSize: 20,
  370. fontWeight: "bold",
  371. color: "#fff",
  372. backgroundColor: "#c00"
  373. },
  374. header: {
  375. backgroundColor: "#f6f6f6",
  376. borderColor: "#000",
  377. borderWidth: 1,
  378. paddingBottom: 20
  379. },
  380. form: {
  381. backgroundColor: "#fff"
  382. },
  383. btns: {
  384. flexDirection: "row",
  385. flexWrap: "wrap",
  386. alignItems: "center",
  387. justifyContent: "center",
  388. paddingVertical: 10,
  389. margin: 4
  390. }
  391. });