Add web player files (#112)

This commit is contained in:
Héctor Ramos 2017-10-04 09:10:33 -07:00 committed by Joel Marcey
parent 419a11af3e
commit 053f384cfe
3 changed files with 292 additions and 0 deletions

140
lib/core/SnackPlayer.js Normal file
View file

@ -0,0 +1,140 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule SnackPlayer
*/
'use strict';
var Prism = require('./Prism');
var React = require('React');
const PropTypes = require('prop-types');
const LatestSDKVersion = '21.0.0';
var ReactNativeToExpoSDKVersionMap = {
'0.48': '21.0.0',
'0.47': '20.0.0',
'0.46': '19.0.0',
'0.45': '18.0.0',
'0.44': '17.0.0',
'0.43': '16.0.0',
'0.42': '15.0.0',
'0.41': '14.0.0',
};
/**
* Use the SnackPlayer by including a ```SnackPlayer``` block in markdown.
*
* Optionally, include url parameters directly after the block's language.
* Valid options are name, description, and platform.
*
* E.g.
* ```SnackPlayer?platform=android&name=Hello%20world!
* import React from 'react';
* import { Text } from 'react-native';
*
* export default class App extends React.Component {
* render() {
* return <Text>Hello World!</Text>;
* }
* }
* ```
*/
class SnackPlayer extends React.Component {
constructor(props, context) {
super(props, context);
this.parseParams = this.parseParams.bind(this);
}
componentDidMount() {
window.ExpoSnack && window.ExpoSnack.initialize();
}
render() {
var code = encodeURIComponent(this.props.children);
var params = this.parseParams(this.props.params);
var platform = params.platform
? params.platform
: 'ios';
var name = params.name
? decodeURIComponent(params.name)
: 'Example';
var description = params.description
? decodeURIComponent(params.description)
: 'Example usage';
var optionalProps = {};
var { version } = this.context;
if (version === 'next') {
optionalProps[
'data-snack-sdk-version'
] = LatestSDKVersion;
} else {
optionalProps[
'data-snack-sdk-version'
] = ReactNativeToExpoSDKVersionMap[version] ||
LatestSDKVersion;
}
return (
<div className="snack-player">
<div
className="mobile-friendly-snack"
style={{ display: 'none' }}
>
<Prism>
{this.props.children}
</Prism>
</div>
<div
className="desktop-friendly-snack"
style={{ marginTop: 15, marginBottom: 15 }}
>
<div
data-snack-name={name}
data-snack-description={description}
data-snack-code={code}
data-snack-platform={platform}
data-snack-preview="true"
{...optionalProps}
style={{
overflow: 'hidden',
background: '#fafafa',
border: '1px solid rgba(0,0,0,.16)',
borderRadius: '4px',
height: '514px',
width: '880px',
}}
/>
</div>
</div>
);
}
parseParams(paramString) {
var params = {};
if (paramString) {
var pairs = paramString.split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
params[pair[0]] = pair[1];
}
}
return params;
}
}
SnackPlayer.contextTypes = {
version: PropTypes.number.isRequired,
};
module.exports = SnackPlayer;

77
lib/core/WebPlayer.js Normal file
View file

@ -0,0 +1,77 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule WebPlayer
*/
'use strict';
var Prism = require('./Prism');
var React = require('React');
var WEB_PLAYER_VERSION = '1.10.0';
/**
* Use the WebPlayer by including a ```ReactNativeWebPlayer``` block in markdown.
*
* Optionally, include url parameters directly after the block's language. For
* the complete list of url parameters, see: https://github.com/dabbott/react-native-web-player
*
* E.g.
* ```ReactNativeWebPlayer?platform=android
* import React from 'react';
* import { AppRegistry, Text } from 'react-native';
*
* const App = () => <Text>Hello World!</Text>;
*
* AppRegistry.registerComponent('MyApp', () => App);
* ```
*/
class WebPlayer extends React.Component {
constructor(props, context) {
super(props, context);
this.parseParams = this.parseParams.bind(this);
}
parseParams(paramString) {
var params = {};
if (paramString) {
var pairs = paramString.split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
params[pair[0]] = pair[1];
}
}
return params;
}
render() {
var hash = `#code=${encodeURIComponent(this.props.children)}`;
if (this.props.params) {
hash += `&${this.props.params}`;
}
return (
<div className={'web-player'}>
<Prism>{this.props.children}</Prism>
<iframe
style={{marginTop: 4}}
width="880"
height={this.parseParams(this.props.params).platform === 'android' ? '425' : '420'}
data-src={`//cdn.rawgit.com/dabbott/react-native-web-player/gh-v${WEB_PLAYER_VERSION}/index.html${hash}`}
frameBorder="0"
/>
</div>
);
}
}
module.exports = WebPlayer;

View file

@ -0,0 +1,75 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/* eslint-disable module-strict */
(function() {
"use strict";
// Not on browser
if (typeof document === "undefined") {
return;
}
document.addEventListener("DOMContentLoaded", init);
function init() {
var mobile = isMobile();
if (mobile) {
document
.querySelector(".nav-site-wrapper a[data-target]")
.addEventListener("click", toggleTarget);
}
var webPlayerList = document.querySelectorAll(".web-player");
// Either show interactive or static code block, depending on desktop or mobile
for (var i = 0; i < webPlayerList.length; ++i) {
webPlayerList[i].classList.add(mobile ? "mobile" : "desktop");
if (!mobile) {
// Determine location to look up required assets
var assetRoot = encodeURIComponent(
document.location.origin + "/react-native"
);
// Set iframe src. Do this dynamically so the iframe never loads on mobile.
var iframe = webPlayerList[i].querySelector("iframe");
iframe.src =
iframe.getAttribute("data-src") + "&assetRoot=" + assetRoot;
}
}
var snackPlayerList = document.querySelectorAll(".snack-player");
// Either show interactive or static code block, depending on desktop or mobile
for (var i = 0; i < snackPlayerList.length; ++i) {
var snackPlayer = snackPlayerList[i];
var snackDesktopPlayer = snackPlayer.querySelectorAll(
".desktop-friendly-snack"
)[0];
var plainCodeExample = snackPlayer.querySelectorAll(
".mobile-friendly-snack"
)[0];
if (mobile) {
snackDesktopPlayer.remove();
plainCodeExample.style.display = "block";
} else {
plainCodeExample.remove();
}
}
}
// Primitive mobile detection
function isMobile() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
);
}
})();