diff --git a/package.json b/package.json index 33d5b4e9..e80a07b6 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "create-torrent": "^3.22.1", "debug": "^2.2.0", "drag-drop": "^2.3.1", + "hyperx": "^1.4.0", "network-address": "^1.1.0", "pretty-bytes": "^3.0.0", "throttleit": "^1.0.0", diff --git a/renderer/views/app.js b/renderer/views/app.js index 3659c5b5..b691ba06 100644 --- a/renderer/views/app.js +++ b/renderer/views/app.js @@ -1,22 +1,26 @@ module.exports = App var h = require('virtual-dom/h') +var hyperx = require('hyperx') +var hx = hyperx(h) var Header = require('./header') var Player = require('./player') var TorrentList = require('./torrent-list') function App (state, dispatch) { - return h('.app', [ - Header(state, dispatch), - h('.content', [ - (function () { - if (state.view.url === '/') { - return TorrentList(state, dispatch) - } else if (state.view.url === '/player') { - return Player(state, dispatch) - } - })() - ]) - ]) + function getView () { + if (state.view.url === '/') { + return TorrentList(state, dispatch) + } else if (state.view.url === '/player') { + return Player(state, dispatch) + } + } + + return hx` + + ${Header(state, dispatch)} + ${getView()} + + ` } diff --git a/renderer/views/header.js b/renderer/views/header.js index ca0c3f0e..eb9bd3cf 100644 --- a/renderer/views/header.js +++ b/renderer/views/header.js @@ -1,32 +1,34 @@ module.exports = Header var h = require('virtual-dom/h') +var hyperx = require('hyperx') +var hx = hyperx(h) function Header (state, dispatch) { - return h('.header', [ - (function () { - if (process.platform === 'darwin') { - return h('.title', state.view.title) - } - })(), - h('.nav.left', [ - h('i.icon.back', { - onclick: onBack - }, 'chevron_left'), - h('i.icon.forward', { - onclick: onForward - }, 'chevron_right') - ]), - (function () { - if (state.view.url !== '/player') { - return h('.nav.right', [ - h('i.icon.add', { - onclick: onAddTorrent - }, 'add') - ]) - } - })() - ]) + return hx` + + ${getTitle()} + + chevron_left + chevron_right + + + ${plusButton()} + + + ` + + function getTitle () { + if (process.platform === 'darwin') { + return hx`${state.view.title}` + } + } + + function plusButton () { + if (state.view.url !== '/player') { + return hx`add` + } + } function onBack (e) { dispatch('back') diff --git a/renderer/views/player.js b/renderer/views/player.js index 2b0405f1..49c8f08b 100644 --- a/renderer/views/player.js +++ b/renderer/views/player.js @@ -1,6 +1,8 @@ module.exports = Player var h = require('virtual-dom/h') +var hyperx = require('hyperx') +var hx = hyperx(h) var electron = require('electron') function Player (state, dispatch) { @@ -23,14 +25,16 @@ function Player (state, dispatch) { } // Show the video as large as will fit in the window, play immediately - return h('.player', [ - h('video', { - src: state.server.localURL, - autoplay: true, - onloadedmetadata: onLoadedMetadata - }), - renderPlayerControls(state, dispatch) - ]) + return hx` + + + ${renderPlayerControls(state, dispatch)} + + ` // As soon as the video loads far enough to know the dimensions, resize the // window to match the video resolution @@ -48,22 +52,22 @@ function Player (state, dispatch) { // TODO: cast buttons function renderPlayerControls (state, dispatch) { var positionPercent = 100 * state.video.currentTime / state.video.duration - return h('.player-controls', [ - h('.scrub-bar', { - onclick: handleScrub, - ondrag: handleScrub - }, [ - h('.loading-bar', renderLoadingBar(state)), - h('.playback-cursor', { - style: { - left: 'calc(' + positionPercent + '% - 4px)' - } - }) - ]), - h('i.icon.play-pause', { - onclick: () => dispatch('playPause') - }, state.video.isPaused ? 'play_arrow' : 'pause') - ]) + var playbackCursorStyle = { left: 'calc(' + positionPercent + '% - 4px)' } + + return hx` + + + ${renderLoadingBar(state)} + + + dispatch('playPause')}> + ${state.video.isPaused ? 'play_arrow' : 'pause'} + + + ` // Handles a click or drag to scrub (jump to another position in the video) function handleScrub (e) { @@ -99,12 +103,16 @@ function renderLoadingBar (state) { } // Output an list of rectangles to show loading progress - return parts.map(function (part) { - return h('.loading-bar-part', { - style: { - left: (100 * part.start / numParts) + '%', - width: (100 * part.count / numParts) + '%' - } - }) - }) + return hx` + + ${parts.map(function (part) { + var style = { + left: (100 * part.start / numParts) + '%', + width: (100 * part.count / numParts) + '%' + } + + return hx`` + })} + + ` } diff --git a/renderer/views/torrent-list.js b/renderer/views/torrent-list.js index 88dfca3f..1c387bdd 100644 --- a/renderer/views/torrent-list.js +++ b/renderer/views/torrent-list.js @@ -1,6 +1,8 @@ module.exports = TorrentList var h = require('virtual-dom/h') +var hyperx = require('hyperx') +var hx = hyperx(h) var prettyBytes = require('pretty-bytes') function TorrentList (state, dispatch) { @@ -9,7 +11,7 @@ function TorrentList (state, dispatch) { : [] var list = torrents.map((torrent) => renderTorrent(state, dispatch, torrent)) - return h('.torrent-list', list) + return hx`${list}` } // Renders a torrent in the torrent list @@ -19,51 +21,74 @@ function renderTorrent (state, dispatch, torrent) { // Background image: show some nice visuals, like a frame from the movie, if possible var style = {} if (torrent.posterURL) { - style['background-image'] = 'linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%), url("' + torrent.posterURL + '")' + style['background-image'] = `linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%), url("${torrent.posterURL}")` } // Foreground: name of the torrent, basic info like size, play button, // cast buttons if available, and delete var elements = [ renderTorrentMetadata(torrent), - h('i.icon.delete', { - onclick: () => dispatch('deleteTorrent', torrent) - }, 'close'), - h('i.btn.icon.play', { - className: !torrent.ready ? 'disabled' : '', - onclick: () => dispatch('openPlayer', torrent) - }, 'play_arrow') + hx` + dispatch('deleteTorrent', torrent)}> + close + + `, + hx` + dispatch('openPlayer', torrent)}> + play_arrow + + ` ] + if (state.view.chromecast) { - elements.push(h('i.btn.icon.chromecast', { - className: !torrent.ready ? 'disabled' : '', - onclick: () => dispatch('openChromecast', torrent) - }, 'cast')) - } - if (state.view.devices.airplay) { - elements.push(h('i.btn.icon.airplay', { - className: !torrent.ready ? 'disabled' : '', - onclick: () => dispatch('openAirplay', torrent) - }, 'airplay')) + elements.push(hx` + dispatch('openChromecast', torrent)}> + cast + + `) } - return h('.torrent', {style: style}, elements) + if (state.view.devices.airplay) { + elements.push(hx` + dispatch('openAirplay', torrent)}> + airplay + + `) + } + + return hx`${elements}` } // Renders the torrent name and download progress function renderTorrentMetadata (torrent) { - return h('.metadata', [ - h('.name.ellipsis', torrent.name || 'Loading torrent...'), - h('.status', [ - h('span.progress', Math.floor(100 * torrent.progress) + '%'), - (function () { - if (torrent.ready && torrent.files.length > 1) { - return h('span.files', torrent.files.length + ' files') - } - })(), - h('span', torrent.numPeers + ' ' + (torrent.numPeers === 1 ? 'peer' : 'peers')), - h('span', prettyBytes(torrent.downloadSpeed) + '/s'), - h('span', prettyBytes(torrent.uploadSpeed) + '/s') - ]) - ]) + return hx` + + ${torrent.name || 'Loading torrent...'} + + ${Math.floor(100 * torrent.progress)}% + + ${getFilesLength()} + ${getPeers()} + ${prettyBytes(torrent.downloadSpeed)}/s + ${prettyBytes(torrent.uploadSpeed)}/s + + ` + + function getPeers () { + var count = torrent.numPeers === 1 ? 'peer' : 'peers' + return `${torrent.numPeers} ${count}` + } + + function getFilesLength () { + if (torrent.ready && torrent.files.length > 1) { + return hx`${torrent.files.length} files` + } + } }