Merge pull request #82 from feross/ui

UI polish (Windows fullscreen, Linux/Windows player window title)
This commit is contained in:
Feross Aboukhadijeh
2016-03-07 22:48:25 -08:00
6 changed files with 73 additions and 48 deletions

View File

@@ -63,7 +63,7 @@ body {
height: 100%;
display: flex;
flex-flow: column;
animation: fadein 1s;
animation: fadein 0.3s;
}
/*

View File

@@ -1,4 +1,5 @@
console.time('init')
var airplay = require('airplay-js')
var cfg = require('application-config')('WebTorrent')
var cfgDirectory = require('application-config-path')('WebTorrent')
@@ -15,11 +16,12 @@ var path = require('path')
var torrentPoster = require('./lib/torrent-poster')
var WebTorrent = require('webtorrent')
var App = require('./views/app')
var createElement = require('virtual-dom/create-element')
var diff = require('virtual-dom/diff')
var patch = require('virtual-dom/patch')
var App = require('./views/app')
var ipcRenderer = electron.ipcRenderer
// For easy debugging in Developer Tools
var state = global.state = require('./state')
@@ -66,7 +68,10 @@ function init () {
// Calling update() updates the UI given the current state
// Do this at least once a second to show latest state for each torrent
// (eg % downloaded) and to keep the cursor in sync when playing a video
setInterval(update, 1000)
setInterval(function () {
update()
updateClientProgress()
}, 1000)
// All state lives in state.js. `state.saved` is read from and written to a
// file. All other state is ephemeral. Here we'll load state.saved:
@@ -84,7 +89,7 @@ function init () {
// ...same thing if you paste a torrent
document.addEventListener('paste', function () {
electron.ipcRenderer.send('addTorrentFromPaste')
ipcRenderer.send('addTorrentFromPaste')
})
// ...keyboard shortcuts
@@ -103,7 +108,6 @@ function init () {
// ...focus and blur. Needed to show correct dock icon text ("badge") in OSX
window.addEventListener('focus', function () {
state.isFocused = true
if (state.dock.badge > 0) electron.ipcRenderer.send('setBadge', '')
state.dock.badge = 0
})
@@ -125,7 +129,21 @@ function render (state) {
// Calls render() to go from state -> UI, then applies to vdom to the real DOM.
function update () {
vdomLoop.update(state)
updateDockIcon()
updateElectron()
}
function updateElectron () {
if (state.title !== state.prev.title) {
state.prev.title = state.title
ipcRenderer.send('setTitle', state.title)
}
if (state.dock.progress !== state.prev.progress) {
state.prev.progress = state.dock.progress
ipcRenderer.send('setProgress', state.dock.progress)
}
if (state.dock.badge !== state.prev.badge) {
ipcRenderer.send('setBadge', state.dock.badge || '')
}
}
// Events from the UI never modify state directly. Instead they call dispatch()
@@ -175,7 +193,7 @@ function dispatch (action, ...args) {
update()
}
if (action === 'toggleFullScreen') {
electron.ipcRenderer.send('toggleFullScreen')
ipcRenderer.send('toggleFullScreen', args[0])
update()
}
if (action === 'videoMouseMoved') {
@@ -185,20 +203,20 @@ function dispatch (action, ...args) {
}
function setupIpc () {
electron.ipcRenderer.on('addTorrent', function (e, torrentId) {
ipcRenderer.on('addTorrent', function (e, torrentId) {
dispatch('addTorrent', torrentId)
})
electron.ipcRenderer.on('seed', function (e, files) {
ipcRenderer.on('seed', function (e, files) {
dispatch('seed', files)
})
electron.ipcRenderer.on('fullscreenChanged', function (e, isFullScreen) {
ipcRenderer.on('fullscreenChanged', function (e, isFullScreen) {
state.isFullScreen = isFullScreen
update()
})
electron.ipcRenderer.on('addFakeDevice', function (e, device) {
ipcRenderer.on('addFakeDevice', function (e, device) {
var player = new EventEmitter()
player.play = (networkURL) => console.log(networkURL)
state.devices[device] = player
@@ -220,7 +238,7 @@ function detectDevices () {
function loadState (callback) {
cfg.read(function (err, data) {
if (err) console.error(err)
electron.ipcRenderer.send('log', 'loaded state from ' + cfg.filePath)
ipcRenderer.send('log', 'loaded state from ' + cfg.filePath)
// populate defaults if they're not there
state.saved = Object.assign({}, state.defaultSavedState, data)
@@ -238,14 +256,14 @@ function resumeTorrents () {
// Write state.saved to the JSON state file
function saveState () {
electron.ipcRenderer.send('log', 'saving state to ' + cfg.filePath)
ipcRenderer.send('log', 'saving state to ' + cfg.filePath)
cfg.write(state.saved, function (err) {
if (err) console.error(err)
update()
})
}
function updateDockIcon () {
function updateClientProgress () {
var progress = state.client.progress
var activeTorrentsExist = state.client.torrents.some(function (torrent) {
return torrent.progress !== 1
@@ -254,10 +272,7 @@ function updateDockIcon () {
if (!activeTorrentsExist || progress === 1) {
progress = -1
}
if (progress !== state.dock.progress) {
state.dock.progress = progress
electron.ipcRenderer.send('setProgress', progress)
}
state.dock.progress = progress
}
function onFiles (files) {
@@ -365,7 +380,6 @@ function addTorrentEvents (torrent) {
if (!state.isFocused) {
state.dock.badge += 1
electron.ipcRenderer.send('setBadge', state.dock.badge)
}
update()
@@ -431,8 +445,10 @@ function openPlayer (infoHash) {
function closePlayer () {
state.url = '/'
state.title = config.APP_NAME
update()
if (state.isFullScreen) {
electron.ipcRenderer.send('toggleFullScreen')
dispatch('toggleFullScreen', false)
}
restoreBounds()
stopServer()
@@ -507,14 +523,14 @@ function setDimensions (dimensions) {
var x = Math.floor((screenWidth - width) / 2)
var y = Math.floor((screenHeight - height) / 2)
electron.ipcRenderer.send('setAspectRatio', aspectRatio)
electron.ipcRenderer.send('setBounds', {x, y, width, height})
ipcRenderer.send('setAspectRatio', aspectRatio)
ipcRenderer.send('setBounds', {x, y, width, height})
}
function restoreBounds () {
electron.ipcRenderer.send('setAspectRatio', 0)
ipcRenderer.send('setAspectRatio', 0)
if (state.mainWindowBounds) {
electron.ipcRenderer.send('setBounds', state.mainWindowBounds, true)
ipcRenderer.send('setBounds', state.mainWindowBounds, true)
}
}

View File

@@ -31,6 +31,7 @@ module.exports = {
duration: 1, /* seconds */
mouseStationarySince: 0 /* Unix time in ms */
},
prev: {}, /* used for state diffing in updateElectron() */
/* Saved state is read from and written to a file every time the app runs.
* It should be simple and minimal and must be JSON.