Hyperlinks to legalese such as Privacy Policy and Terms of Service
This commit is contained in:
parent
841050953f
commit
1f457dfca5
|
@ -0,0 +1,87 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Linking, Text } from 'react-native';
|
||||
|
||||
/**
|
||||
* Implements a (hyper)link to a URL in the fashion of the HTML anchor element
|
||||
* and its href attribute.
|
||||
*/
|
||||
export class Link extends Component {
|
||||
/**
|
||||
* Initializes a new Link instance.
|
||||
*
|
||||
* @param {Object} props - Component properties.
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onPress = this._onPress.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
return (
|
||||
<Text
|
||||
onPress = { this._onPress }
|
||||
style = { this.props.style }>
|
||||
{
|
||||
this.props.children
|
||||
}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this instance that Linking failed to open the associated URL.
|
||||
*
|
||||
* @param {any} reason - The rejection reason.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onLinkingOpenURLRejected(reason) {
|
||||
const onRejected = this.props.onLinkingOpenURLRejected;
|
||||
|
||||
onRejected && onRejected(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles press on this Link. Opens the URL associated with this Link.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onPress() {
|
||||
Linking.openURL(this.props.url)
|
||||
.catch(reason => this._onLinkingOpenURLRejected(reason));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link component's property types.
|
||||
*/
|
||||
Link.propTypes = {
|
||||
/**
|
||||
* The children to be displayed within this Link.
|
||||
*/
|
||||
children: React.PropTypes.node,
|
||||
|
||||
/**
|
||||
* Notifies that this Link failed to open the URL associated with it.
|
||||
*/
|
||||
onLinkingOpenURLRejected: React.PropTypes.function,
|
||||
|
||||
/**
|
||||
* The CSS style to be applied to this Link for the purposes of display.
|
||||
*/
|
||||
style: React.PropTypes.object,
|
||||
|
||||
/**
|
||||
* The URL to be opened when this Link is clicked/pressed.
|
||||
*/
|
||||
url: React.PropTypes.string
|
||||
};
|
|
@ -1 +1,2 @@
|
|||
export * from './Container';
|
||||
export * from './Link';
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* The application's default properties related to the CSS box model such as
|
||||
* margins, borders, padding.
|
||||
*/
|
||||
export const BoxModel = {
|
||||
/**
|
||||
* The application's default margin when non-zero margin is necessary.
|
||||
*/
|
||||
margin: 10,
|
||||
|
||||
/**
|
||||
* The application's default padding when non-zero padding is necessary.
|
||||
*/
|
||||
padding: 10
|
||||
};
|
|
@ -1,11 +1,26 @@
|
|||
/**
|
||||
* The application color palette.
|
||||
* The application's definition of the default color black.
|
||||
*/
|
||||
const BLACK = '#111111';
|
||||
|
||||
/**
|
||||
* The application's color palette.
|
||||
*/
|
||||
export const ColorPalette = {
|
||||
appBackground: '#111111',
|
||||
/**
|
||||
* The application's background color.
|
||||
*/
|
||||
appBackground: BLACK,
|
||||
|
||||
/**
|
||||
* The application's definition of the default color black. Generally,
|
||||
* expected to be kept in sync with the application's background color for
|
||||
* the sake of consistency.
|
||||
*/
|
||||
black: BLACK,
|
||||
blue: '#17A0DB',
|
||||
buttonUnderlay: '#495258',
|
||||
jitsiBlue: '#17A0DB',
|
||||
jitsiDarkGrey: '#555555',
|
||||
jitsiRed: '#D00000',
|
||||
jitsiToggled: '#495258'
|
||||
darkGrey: '#555555',
|
||||
red: '#D00000',
|
||||
white: 'white'
|
||||
};
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export * from './BoxModel';
|
||||
export * from './ColorPalette';
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
import { createStyleSheet } from '../../../base/styles';
|
||||
import { ColorPalette, createStyleSheet } from '../../../base/styles';
|
||||
|
||||
import { styles as platformIndependentStyles } from '../styles';
|
||||
|
||||
/**
|
||||
* The base/default style of indicators such as audioMutedIndicator,
|
||||
* moderatorIndicator, and videoMutedIndicator.
|
||||
*/
|
||||
const indicator = {
|
||||
textShadowColor: ColorPalette.black,
|
||||
textShadowOffset: {
|
||||
height: -1,
|
||||
width: 0
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Native-specific styles for the film strip.
|
||||
*/
|
||||
|
@ -10,13 +22,7 @@ export const styles = createStyleSheet(platformIndependentStyles, {
|
|||
/**
|
||||
* Audio muted indicator style.
|
||||
*/
|
||||
audioMutedIndicator: {
|
||||
textShadowColor: 'black',
|
||||
textShadowOffset: {
|
||||
height: -1,
|
||||
width: 0
|
||||
}
|
||||
},
|
||||
audioMutedIndicator: indicator,
|
||||
|
||||
/**
|
||||
* Dominant speaker indicator background style.
|
||||
|
@ -29,13 +35,7 @@ export const styles = createStyleSheet(platformIndependentStyles, {
|
|||
/**
|
||||
* Moderator indicator style.
|
||||
*/
|
||||
moderatorIndicator: {
|
||||
textShadowColor: 'black',
|
||||
textShadowOffset: {
|
||||
height: -1,
|
||||
width: 0
|
||||
}
|
||||
},
|
||||
moderatorIndicator: indicator,
|
||||
|
||||
/**
|
||||
* Video thumbnail style.
|
||||
|
@ -48,11 +48,5 @@ export const styles = createStyleSheet(platformIndependentStyles, {
|
|||
/**
|
||||
* Video muted indicator style.
|
||||
*/
|
||||
videoMutedIndicator: {
|
||||
textShadowColor: 'black',
|
||||
textShadowOffset: {
|
||||
height: -1,
|
||||
width: 0
|
||||
}
|
||||
}
|
||||
videoMutedIndicator: indicator
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ColorPalette } from '../../base/styles';
|
||||
import { BoxModel, ColorPalette } from '../../base/styles';
|
||||
|
||||
/**
|
||||
* Film strip related styles common to both Web and native.
|
||||
|
@ -9,7 +9,7 @@ export const styles = {
|
|||
*/
|
||||
audioMutedIndicator: {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'white',
|
||||
color: ColorPalette.white,
|
||||
left: 20,
|
||||
position: 'absolute',
|
||||
top: 1
|
||||
|
@ -19,7 +19,7 @@ export const styles = {
|
|||
* Dominant speaker indicator style.
|
||||
*/
|
||||
dominantSpeakerIndicator: {
|
||||
color: 'white',
|
||||
color: ColorPalette.white,
|
||||
fontSize: 15
|
||||
},
|
||||
|
||||
|
@ -27,7 +27,7 @@ export const styles = {
|
|||
* Dominant speaker indicator background style.
|
||||
*/
|
||||
dominantSpeakerIndicatorBackground: {
|
||||
backgroundColor: ColorPalette.jitsiBlue,
|
||||
backgroundColor: ColorPalette.blue,
|
||||
borderRadius: 15,
|
||||
bottom: 2,
|
||||
left: 1,
|
||||
|
@ -41,7 +41,7 @@ export const styles = {
|
|||
filmStrip: {
|
||||
alignItems: 'flex-end',
|
||||
alignSelf: 'stretch',
|
||||
bottom: 10,
|
||||
bottom: BoxModel.margin,
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
left: 0,
|
||||
|
@ -55,7 +55,7 @@ export const styles = {
|
|||
* to allow scrolling through them if they do not fit within the display.
|
||||
*/
|
||||
filmStripScrollViewContentContainer: {
|
||||
paddingHorizontal: 10
|
||||
paddingHorizontal: BoxModel.padding
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -63,7 +63,7 @@ export const styles = {
|
|||
*/
|
||||
moderatorIndicator: {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'white',
|
||||
color: ColorPalette.white,
|
||||
left: 1,
|
||||
position: 'absolute',
|
||||
top: 1
|
||||
|
@ -74,7 +74,7 @@ export const styles = {
|
|||
*/
|
||||
thumbnail: {
|
||||
alignItems: 'stretch',
|
||||
backgroundColor: 'black',
|
||||
backgroundColor: ColorPalette.appBackground,
|
||||
borderColor: '#424242',
|
||||
borderStyle: 'solid',
|
||||
borderWidth: 1,
|
||||
|
@ -88,8 +88,8 @@ export const styles = {
|
|||
* Pinned video thumbnail style.
|
||||
*/
|
||||
thumbnailPinned: {
|
||||
borderColor: ColorPalette.jitsiBlue,
|
||||
shadowColor: 'black',
|
||||
borderColor: ColorPalette.blue,
|
||||
shadowColor: ColorPalette.black,
|
||||
shadowOffset: {
|
||||
height: 5,
|
||||
width: 5
|
||||
|
@ -102,7 +102,7 @@ export const styles = {
|
|||
*/
|
||||
videoMutedIndicator: {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'white',
|
||||
color: ColorPalette.white,
|
||||
left: 35,
|
||||
position: 'absolute',
|
||||
top: 1
|
||||
|
|
|
@ -76,7 +76,7 @@ class Toolbar extends AbstractToolbar {
|
|||
onClick = { this._onHangup }
|
||||
style = {{
|
||||
...styles.toolbarButton,
|
||||
backgroundColor: ColorPalette.jitsiRed
|
||||
backgroundColor: ColorPalette.red
|
||||
}}
|
||||
underlayColor = { underlayColor } />
|
||||
<ToolbarButton
|
||||
|
|
|
@ -35,7 +35,7 @@ const container = {
|
|||
*/
|
||||
const icon = {
|
||||
alignSelf: 'center',
|
||||
color: ColorPalette.jitsiDarkGrey,
|
||||
color: ColorPalette.darkGrey,
|
||||
fontSize: 24
|
||||
};
|
||||
|
||||
|
@ -49,7 +49,7 @@ export const styles = createStyleSheet({
|
|||
*/
|
||||
icon: {
|
||||
...icon,
|
||||
color: ColorPalette.jitsiDarkGrey
|
||||
color: ColorPalette.darkGrey
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@ export const styles = createStyleSheet({
|
|||
*/
|
||||
toolbarButton: {
|
||||
...button,
|
||||
backgroundColor: 'white',
|
||||
backgroundColor: ColorPalette.white,
|
||||
marginLeft: 20,
|
||||
marginRight: 20,
|
||||
opacity: 0.8
|
||||
|
@ -104,6 +104,6 @@ export const styles = createStyleSheet({
|
|||
*/
|
||||
whiteIcon: {
|
||||
...icon,
|
||||
color: 'white'
|
||||
color: ColorPalette.white
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,12 +2,23 @@ import React from 'react';
|
|||
import { Text, TextInput, TouchableHighlight, View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
AbstractWelcomePage,
|
||||
mapStateToProps
|
||||
} from './AbstractWelcomePage';
|
||||
import { Link } from '../../base/react';
|
||||
import { ColorPalette } from '../../base/styles';
|
||||
|
||||
import { AbstractWelcomePage, mapStateToProps } from './AbstractWelcomePage';
|
||||
import { styles } from './styles';
|
||||
|
||||
/**
|
||||
* The URL at which the privacy policy is available to the user.
|
||||
*/
|
||||
const PRIVACY_POLICY_URL = 'https://www.atlassian.com/legal/privacy-policy';
|
||||
|
||||
/**
|
||||
* The URL at which the terms of service are available to the user.
|
||||
*/
|
||||
const TERMS_OF_SERVICE_URL
|
||||
= 'https://www.atlassian.com/legal/customer-agreement';
|
||||
|
||||
/**
|
||||
* The native container rendering the welcome page.
|
||||
*
|
||||
|
@ -25,6 +36,25 @@ class WelcomePage extends AbstractWelcomePage {
|
|||
{
|
||||
this._renderLocalVideo()
|
||||
}
|
||||
{
|
||||
this._renderLocalVideoOverlay()
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a View over the local video. The latter is thought of as the
|
||||
* background (content) of this WelcomePage. The former is thought of as the
|
||||
* foreground (content) of this WelcomePage such as the room name input, the
|
||||
* button to initiate joining the specified room, etc.
|
||||
*
|
||||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderLocalVideoOverlay() {
|
||||
return (
|
||||
<View style = { styles.localVideoOverlay }>
|
||||
<View style = { styles.roomContainer }>
|
||||
<Text style = { styles.title }>Enter room name</Text>
|
||||
<TextInput
|
||||
|
@ -39,10 +69,22 @@ class WelcomePage extends AbstractWelcomePage {
|
|||
disabled = { this._isJoinDisabled() }
|
||||
onPress = { this._onJoinClick }
|
||||
style = { styles.button }
|
||||
underlayColor = 'white'>
|
||||
underlayColor = { ColorPalette.white }>
|
||||
<Text style = { styles.buttonText }>JOIN</Text>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View style = { styles.legaleseContainer }>
|
||||
<Link
|
||||
style = { styles.legaleseItem }
|
||||
url = { PRIVACY_POLICY_URL }>
|
||||
Privacy Policy
|
||||
</Link>
|
||||
<Link
|
||||
style = { styles.legaleseItem }
|
||||
url = { TERMS_OF_SERVICE_URL }>
|
||||
Terms of Service
|
||||
</Link>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,39 +1,26 @@
|
|||
import { ColorPalette, createStyleSheet } from '../../base/styles';
|
||||
import { BoxModel, ColorPalette, createStyleSheet } from '../../base/styles';
|
||||
|
||||
/**
|
||||
* Welcome page container style.
|
||||
* The default color of text on the WelcomePage.
|
||||
*/
|
||||
const container = {
|
||||
alignSelf: 'stretch',
|
||||
backgroundColor: ColorPalette.jitsiBlue,
|
||||
bottom: 0,
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: 0
|
||||
};
|
||||
const TEXT_COLOR = ColorPalette.white;
|
||||
|
||||
/**
|
||||
* The welcome page style.
|
||||
* TODO: Make styles more generic and reusable. Use color palette for all
|
||||
* colors.
|
||||
* The styles of WelcomePage.
|
||||
*/
|
||||
export const styles = createStyleSheet({
|
||||
/**
|
||||
* Join button text style.
|
||||
* Join button style.
|
||||
*/
|
||||
button: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: 'white',
|
||||
backgroundColor: ColorPalette.white,
|
||||
borderColor: ColorPalette.white,
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
height: 45,
|
||||
justifyContent: 'center',
|
||||
marginBottom: 10,
|
||||
marginTop: 10
|
||||
marginBottom: BoxModel.margin,
|
||||
marginTop: BoxModel.margin
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -46,25 +33,56 @@ export const styles = createStyleSheet({
|
|||
},
|
||||
|
||||
/**
|
||||
* Welcome page container style.
|
||||
* The style of the top-level container of WelcomePage.
|
||||
*/
|
||||
container,
|
||||
container: {
|
||||
alignSelf: 'stretch',
|
||||
backgroundColor: ColorPalette.blue,
|
||||
flex: 1
|
||||
},
|
||||
|
||||
/**
|
||||
* The style of the legal-related content such as (hyper)links to Privacy
|
||||
* Policy and Terms of Service displayed on the WelcomePage.
|
||||
*/
|
||||
legaleseContainer: {
|
||||
flex: 0,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
|
||||
/**
|
||||
* The style of a piece of legal-related content such as a (hyper)link to
|
||||
* Privacy Policy or Terms of Service displayed on the WelcomePage.
|
||||
*/
|
||||
legaleseItem: {
|
||||
color: TEXT_COLOR,
|
||||
margin: BoxModel.margin
|
||||
},
|
||||
|
||||
/**
|
||||
* The style of the View displayed over the local video. The latter is
|
||||
* thought of as the background (content) of WelcomePage. The former is
|
||||
* thought of as the foreground (content) of WelcomePage.
|
||||
*/
|
||||
localVideoOverlay: {
|
||||
bottom: 0,
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: 0
|
||||
},
|
||||
|
||||
/**
|
||||
* Container for room name input box and 'join' button.
|
||||
*/
|
||||
roomContainer: {
|
||||
...container,
|
||||
backgroundColor: 'transparent',
|
||||
padding: 30
|
||||
},
|
||||
|
||||
/**
|
||||
* Navigator container style.
|
||||
*/
|
||||
navContainer: {
|
||||
backgroundColor: ColorPalette.appBackground,
|
||||
flex: 1
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
margin: 3 * BoxModel.margin
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -72,11 +90,11 @@ export const styles = createStyleSheet({
|
|||
*/
|
||||
textInput: {
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: 'white',
|
||||
borderColor: ColorPalette.white,
|
||||
borderRadius: 8,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: 1,
|
||||
color: 'white',
|
||||
color: TEXT_COLOR,
|
||||
fontSize: 23,
|
||||
height: 50,
|
||||
padding: 4,
|
||||
|
@ -87,9 +105,9 @@ export const styles = createStyleSheet({
|
|||
* Application title style.
|
||||
*/
|
||||
title: {
|
||||
color: '#fff',
|
||||
color: TEXT_COLOR,
|
||||
fontSize: 25,
|
||||
marginBottom: 20,
|
||||
marginBottom: 2 * BoxModel.margin,
|
||||
textAlign: 'center'
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue