Use Material UI; improve Preferences Page
New principles for our UI: - Components should use inline styles whenever possible - Let's shrink the size of main.css to < 100 lines over time so it just contains typography and basic styles - Always require just the individual component that is needed from Material UI so that the whole library doesn't get loaded (important for startup perf)
This commit is contained in:
@@ -46,11 +46,14 @@ var BUILT_IN_ELECTRON_MODULES = [ 'electron' ]
|
||||
var BUILT_IN_DEPS = [].concat(BUILT_IN_NODE_MODULES, BUILT_IN_ELECTRON_MODULES)
|
||||
|
||||
var EXECUTABLE_DEPS = [
|
||||
'gh-release',
|
||||
'standard',
|
||||
'babel-cli',
|
||||
'babel-plugin-syntax-jsx',
|
||||
'babel-plugin-transform-react-jsx'
|
||||
'babel-plugin-transform-es2015-destructuring',
|
||||
'babel-plugin-transform-object-rest-spread',
|
||||
'babel-plugin-transform-react-jsx',
|
||||
'gh-release',
|
||||
'nodemon',
|
||||
'standard'
|
||||
]
|
||||
|
||||
main()
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"application-config": "^1.0.0",
|
||||
"bitfield": "^1.0.2",
|
||||
"chromecasts": "^1.8.0",
|
||||
"classnames": "^2.2.5",
|
||||
"create-torrent": "^3.24.5",
|
||||
"deep-equal": "^1.0.1",
|
||||
"dlnacasts": "^0.1.0",
|
||||
@@ -29,12 +28,14 @@
|
||||
"iso-639-1": "^1.2.1",
|
||||
"languagedetect": "^1.1.1",
|
||||
"location-history": "^1.0.0",
|
||||
"material-ui": "^0.15.4",
|
||||
"musicmetadata": "^2.0.2",
|
||||
"network-address": "^1.1.0",
|
||||
"parse-torrent": "^5.7.3",
|
||||
"prettier-bytes": "^1.0.1",
|
||||
"react": "^15.2.1",
|
||||
"react-dom": "^15.2.1",
|
||||
"react-tap-event-plugin": "^1.0.0",
|
||||
"run-parallel": "^1.1.6",
|
||||
"semver": "^5.1.0",
|
||||
"simple-concat": "^1.0.0",
|
||||
|
||||
@@ -5,9 +5,12 @@ crashReporter.init()
|
||||
|
||||
const dragDrop = require('drag-drop')
|
||||
const electron = require('electron')
|
||||
const fs = require('fs')
|
||||
const React = require('react')
|
||||
const ReactDOM = require('react-dom')
|
||||
const fs = require('fs')
|
||||
|
||||
// Required by Material UI -- adds `onTouchTap` event
|
||||
require('react-tap-event-plugin')()
|
||||
|
||||
const config = require('../config')
|
||||
const App = require('./views/app')
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
const c = require('classnames')
|
||||
const React = require('react')
|
||||
|
||||
class Button extends React.Component {
|
||||
static get propTypes () {
|
||||
return {
|
||||
className: React.PropTypes.string,
|
||||
onClick: React.PropTypes.func,
|
||||
theme: React.PropTypes.oneOf(['light', 'dark']),
|
||||
type: React.PropTypes.oneOf(['default', 'flat', 'raised'])
|
||||
}
|
||||
}
|
||||
|
||||
static get defaultProps () {
|
||||
return {
|
||||
theme: 'light',
|
||||
type: 'default'
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { theme, type, className, ...other } = this.props
|
||||
return (
|
||||
<button
|
||||
{...other}
|
||||
className={c(
|
||||
'Button',
|
||||
theme,
|
||||
type,
|
||||
className
|
||||
)}
|
||||
onClick={this.props.onClick}
|
||||
>
|
||||
{this.props.children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Button
|
||||
@@ -1,38 +1,33 @@
|
||||
const c = require('classnames')
|
||||
const electron = require('electron')
|
||||
const React = require('react')
|
||||
|
||||
const remote = electron.remote
|
||||
|
||||
const Button = require('./Button')
|
||||
const TextInput = require('./TextInput')
|
||||
const RaisedButton = require('material-ui/RaisedButton').default
|
||||
const TextField = require('material-ui/TextField').default
|
||||
|
||||
class PathSelector extends React.Component {
|
||||
static get propTypes () {
|
||||
return {
|
||||
className: React.PropTypes.string,
|
||||
defaultValue: React.PropTypes.string.isRequired,
|
||||
dialog: React.PropTypes.object,
|
||||
label: React.PropTypes.string.isRequired,
|
||||
onChange: React.PropTypes.func
|
||||
displayValue: React.PropTypes.string,
|
||||
id: React.PropTypes.string,
|
||||
onChange: React.PropTypes.func,
|
||||
title: React.PropTypes.string.isRequired,
|
||||
value: React.PropTypes.string.isRequired
|
||||
}
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
value: props.defaultValue
|
||||
}
|
||||
|
||||
this.handleClick = this.handleClick.bind(this)
|
||||
}
|
||||
|
||||
handleClick () {
|
||||
var opts = Object.assign({
|
||||
defaultPath: this.state.value,
|
||||
properties: [ 'openFile', 'openDirectory' ],
|
||||
title: this.props.label
|
||||
defaultPath: this.props.value,
|
||||
properties: [ 'openFile', 'openDirectory' ]
|
||||
}, this.props.dialog)
|
||||
|
||||
remote.dialog.showOpenDialog(
|
||||
@@ -40,28 +35,52 @@ class PathSelector extends React.Component {
|
||||
opts,
|
||||
(filenames) => {
|
||||
if (!Array.isArray(filenames)) return
|
||||
this.setState({value: filenames[0]})
|
||||
this.props.onChange && this.props.onChange(filenames[0])
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const id = this.props.title.replace(' ', '-').toLowerCase()
|
||||
return (
|
||||
<div className={c('PathSelector', this.props.className)}>
|
||||
<div className='label'>{this.props.label}:</div>
|
||||
<TextInput
|
||||
className='input'
|
||||
disabled
|
||||
value={this.state.value}
|
||||
/>
|
||||
<Button
|
||||
className='button'
|
||||
theme='dark'
|
||||
onClick={this.handleClick}
|
||||
<div
|
||||
className={this.props.className}
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className='label'
|
||||
style={{
|
||||
flex: '0 auto',
|
||||
marginRight: 10,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap'
|
||||
}}
|
||||
>
|
||||
Change…
|
||||
</Button>
|
||||
{this.props.title}:
|
||||
</div>
|
||||
<TextField
|
||||
className='control'
|
||||
disabled
|
||||
id={id}
|
||||
style={{
|
||||
flex: '1',
|
||||
fontSize: 14
|
||||
}}
|
||||
value={this.props.displayValue || this.props.value}
|
||||
/>
|
||||
<RaisedButton
|
||||
className='control'
|
||||
label='Change'
|
||||
onClick={this.handleClick}
|
||||
style={{
|
||||
marginLeft: 10
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,33 +1,142 @@
|
||||
const React = require('react')
|
||||
const path = require('path')
|
||||
|
||||
const PathSelector = require('./PathSelector')
|
||||
const Checkbox = require('material-ui/Checkbox').default
|
||||
const colors = require('material-ui/styles/colors')
|
||||
const RaisedButton = require('material-ui/RaisedButton').default
|
||||
|
||||
const PathSelector = require('./PathSelector')
|
||||
const {dispatch} = require('../lib/dispatcher')
|
||||
|
||||
class PreferencesPage extends React.Component {
|
||||
render () {
|
||||
var state = this.props.state
|
||||
constructor () {
|
||||
super()
|
||||
|
||||
this.handleDownloadPathChange =
|
||||
this.handleDownloadPathChange.bind(this)
|
||||
|
||||
this.handleOpenExternalPlayerChange =
|
||||
this.handleOpenExternalPlayerChange.bind(this)
|
||||
|
||||
this.handleExternalPlayerPathChange =
|
||||
this.handleExternalPlayerPathChange.bind(this)
|
||||
}
|
||||
|
||||
downloadPathSelector () {
|
||||
return (
|
||||
<div className='PreferencesPage'>
|
||||
<Preference>
|
||||
<PathSelector
|
||||
dialog={{
|
||||
title: 'Select download directory',
|
||||
properties: [ 'openDirectory' ]
|
||||
}}
|
||||
onChange={this.handleDownloadPathChange}
|
||||
title='Download location'
|
||||
value={this.props.state.unsaved.prefs.downloadPath}
|
||||
/>
|
||||
</Preference>
|
||||
)
|
||||
}
|
||||
|
||||
handleDownloadPathChange (filePath) {
|
||||
dispatch('updatePreferences', 'downloadPath', filePath)
|
||||
}
|
||||
|
||||
openExternalPlayerCheckbox () {
|
||||
return (
|
||||
<Preference>
|
||||
<Checkbox
|
||||
className='control'
|
||||
checked={!this.props.state.unsaved.prefs.openExternalPlayer}
|
||||
label={'Play torrent media files using WebTorrent'}
|
||||
onCheck={this.handleOpenExternalPlayerChange}
|
||||
/>
|
||||
</Preference>
|
||||
)
|
||||
}
|
||||
|
||||
handleOpenExternalPlayerChange (e, isChecked) {
|
||||
dispatch('updatePreferences', 'openExternalPlayer', !isChecked)
|
||||
}
|
||||
|
||||
externalPlayerPathSelector () {
|
||||
const playerName = path.basename(
|
||||
this.props.state.unsaved.prefs.externalPlayerPath || 'VLC'
|
||||
)
|
||||
|
||||
const description = this.props.state.unsaved.prefs.openExternalPlayer
|
||||
? `Torrent media files will always play in ${playerName}.`
|
||||
: `Torrent media files will play in ${playerName} if WebTorrent cannot ` +
|
||||
'play them.'
|
||||
|
||||
return (
|
||||
<Preference>
|
||||
<p>{description}</p>
|
||||
<PathSelector
|
||||
dialog={{
|
||||
title: 'Select media player app',
|
||||
properties: [ 'openFile' ]
|
||||
}}
|
||||
displayValue={playerName}
|
||||
onChange={this.handleExternalPlayerPathChange}
|
||||
title='External player'
|
||||
value={this.props.state.unsaved.prefs.externalPlayerPath}
|
||||
/>
|
||||
</Preference>
|
||||
)
|
||||
}
|
||||
|
||||
handleExternalPlayerPathChange (filePath) {
|
||||
if (path.extname(filePath) === '.app') {
|
||||
// Mac: Use executable in packaged .app bundle
|
||||
filePath += '/Contents/MacOS/' + path.basename(filePath, '.app')
|
||||
}
|
||||
dispatch('updatePreferences', 'externalPlayerPath', filePath)
|
||||
}
|
||||
|
||||
setDefaultAppButton () {
|
||||
return (
|
||||
<Preference>
|
||||
<p>WebTorrent is not currently the default torrent app.</p>
|
||||
<RaisedButton
|
||||
className='control'
|
||||
onClick={this.handleSetDefaultApp}
|
||||
label='Make WebTorrent the default'
|
||||
/>
|
||||
</Preference>
|
||||
)
|
||||
}
|
||||
|
||||
handleSetDefaultApp () {
|
||||
window.alert('TODO')
|
||||
// var isFileHandler = state.unsaved.prefs.isFileHandler
|
||||
// dispatch('updatePreferences', 'isFileHandler', !isFileHandler)
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
color: colors.grey400,
|
||||
marginLeft: 20,
|
||||
marginRight: 20
|
||||
}}
|
||||
>
|
||||
<PreferencesSection title='Downloads'>
|
||||
<Preference>
|
||||
{DownloadPathSelector(state)}
|
||||
</Preference>
|
||||
{this.downloadPathSelector()}
|
||||
</PreferencesSection>
|
||||
<PreferencesSection title='Playback'>
|
||||
<Preference>
|
||||
{ExternalPlayerPathSelector(state)}
|
||||
</Preference>
|
||||
{this.openExternalPlayerCheckbox()}
|
||||
{this.externalPlayerPathSelector()}
|
||||
</PreferencesSection>
|
||||
<PreferencesSection title='Default torrent app'>
|
||||
{this.setDefaultAppButton()}
|
||||
</PreferencesSection>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// {ExternalPlayerCheckbox(state)}
|
||||
// {DefaultAppCheckbox(state)}
|
||||
|
||||
class PreferencesSection extends React.Component {
|
||||
static get propTypes () {
|
||||
return {
|
||||
@@ -37,8 +146,18 @@ class PreferencesSection extends React.Component {
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='PreferencesSection'>
|
||||
<h2 className='title'>{this.props.title}</h2>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 30,
|
||||
marginTop: 30
|
||||
}}
|
||||
>
|
||||
<h2
|
||||
style={{
|
||||
color: colors.grey50,
|
||||
fontSize: 22
|
||||
}}
|
||||
>{this.props.title}</h2>
|
||||
{this.props.children}
|
||||
</div>
|
||||
)
|
||||
@@ -48,119 +167,15 @@ class PreferencesSection extends React.Component {
|
||||
class Preference extends React.Component {
|
||||
render () {
|
||||
return (
|
||||
<div className='Preference'>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 10
|
||||
}}
|
||||
>
|
||||
{this.props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function DownloadPathSelector (state) {
|
||||
return (
|
||||
<PathSelector
|
||||
className='download-path'
|
||||
label='Download location'
|
||||
dialog={{
|
||||
title: 'Select download directory',
|
||||
properties: [ 'openDirectory' ]
|
||||
}}
|
||||
defaultValue={state.unsaved.prefs.downloadPath}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
)
|
||||
|
||||
function handleChange (filePath) {
|
||||
dispatch('updatePreferences', 'downloadPath', filePath)
|
||||
}
|
||||
}
|
||||
|
||||
function ExternalPlayerPathSelector (state) {
|
||||
return (
|
||||
<PathSelector
|
||||
className='download-path'
|
||||
label='Player app location'
|
||||
dialog={{
|
||||
title: 'Select media player app',
|
||||
properties: [ 'openFile' ]
|
||||
}}
|
||||
defaultValue={state.unsaved.prefs.externalPlayerPath || '<VLC>'}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
)
|
||||
|
||||
function handleChange (filePath) {
|
||||
if (path.extname(filePath) === '.app') {
|
||||
// Get executable in packaged mac app
|
||||
var name = path.basename(filePath, '.app')
|
||||
filePath += '/Contents/MacOS/' + name
|
||||
}
|
||||
dispatch('updatePreferences', 'externalPlayerPath', filePath)
|
||||
}
|
||||
}
|
||||
|
||||
// function ExternalPlayerCheckbox (state) {
|
||||
// return renderCheckbox({
|
||||
// label: 'Play in External Player',
|
||||
// description: 'Media will play in external player',
|
||||
// property: 'openExternalPlayer',
|
||||
// value: state.saved.prefs.openExternalPlayer
|
||||
// },
|
||||
// state.unsaved.prefs.openExternalPlayer,
|
||||
// function (value) {
|
||||
// dispatch('updatePreferences', 'openExternalPlayer', value)
|
||||
// })
|
||||
// }
|
||||
|
||||
// function renderCheckbox (definition, value, callback) {
|
||||
// var iconClass = 'icon clickable'
|
||||
// if (value) iconClass += ' enabled'
|
||||
|
||||
// return (
|
||||
// <div key='{definition.key}' className='control-group'>
|
||||
// <div className='controls'>
|
||||
// <label className='control-label'>
|
||||
// <div className='preference-title'>{definition.label}</div>
|
||||
// </label>
|
||||
// <div className='controls'>
|
||||
// <label className='clickable' onClick={handleClick}>
|
||||
// <i
|
||||
// className={iconClass}
|
||||
// id='{definition.property}'
|
||||
// >
|
||||
// check_circle
|
||||
// </i>
|
||||
// <span className='checkbox-label'>{definition.description}</span>
|
||||
// </label>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// )
|
||||
// function handleClick () {
|
||||
// callback(!value)
|
||||
// }
|
||||
// }
|
||||
|
||||
// function DefaultAppCheckbox (state) {
|
||||
// var definition = {
|
||||
// key: 'file-handlers',
|
||||
// label: 'Handle Torrent Files'
|
||||
// }
|
||||
// var buttonText = state.unsaved.prefs.isFileHandler
|
||||
// ? 'Remove default app for torrent files'
|
||||
// : 'Make WebTorrent the default app for torrent files'
|
||||
// var controls = [(
|
||||
// <button key='toggle-handlers'
|
||||
// className='btn'
|
||||
// onClick={toggleFileHandlers}>
|
||||
// {buttonText}
|
||||
// </button>
|
||||
// )]
|
||||
// return renderControlGroup(definition, controls)
|
||||
|
||||
// function toggleFileHandlers () {
|
||||
// var isFileHandler = state.unsaved.prefs.isFileHandler
|
||||
// dispatch('updatePreferences', 'isFileHandler', !isFileHandler)
|
||||
// }
|
||||
// }
|
||||
|
||||
module.exports = PreferencesPage
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
const c = require('classnames')
|
||||
const React = require('react')
|
||||
|
||||
class TextInput extends React.Component {
|
||||
static get propTypes () {
|
||||
return {
|
||||
theme: React.PropTypes.oneOf('light', 'dark'),
|
||||
className: React.PropTypes.string
|
||||
}
|
||||
}
|
||||
|
||||
static get defaultProps () {
|
||||
return {
|
||||
theme: 'light'
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, theme, ...other } = this.props
|
||||
return (
|
||||
<input
|
||||
{...other}
|
||||
className={c(
|
||||
'TextInput',
|
||||
theme,
|
||||
className
|
||||
)}
|
||||
type='text'
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TextInput
|
||||
@@ -1,5 +1,9 @@
|
||||
const React = require('react')
|
||||
|
||||
const darkBaseTheme = require('material-ui/styles/baseThemes/darkBaseTheme').default
|
||||
const getMuiTheme = require('material-ui/styles/getMuiTheme').default
|
||||
const MuiThemeProvider = require('material-ui/styles/MuiThemeProvider').default
|
||||
|
||||
const Header = require('./header')
|
||||
|
||||
const Views = {
|
||||
@@ -16,8 +20,11 @@ const Modals = {
|
||||
'unsupported-media-modal': require('./unsupported-media-modal')
|
||||
}
|
||||
|
||||
module.exports = class App extends React.Component {
|
||||
var muiTheme = getMuiTheme(Object.assign(darkBaseTheme, {
|
||||
fontFamily: 'BlinkMacSystemFont, \'Helvetica Neue\', Helvetica, sans-serif'
|
||||
}))
|
||||
|
||||
module.exports = class App extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = props.state
|
||||
@@ -47,12 +54,14 @@ module.exports = class App extends React.Component {
|
||||
if (hideControls) cls.push('hide-video-controls')
|
||||
|
||||
var vdom = (
|
||||
<div className={'app ' + cls.join(' ')}>
|
||||
<Header state={state} />
|
||||
{this.getErrorPopover()}
|
||||
<div key='content' className='content'>{this.getView()}</div>
|
||||
{this.getModal()}
|
||||
</div>
|
||||
<MuiThemeProvider muiTheme={muiTheme}>
|
||||
<div className={'app ' + cls.join(' ')}>
|
||||
<Header state={state} />
|
||||
{this.getErrorPopover()}
|
||||
<div key='content' className='content'>{this.getView()}</div>
|
||||
{this.getModal()}
|
||||
</div>
|
||||
</MuiThemeProvider>
|
||||
)
|
||||
|
||||
return vdom
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
.Button {
|
||||
-webkit-app-region: no-drag;
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
color: #aaa;
|
||||
cursor: default;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
padding: 7px 18px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default button
|
||||
*/
|
||||
|
||||
.Button.default {
|
||||
color: #222;
|
||||
background-color: rgba(153, 153, 153, 0.1);
|
||||
}
|
||||
|
||||
.Button.default.dark {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.Button.default:hover,
|
||||
.Button.default:focus { /* Material design: focused */
|
||||
background-color: rgba(153, 153, 153, 0.2);
|
||||
}
|
||||
|
||||
.Button.default:active { /* Material design: pressed */
|
||||
background-color: rgba(153, 153, 153, 0.4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flat button
|
||||
*/
|
||||
|
||||
.Button.flat {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.Button.flat.dark {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.Button.flat:hover,
|
||||
.Button.flat:focus {
|
||||
background-color: rgba(153, 153, 153, 0.2);
|
||||
}
|
||||
|
||||
.Button.flat:active {
|
||||
background-color: rgba(153, 153, 153, 0.4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raised button
|
||||
*/
|
||||
|
||||
.Button.raised {
|
||||
background-color: #2196f3;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.Button.raised:hover,
|
||||
.Button.raised:focus {
|
||||
background-color: #38a0f5;
|
||||
}
|
||||
|
||||
.Button.raised:active {
|
||||
background-color: #51abf6;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
.PathSelector {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.PathSelector .label {
|
||||
margin-right: 10px;
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.PathSelector .input {
|
||||
flex: 5 5 200px;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
.TextInput {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 3px;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
padding: 3px 6px;
|
||||
width: 200px;
|
||||
-webkit-app-region: no-drag;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.TextInput.light {
|
||||
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.TextInput.dark {
|
||||
border: 1px solid rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
.PreferencesPage {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
.PreferencesSection:not(:last-child) {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.PreferencesSection .title {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.Preference:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ body {
|
||||
}
|
||||
|
||||
.app {
|
||||
color: #FFF;
|
||||
color: #FAFAFA; /* grey50 */
|
||||
font-family: BlinkMacSystemFont, 'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5em;
|
||||
@@ -91,9 +91,7 @@ table {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Material Icons'),
|
||||
local('MaterialIcons-Regular'),
|
||||
url('../MaterialIcons-Regular.woff2') format('woff2');
|
||||
src: url('MaterialIcons-Regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
.icon {
|
||||
@@ -1025,3 +1023,19 @@ video::-webkit-media-text-track-container {
|
||||
height: 32px;
|
||||
margin: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this class on Material UI components to get correct native app behavior:
|
||||
*
|
||||
* - Dragging the button should NOT drag the entire app window
|
||||
* - The cursor should be default, not a pointer (hand) like on the web
|
||||
*/
|
||||
|
||||
.control {
|
||||
-webkit-app-region: no-drag;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
.control * {
|
||||
cursor: default !important;
|
||||
}
|
||||
@@ -3,22 +3,11 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>WebTorrent Desktop</title>
|
||||
|
||||
<link rel="stylesheet" href="css/components/Button.css">
|
||||
<link rel="stylesheet" href="css/components/PathSelector.css">
|
||||
<link rel="stylesheet" href="css/components/TextInput.css">
|
||||
<link rel="stylesheet" href="css/pages/PreferencesPage.css">
|
||||
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="main.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- React prints a warning if you render to <body> directly -->
|
||||
<div id='body'></div>
|
||||
<!-- We can't just say src='...main.js', that breaks require()s -->
|
||||
<script>
|
||||
require('../build/renderer/main.js')
|
||||
</script>
|
||||
<script>require('../build/renderer/main.js')</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user