Merge branch 'my-files-page'
This commit is contained in:
commit
1609cc0e3f
16 changed files with 390 additions and 78 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,7 @@
|
|||
dist/css/*
|
||||
dist/js/*
|
||||
!dist/js/flowplayer/
|
||||
!dist/js/flowplayer/
|
||||
node_modules
|
||||
.sass-cache
|
||||
.idea
|
||||
|
|
2
dist/index.html
vendored
2
dist/index.html
vendored
|
@ -21,6 +21,7 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.7.4/polyfill.js"></script>
|
||||
<script src="./js/flowplayer/flowplayer-3.2.13.min.js"></script>
|
||||
<script src="./js/lbry.js"></script>
|
||||
<script src="./js/component/common.js"></script>
|
||||
<script src="./js/component/splash.js"></script>
|
||||
|
@ -29,6 +30,7 @@
|
|||
<script src="./js/page/help.js"></script>
|
||||
<script src="./js/page/watch.js"></script>
|
||||
<script src="./js/page/report.js"></script>
|
||||
<script src="./js/page/my_files.js"></script>
|
||||
<script src="./js/page/start.js"></script>
|
||||
<script src="./js/app.js"></script>
|
||||
<script src="./js/main.js"></script>
|
||||
|
|
22
dist/js/flowplayer/flowplayer-3.2.13.min.js
vendored
Normal file
22
dist/js/flowplayer/flowplayer-3.2.13.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
dist/js/flowplayer/flowplayer-3.2.18.swf
vendored
Normal file
BIN
dist/js/flowplayer/flowplayer-3.2.18.swf
vendored
Normal file
Binary file not shown.
BIN
dist/js/flowplayer/flowplayer.controls-3.2.16.swf
vendored
Normal file
BIN
dist/js/flowplayer/flowplayer.controls-3.2.16.swf
vendored
Normal file
Binary file not shown.
33
js/app.js
33
js/app.js
|
@ -1,15 +1,10 @@
|
|||
var appStyles = {
|
||||
width: '800px',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
};
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
// For now, routes are in format ?page or ?page=args
|
||||
var match, param, val;
|
||||
[match, param, val] = window.location.search.match(/\??([^=]*)(?:=(.*))?/);
|
||||
|
||||
if (['settings', 'help', 'start', 'watch', 'report'].indexOf(param) != -1) {
|
||||
if (['settings', 'help', 'start', 'watch', 'report', 'files'].indexOf(param) != -1) {
|
||||
var viewingPage = param;
|
||||
} else {
|
||||
var viewingPage = 'home';
|
||||
|
@ -44,31 +39,21 @@ var App = React.createClass({
|
|||
}
|
||||
});
|
||||
},
|
||||
componentDidMount: function() {
|
||||
lbry.getStartNotice(function(notice) {
|
||||
if (notice) {
|
||||
alert(notice);
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
if (this.state.viewingPage == 'home') {
|
||||
var content = <HomePage />;
|
||||
return <HomePage />;
|
||||
} else if (this.state.viewingPage == 'settings') {
|
||||
var content = <SettingsPage />;
|
||||
return <SettingsPage />;
|
||||
} else if (this.state.viewingPage == 'help') {
|
||||
var content = <HelpPage />;
|
||||
return <HelpPage />;
|
||||
} else if (this.state.viewingPage == 'watch') {
|
||||
var content = <WatchPage name={this.state.pageArgs}/>;
|
||||
return <WatchPage name={this.state.pageArgs}/>;
|
||||
} else if (this.state.viewingPage == 'report') {
|
||||
var content = <ReportPage />;
|
||||
return <ReportPage />;
|
||||
} else if (this.state.viewingPage == 'files') {
|
||||
return <MyFilesPage />;
|
||||
} else if (this.state.viewingPage == 'start') {
|
||||
var content = <StartPage />;
|
||||
return <StartPage />;
|
||||
}
|
||||
return (
|
||||
<div style={appStyles}>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -3,9 +3,10 @@
|
|||
var Icon = React.createClass({
|
||||
propTypes: {
|
||||
style: React.PropTypes.object,
|
||||
fixed: React.PropTypes.boolean,
|
||||
},
|
||||
render: function() {
|
||||
var className = 'icon ' + this.props.icon;
|
||||
var className = 'icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + this.props.icon;
|
||||
return <span className={className} style={this.props.style}></span>
|
||||
}
|
||||
});
|
||||
|
@ -18,7 +19,8 @@ var Link = React.createClass({
|
|||
className = (this.props.button ? 'button-block button-' + this.props.button : 'button-text') +
|
||||
(this.props.hidden ? ' hidden' : '') + (this.props.disabled ? ' disabled' : '');
|
||||
return (
|
||||
<a className={className} href={href} style={this.props.style ? this.props.style : {}} onClick={this.props.onClick}>
|
||||
<a className={className} href={href} style={this.props.style ? this.props.style : {}}
|
||||
title={this.props.title} onClick={this.props.onClick}>
|
||||
{this.props.icon ? icon : '' }
|
||||
{this.props.label}
|
||||
</a>
|
||||
|
@ -26,6 +28,79 @@ var Link = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
// Generic menu styles
|
||||
var menuStyle = {
|
||||
border: '1px solid #aaa',
|
||||
padding: '4px',
|
||||
whiteSpace: 'nowrap',
|
||||
};
|
||||
|
||||
var Menu = React.createClass({
|
||||
handleWindowClick: function(e) {
|
||||
if (this.props.toggleButton && ReactDOM.findDOMNode(this.props.toggleButton).contains(e.target)) {
|
||||
// Toggle button was clicked
|
||||
this.setState({
|
||||
open: !this.state.open
|
||||
});
|
||||
} else if (this.state.open && !this.refs.div.contains(e.target)) {
|
||||
// Menu is open and user clicked outside of it
|
||||
this.setState({
|
||||
open: false
|
||||
});
|
||||
}
|
||||
},
|
||||
propTypes: {
|
||||
openButton: React.PropTypes.element,
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
open: false,
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
window.addEventListener('click', this.handleWindowClick, false);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
window.removeEventListener('click', this.handleWindowClick, false);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div ref='div' style={menuStyle} className={this.state.open ? '' : 'hidden'}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var menuItemStyle = {
|
||||
display: 'block',
|
||||
};
|
||||
var MenuItem = React.createClass({
|
||||
propTypes: {
|
||||
href: React.PropTypes.string,
|
||||
label: React.PropTypes.string,
|
||||
icon: React.PropTypes.string,
|
||||
onClick: React.PropTypes.function,
|
||||
},
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
iconPosition: 'left',
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var icon = (this.props.icon ? <Icon icon={this.props.icon} fixed /> : null);
|
||||
|
||||
return (
|
||||
<a style={menuItemStyle} href={this.props.href} label={this.props.label} title={this.props.label}
|
||||
className="button-text no-underline">
|
||||
{this.props.iconPosition == 'left' ? icon : null}
|
||||
{this.props.label}
|
||||
{this.props.iconPosition == 'left' ? null : icon}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var creditAmountStyle = {
|
||||
color: '#216C2A',
|
||||
fontWeight: 'bold',
|
||||
|
@ -48,4 +123,16 @@ var CreditAmount = React.createClass({
|
|||
</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var subPageLogoStyle = {
|
||||
maxWidth: '150px',
|
||||
display: 'block',
|
||||
marginTop: '36px',
|
||||
};
|
||||
|
||||
var SubPageLogo = React.createClass({
|
||||
render: function() {
|
||||
return <img src="img/lbry-dark-1600x528.png" style={subPageLogoStyle} />;
|
||||
}
|
||||
});
|
36
js/lbry.js
36
js/lbry.js
|
@ -103,6 +103,22 @@ lbry.getFileStatus = function(name, callback) {
|
|||
lbry.call('get_lbry_file', { 'name': name }, callback);
|
||||
}
|
||||
|
||||
lbry.getFilesInfo = function(callback) {
|
||||
lbry.call('get_lbry_files', {}, callback);
|
||||
}
|
||||
|
||||
lbry.startFile = function(name, callback) {
|
||||
lbry.call('start_lbry_file', { name: name }, callback);
|
||||
}
|
||||
|
||||
lbry.stopFile = function(name, callback) {
|
||||
lbry.call('stop_lbry_file', { name: name }, callback);
|
||||
}
|
||||
|
||||
lbry.deleteFile = function(name, callback) {
|
||||
lbry.call('delete_lbry_file', { name: name }, callback)
|
||||
}
|
||||
|
||||
lbry.getVersionInfo = function(callback) {
|
||||
lbry.call('version', {}, callback);
|
||||
};
|
||||
|
@ -154,6 +170,26 @@ lbry.imagePath = function(file)
|
|||
return lbry.rootPath + '/img/' + file;
|
||||
}
|
||||
|
||||
lbry.getMediaType = function(filename) {
|
||||
var dotIndex = filename.lastIndexOf('.');
|
||||
if (dotIndex == -1) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
var ext = filename.substr(dotIndex + 1);
|
||||
if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
|
||||
return 'video';
|
||||
} else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
|
||||
return 'audio';
|
||||
} else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
|
||||
return 'document';
|
||||
} else {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
lbry.stop = function(callback) {
|
||||
lbry.call('stop', {}, callback);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
var HelpPage = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<main>
|
||||
<main className="page">
|
||||
<SubPageLogo />
|
||||
<h1>Troubleshooting</h1>
|
||||
<p>Here are the most commonly encountered problems and what to try doing about them.</p>
|
||||
|
||||
|
|
|
@ -228,23 +228,41 @@ var Header = React.createClass({
|
|||
});
|
||||
|
||||
var topBarStyle = {
|
||||
'float': 'right'
|
||||
'float': 'right',
|
||||
'position': 'relative',
|
||||
'height': '26px',
|
||||
},
|
||||
balanceStyle = {
|
||||
'marginRight': '5px'
|
||||
},
|
||||
closeIconStyle = {
|
||||
'color': '#ff5155'
|
||||
};
|
||||
|
||||
var mainMenuStyle = {
|
||||
position: 'absolute',
|
||||
top: '26px',
|
||||
right: '0px',
|
||||
};
|
||||
|
||||
var MainMenu = React.createClass({
|
||||
render: function() {
|
||||
var isLinux = /linux/i.test(navigator.userAgent); // @TODO: find a way to use getVersionInfo() here without messy state management
|
||||
return (
|
||||
<div style={mainMenuStyle}>
|
||||
<Menu {...this.props}>
|
||||
<MenuItem href='/?files' label="My Files" icon='icon-cloud-download' />
|
||||
<MenuItem href='/?settings' label="Settings" icon='icon-gear' />
|
||||
<MenuItem href='/?help' label="Help" icon='icon-question-circle' />
|
||||
{isLinux ? <MenuItem href="/?start" label="Exit LBRY" icon="icon-close" />
|
||||
: null}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TopBar = React.createClass({
|
||||
onClose: function() {
|
||||
window.location.href = "?start";
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
balance: 0,
|
||||
showClose: /linux/i.test(navigator.userAgent) // @TODO: find a way to use getVersionInfo() here without messy state management
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
|
@ -254,27 +272,34 @@ var TopBar = React.createClass({
|
|||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
onClose: function() {
|
||||
window.location.href = "?start";
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<span className='top-bar' style={topBarStyle}>
|
||||
<span style={balanceStyle}>
|
||||
<CreditAmount amount={this.state.balance}/>
|
||||
</span>
|
||||
<Link href='/?settings' icon='icon-gear' />
|
||||
{ ' ' }
|
||||
<Link href='/?help' icon='icon-question-circle' />
|
||||
{ ' ' }
|
||||
<Link href="/?start" onClick={this.onClose} icon="icon-close" style={closeIconStyle} hidden={!this.state.showClose} />
|
||||
|
||||
<Link ref="menuButton" title="LBRY Menu" icon="icon-bars" />
|
||||
<MainMenu toggleButton={this.refs.menuButton} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var HomePage = React.createClass({
|
||||
componentDidMount: function() {
|
||||
lbry.getStartNotice(function(notice) {
|
||||
if (notice) {
|
||||
alert(notice);
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div className="page">
|
||||
<Header />
|
||||
<Discover />
|
||||
</div>
|
||||
|
|
138
js/page/my_files.js
Normal file
138
js/page/my_files.js
Normal file
|
@ -0,0 +1,138 @@
|
|||
var removeIconColumnStyle = {
|
||||
fontSize: '1.3em',
|
||||
height: '120px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
progressBarStyle = {
|
||||
height: '15px',
|
||||
width: '230px',
|
||||
backgroundColor: '#444',
|
||||
border: '2px solid #eee',
|
||||
display: 'inline-block',
|
||||
},
|
||||
myFilesRowImgStyle = {
|
||||
maxHeight: '100px',
|
||||
display: 'block',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
float: 'left'
|
||||
};
|
||||
|
||||
var MyFilesRow = React.createClass({
|
||||
onRemoveClicked: function() {
|
||||
var alertText = 'Are you sure you\'d like to remove "' + this.props.title + '?" This will ' +
|
||||
(this.completed ? ' stop the download and ' : '') +
|
||||
'permanently remove the file from your system.';
|
||||
|
||||
if (confirm(alertText)) {
|
||||
lbry.deleteFile(this.props.lbryUri);
|
||||
}
|
||||
},
|
||||
onPauseResumeClicked: function() {
|
||||
if (this.props.stopped) {
|
||||
lbry.startFile(this.props.lbryUri);
|
||||
} else {
|
||||
lbry.stopFile(this.props.lbryUri);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
if (this.props.completed) {
|
||||
var pauseLink = null;
|
||||
var curProgressBarStyle = {display: 'none'};
|
||||
} else {
|
||||
var pauseLink = <Link icon={this.props.stopped ? 'icon-play' : 'icon-pause'}
|
||||
label={this.props.stopped ? 'Resume download' : 'Pause download'}
|
||||
onClick={() => { this.onPauseResumeClicked() }} />;
|
||||
|
||||
var curProgressBarStyle = Object.assign({}, progressBarStyle);
|
||||
curProgressBarStyle.width = this.props.ratioLoaded * 230;
|
||||
curProgressBarStyle.borderRightWidth = 230 - (this.props.ratioLoaded * 230) + 2;
|
||||
}
|
||||
|
||||
if (this.props.showWatchButton) {
|
||||
// No support for lbry:// URLs in Windows or on Chrome yet
|
||||
if (/windows|win32/i.test(navigator.userAgent) || (window.chrome && window.navigator.vendor == "Google Inc.")) {
|
||||
var watchUri = "/?watch=" + this.props.lbryUri;
|
||||
} else {
|
||||
var watchUri = 'lbry://' + this.props.lbryUri;
|
||||
}
|
||||
|
||||
var watchLink = <Link href={watchUri} label="Watch" icon="icon-play" button="primary" />;
|
||||
} else {
|
||||
var watchLink = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="row-fluid">
|
||||
<div className="span3">
|
||||
<img src={this.props.imgUrl} alt={'Photo for ' + this.props.title} style={myFilesRowImgStyle} />
|
||||
</div>
|
||||
<div className="span6">
|
||||
<h2>{this.props.title}</h2>
|
||||
<div className={this.props.completed ? 'hidden' : ''} style={curProgressBarStyle}></div>
|
||||
{ ' ' }
|
||||
{this.props.completed ? 'Download complete' : (parseInt(this.props.ratioLoaded * 100) + '%')}
|
||||
<div>{ pauseLink }</div>
|
||||
<div>{ watchLink }</div>
|
||||
</div>
|
||||
<div className="span1" style={removeIconColumnStyle}>
|
||||
<Link icon="icon-close" title="Remove file" onClick={() => { this.onRemoveClicked() } } /><br />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MyFilesPage = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
filesInfo: null,
|
||||
};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.updateFilesInfo();
|
||||
},
|
||||
updateFilesInfo: function() {
|
||||
lbry.getFilesInfo((filesInfo) => {
|
||||
this.setState({
|
||||
filesInfo: (filesInfo ? filesInfo : []),
|
||||
});
|
||||
setTimeout(() => { this.updateFilesInfo() }, 1000);
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
if (this.state.filesInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.state.filesInfo.length) {
|
||||
var content = <span>You haven't downloaded anything from LBRY yet. Go <Link href="/" label="search for your first download" />!</span>;
|
||||
} else {
|
||||
var content = [];
|
||||
for (let fileInfo of this.state.filesInfo) {
|
||||
let {completed, written_bytes, total_bytes, lbry_uri, file_name, stopped, metadata} = fileInfo;
|
||||
let {name, stream_name, thumbnail} = metadata;
|
||||
|
||||
var title = (name || stream_name || ('lbry://' + lbry_uri));
|
||||
var ratioLoaded = written_bytes / total_bytes;
|
||||
var showWatchButton = (lbry.getMediaType(file_name) == 'video');
|
||||
|
||||
content.push(<MyFilesRow lbryUri={lbry_uri} title={title} completed={completed} stopped={stopped}
|
||||
ratioLoaded={ratioLoaded} imgUrl={thumbnail}
|
||||
showWatchButton={showWatchButton}/>);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<main className="page">
|
||||
<SubPageLogo />
|
||||
<h1>My files</h1>
|
||||
{content}
|
||||
<section>
|
||||
<Link href="/" label="<< Return" />
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -20,7 +20,8 @@ var ReportPage = React.createClass({
|
|||
},
|
||||
render: function() {
|
||||
return (
|
||||
<main>
|
||||
<main className="page">
|
||||
<SubPageLogo />
|
||||
<h1>Report a bug</h1>
|
||||
<section>
|
||||
<p>Please describe the problem you experienced and any information you think might be useful to us. Links to screenshots are great!</p>
|
||||
|
|
|
@ -73,7 +73,8 @@ var SettingsPage = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<main className="page">
|
||||
<SubPageLogo />
|
||||
<h1>Settings</h1>
|
||||
<section>
|
||||
<h4>Run on startup</h4>
|
||||
|
|
|
@ -4,7 +4,8 @@ var StartPage = React.createClass({
|
|||
},
|
||||
render: function() {
|
||||
return (
|
||||
<main>
|
||||
<main className="page">
|
||||
<SubPageLogo />
|
||||
<h1>LBRY has closed</h1>
|
||||
<Link href="lbry://lbry" label="Click here to start LBRY" />
|
||||
</main>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var videoStyle = {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
// height: '100%',
|
||||
backgroundColor: '#000'
|
||||
};
|
||||
|
||||
|
@ -19,19 +19,6 @@ var WatchPage = React.createClass({
|
|||
lbry.getStream(this.props.name);
|
||||
this.updateLoadStatus();
|
||||
},
|
||||
reloadIfNeeded: function() {
|
||||
// Fallback option for loading problems: every 15 seconds, if the video hasn't reported being
|
||||
// playable yet, ask it to reload.
|
||||
if (!this.state.readyToPlay) {
|
||||
this._video.load()
|
||||
setTimeout(() => { this.reloadIfNeeded() }, 15000);
|
||||
}
|
||||
},
|
||||
onCanPlay: function() {
|
||||
this.setState({
|
||||
readyToPlay: true
|
||||
});
|
||||
},
|
||||
updateLoadStatus: function() {
|
||||
lbry.getFileStatus(this.props.name, (status) => {
|
||||
if (!status || status.code != 'running' || status.written_bytes == 0) {
|
||||
|
@ -44,31 +31,20 @@ var WatchPage = React.createClass({
|
|||
setTimeout(() => { this.updateLoadStatus() }, 250);
|
||||
} else {
|
||||
this.setState({
|
||||
loadStatusMessage: "Buffering",
|
||||
downloadStarted: true,
|
||||
});
|
||||
setTimeout(() => { this.reloadIfNeeded() }, 15000);
|
||||
readyToPlay: true
|
||||
})
|
||||
flowplayer('player', 'js/flowplayer/flowplayer-3.2.18.swf');
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
if (!this.state.downloadStarted) {
|
||||
var video = null;
|
||||
} else {
|
||||
// If the download has started, render the <video> behind the scenes so it can start loading.
|
||||
// When the video is actually ready to play, the loading text is hidden and the video shown.
|
||||
var video = <video src={"/view?name=" + this.props.name} style={videoStyle}
|
||||
className={this.state.readyToPlay ? '' : 'hidden'} controls
|
||||
onCanPlay={this.onCanPlay} ref={(video) => {this._video = video}}/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<main className="page full-width">
|
||||
<div className={this.state.readyToPlay ? 'hidden' : ''}>
|
||||
<h3>Loading lbry://{this.props.name}</h3>
|
||||
{this.state.loadStatusMessage}...
|
||||
</div>
|
||||
{video}
|
||||
<a id="player" href={"/view?name=" + this.props.name} style={videoStyle} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,22 @@ body
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 800px;
|
||||
|
||||
&.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-fixed-width {
|
||||
/* This borrowed is from a component of Font Awesome we're not using, maybe add it? */
|
||||
width: (18em / 14);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section
|
||||
{
|
||||
margin-bottom: $spacing-vertical;
|
||||
|
@ -22,7 +38,7 @@ section
|
|||
}
|
||||
}
|
||||
|
||||
h1 { font-size: 2.0em; margin-bottom: $spacing-vertical / 2; margin-top: $spacing-vertical * 1.5; }
|
||||
h1 { font-size: 2.0em; margin-bottom: $spacing-vertical / 2; margin-top: $spacing-vertical; }
|
||||
h2 { font-size: 1.75em; }
|
||||
h3 { font-size: 1.4em; }
|
||||
h4 { font-size: 1.2em; }
|
||||
|
@ -127,15 +143,34 @@ input[type="search"]
|
|||
.button-text
|
||||
{
|
||||
color: $color-primary;
|
||||
text-decoration: underline;
|
||||
.icon
|
||||
{
|
||||
&:first-child {
|
||||
padding-right: 5px;
|
||||
}
|
||||
&:last-child:not(:only-child) {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.no-underline) {
|
||||
text-decoration: underline;
|
||||
.icon {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
&:hover
|
||||
{
|
||||
opacity: 0.70;
|
||||
transition: opacity .225s ease;
|
||||
text-decoration: underline;
|
||||
.icon {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
.icon:only-child {
|
||||
position: relative;
|
||||
top: 0.16em;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue