1e98c3cdfSJon Samp--- 2db5f2de4SAman Mittaltitle: Handle platform differences 3e98c3cdfSJon Samp--- 4e98c3cdfSJon Samp 5f2fad9b1SAman Mittalimport { SnackInline, Terminal } from '~/ui/components/Snippet'; 6e98c3cdfSJon Sampimport Video from '~/components/plugins/Video'; 73c9a6b96SBartosz Kaszubowskiimport { A } from '~/ui/components/Text'; 8a30150b3SAman Mittalimport { Step } from '~/ui/components/Step'; 99de0c686SAman Mittalimport { BoxLink } from '~/ui/components/BoxLink'; 109de0c686SAman Mittalimport { BookOpen02Icon } from '@expo/styleguide-icons'; 11e98c3cdfSJon Samp 12f2fad9b1SAman MittalAndroid, iOS, and the web have different capabilities. In our case, Android and iOS both are able to capture a screenshot with the `react-native-view-shot` library, however web browsers cannot. 13e98c3cdfSJon Samp 14f2fad9b1SAman MittalIn this chapter, let's learn how to make an exception for web browsers to get the same functionality on all platforms. 15e98c3cdfSJon Samp 16a30150b3SAman Mittal<Step label="1"> 17a30150b3SAman Mittal 18a30150b3SAman Mittal## Install and import dom-to-image 19e98c3cdfSJon Samp 203c9a6b96SBartosz KaszubowskiTo capture a screenshot on the web and save it as an image , we'll use a third-party library called [dom-to-image](https://github.com/tsayen/dom-to-image#readme). 213c9a6b96SBartosz KaszubowskiIt allows taking a screenshot of any DOM node and turning it into a vector (SVG) or raster (PNG or JPEG) image. 22e98c3cdfSJon Samp 23f2fad9b1SAman MittalStop the development server and run the following command to install the library: 24e98c3cdfSJon Samp 25f2fad9b1SAman Mittal<Terminal cmd={['$ npm install dom-to-image']} /> 26e98c3cdfSJon Samp 27f2fad9b1SAman MittalAfter installing it, make sure to restart the development server and press <kbd>w</kbd> in the terminal. 28e98c3cdfSJon Samp 29f2fad9b1SAman MittalTo use it, let's import it into **App.js**: 30e98c3cdfSJon Samp 31f2fad9b1SAman Mittal```jsx App.js 32f2fad9b1SAman Mittalimport domtoimage from 'dom-to-image'; 33f2fad9b1SAman Mittal``` 34e98c3cdfSJon Samp 35a30150b3SAman Mittal</Step> 36a30150b3SAman Mittal 37a30150b3SAman Mittal<Step label="2"> 38a30150b3SAman Mittal 39a30150b3SAman Mittal## Add platform-specific code 40f2fad9b1SAman Mittal 413c9a6b96SBartosz KaszubowskiReact Native provides a `Platform` module that gives us access to information about the platform on which the app is currently running. 423c9a6b96SBartosz KaszubowskiYou can use it to implement platform-specific behavior. 43f2fad9b1SAman Mittal 44f2fad9b1SAman MittalImport the `Platform` module in **App.js**: 45e98c3cdfSJon Samp 46e98c3cdfSJon Samp{/* prettier-ignore */} 47f2fad9b1SAman Mittal```jsx App.js 48f2fad9b1SAman Mittalimport { StyleSheet, View, /* @info Import the Platform module from react-native. */ Platform /* @end */ } from 'react-native'; 49f2fad9b1SAman Mittal``` 50e98c3cdfSJon Samp 513c9a6b96SBartosz KaszubowskiInside the `onSaveImageAsync()` function in the `<App>` component, we'll use `Platform.OS` to check whether the platform is `'web'`. 523c9a6b96SBartosz KaszubowskiIf it is not `'web'`, we'll run the logic added previously to take and save the screenshot. If it is `'web'`, 533c9a6b96SBartosz Kaszubowskiwe'll use the `domtoimage.toJpeg()` method to convert and capture the current `<View>` as a JPEG image. 54e98c3cdfSJon Samp 55f2fad9b1SAman Mittal<SnackInline 56f2fad9b1SAman Mittallabel="Take a screenshot" 57f2fad9b1SAman MittaltemplateId="tutorial/08-run-on-web/App" 58f2fad9b1SAman Mittaldependencies={['expo-image-picker', '@expo/vector-icons/FontAwesome', '@expo/vector-icons', 'expo-status-bar', '@expo/vector-icons/MaterialIcons', 'react-native-gesture-handler', 'react-native-reanimated', 'react-native-view-shot', 'expo-media-library', '[email protected]']} 59f2fad9b1SAman Mittalfiles={{ 60f2fad9b1SAman Mittal 'assets/images/background-image.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/503001f14bb7b8fe48a4e318ad07e910', 61f2fad9b1SAman Mittal 'assets/images/emoji1.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/be9751678c0b3f9c6bf55f60de815d30', 62f2fad9b1SAman Mittal 'assets/images/emoji2.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/7c0d14b79e134d528c5e0801699d6ccf', 63f2fad9b1SAman Mittal 'assets/images/emoji3.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/d713e2de164764c2ab3db0ab4e40c577', 64f2fad9b1SAman Mittal 'assets/images/emoji4.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/ac2163b98a973cb50bfb716cc4438f9a', 65f2fad9b1SAman Mittal 'assets/images/emoji5.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/9cc0e2ff664bae3af766b9750331c3ad', 66f2fad9b1SAman Mittal 'assets/images/emoji6.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/ce614cf0928157b3f7daa3cb8e7bd486', 67f2fad9b1SAman Mittal 'components/ImageViewer.js': 'tutorial/02-image-picker/ImageViewer.js', 68f2fad9b1SAman Mittal 'components/Button.js': 'tutorial/03-button-options/Button.js', 69f2fad9b1SAman Mittal 'components/CircleButton.js': 'tutorial/03-button-options/CircleButton.js', 70f2fad9b1SAman Mittal 'components/IconButton.js': 'tutorial/03-button-options/IconButton.js', 71f2fad9b1SAman Mittal 'components/EmojiPicker.js': 'tutorial/04-modal/EmojiPicker.js', 72f2fad9b1SAman Mittal 'components/EmojiList.js': 'tutorial/05-emoji-list/EmojiList.js', 73f2fad9b1SAman Mittal 'components/EmojiSticker.js': 'tutorial/06-gestures/CompleteEmojiSticker.js', 74f2fad9b1SAman Mittal}}> 75e98c3cdfSJon Samp 76f2fad9b1SAman Mittal{/* prettier-ignore */} 77f2fad9b1SAman Mittal```jsx 78f2fad9b1SAman Mittalconst onSaveImageAsync = async () => { 79f2fad9b1SAman Mittal /* @info Add the if condition here to check whether the current platform is web or not. */ if (Platform.OS !== 'web') { /* @end */ 80f2fad9b1SAman Mittal try { 81f2fad9b1SAman Mittal const localUri = await captureRef(imageRef, { 82f2fad9b1SAman Mittal height: 440, 83f2fad9b1SAman Mittal quality: 1, 84f2fad9b1SAman Mittal }); 85f2fad9b1SAman Mittal await MediaLibrary.saveToLibraryAsync(localUri); 86f2fad9b1SAman Mittal if (localUri) { 87f2fad9b1SAman Mittal alert('Saved!'); 88e98c3cdfSJon Samp } 89f2fad9b1SAman Mittal } catch (e) { 90f2fad9b1SAman Mittal console.log(e); 91e98c3cdfSJon Samp } 92f2fad9b1SAman Mittal } /* @info Add an else condition to run the logic when the current platform is the web. */else { 93*9ddb7644SVictor Li try { 94*9ddb7644SVictor Li const dataUrl = await domtoimage.toJpeg(imageRef.current, { 95f2fad9b1SAman Mittal quality: 0.95, 96f2fad9b1SAman Mittal width: 320, 97f2fad9b1SAman Mittal height: 440, 98*9ddb7644SVictor Li }); 99*9ddb7644SVictor Li 100f2fad9b1SAman Mittal let link = document.createElement('a'); 101f2fad9b1SAman Mittal link.download = 'sticker-smash.jpeg'; 102f2fad9b1SAman Mittal link.href = dataUrl; 103f2fad9b1SAman Mittal link.click(); 104*9ddb7644SVictor Li } catch (e) { 105f2fad9b1SAman Mittal console.log(e); 106*9ddb7644SVictor Li } 107e98c3cdfSJon Samp } /* @end */ 108e98c3cdfSJon Samp}; 109e98c3cdfSJon Samp``` 110e98c3cdfSJon Samp 111e98c3cdfSJon Samp</SnackInline> 112e98c3cdfSJon Samp 113f2fad9b1SAman MittalOn running the app in a web browser, we can now save a screenshot: 114f2fad9b1SAman Mittal 115f2fad9b1SAman Mittal<Video file="tutorial/web.mp4" /> 116f2fad9b1SAman Mittal 117a30150b3SAman Mittal</Step> 118a30150b3SAman Mittal 11962adc335SAman Mittal## Next step 120e98c3cdfSJon Samp 1219de0c686SAman MittalThe app does everything we set out for it to do, so it's time to shift our focus toward the purely aesthetic. 1229de0c686SAman Mittal 1239de0c686SAman Mittal<BoxLink 1249de0c686SAman Mittal title="Configure status bar, splash screen and app icon" 1259de0c686SAman Mittal Icon={BookOpen02Icon} 1269de0c686SAman Mittal description="In the next chapter, we will customize the app's status bar, splash screen, and app icon." 1279de0c686SAman Mittal href="/tutorial/configuration" 1289de0c686SAman Mittal/> 129