Hyperlinks to legalese such as Privacy Policy and Terms of Service

This commit is contained in:
Lyubomir Marinov 2016-11-29 14:04:56 -06:00
parent 841050953f
commit 1f457dfca5
11 changed files with 261 additions and 88 deletions

View File

@ -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
};

View File

@ -1 +1,2 @@
export * from './Container';
export * from './Link';

View File

@ -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
};

View File

@ -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'
};

View File

@ -1 +1,2 @@
export * from './BoxModel';
export * from './ColorPalette';

View File

@ -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
});

View File

@ -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

View File

@ -76,7 +76,7 @@ class Toolbar extends AbstractToolbar {
onClick = { this._onHangup }
style = {{
...styles.toolbarButton,
backgroundColor: ColorPalette.jitsiRed
backgroundColor: ColorPalette.red
}}
underlayColor = { underlayColor } />
<ToolbarButton

View File

@ -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
}
});

View File

@ -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>
);
}

View File

@ -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'
}
});