Merge pull request #82 from feross/ui
UI polish (Windows fullscreen, Linux/Windows player window title)
This commit is contained in:
11
main/ipc.js
11
main/ipc.js
@@ -2,9 +2,10 @@ module.exports = {
|
||||
init: init
|
||||
}
|
||||
|
||||
var electron = require('electron')
|
||||
var debug = require('debug')('webtorrent-app:ipcMain')
|
||||
var electron = require('electron')
|
||||
var ipcMain = electron.ipcMain
|
||||
var menu = require('./menu')
|
||||
var windows = require('./windows')
|
||||
|
||||
function init () {
|
||||
@@ -28,8 +29,12 @@ function init () {
|
||||
setProgress(progress)
|
||||
})
|
||||
|
||||
ipcMain.on('toggleFullScreen', function (e) {
|
||||
windows.main.setFullScreen(!windows.main.isFullScreen())
|
||||
ipcMain.on('toggleFullScreen', function (e, flag) {
|
||||
menu.toggleFullScreen(flag)
|
||||
})
|
||||
|
||||
ipcMain.on('setTitle', function (e, title) {
|
||||
windows.main.setTitle(title)
|
||||
})
|
||||
|
||||
ipcMain.on('log', function (e, message) {
|
||||
|
||||
30
main/menu.js
30
main/menu.js
@@ -5,19 +5,21 @@ var windows = require('./windows')
|
||||
|
||||
var app = electron.app
|
||||
|
||||
function toggleFullScreen () {
|
||||
debug('toggleFullScreen')
|
||||
function toggleFullScreen (flag) {
|
||||
debug('toggleFullScreen %s', flag)
|
||||
if (windows.main && windows.main.isVisible()) {
|
||||
windows.main.setFullScreen(!windows.main.isFullScreen())
|
||||
flag = flag != null ? flag : !windows.main.isFullScreen()
|
||||
windows.main.setFullScreen(flag)
|
||||
}
|
||||
}
|
||||
|
||||
// Sets whether the window should always show on top of other windows
|
||||
function toggleFloatOnTop () {
|
||||
debug('toggleFloatOnTop %s')
|
||||
function toggleFloatOnTop (flag) {
|
||||
debug('toggleFloatOnTop %s', flag)
|
||||
if (windows.main) {
|
||||
windows.main.setAlwaysOnTop(!windows.main.isAlwaysOnTop())
|
||||
getMenuItem('Float on Top').checked = windows.main.isAlwaysOnTop()
|
||||
flag = flag != null ? flag : !windows.main.isAlwaysOnTop()
|
||||
windows.main.setAlwaysOnTop(flag)
|
||||
getMenuItem('Float on Top').checked = flag
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +39,7 @@ function reloadWindow () {
|
||||
}
|
||||
|
||||
function addFakeDevice (device) {
|
||||
debug('addFakeDevice %s', device)
|
||||
windows.main.send('addFakeDevice', device)
|
||||
}
|
||||
|
||||
@@ -52,10 +55,11 @@ function onWindowHide () {
|
||||
getMenuItem('Float on Top').enabled = false
|
||||
}
|
||||
|
||||
function onToggleFullScreen () {
|
||||
windows.main.setMenuBarVisibility(!windows.main.isFullScreen())
|
||||
getMenuItem('Full Screen').checked = windows.main.isFullScreen()
|
||||
windows.main.send('fullscreenChanged', windows.main.isFullScreen())
|
||||
function onToggleFullScreen (isFullScreen) {
|
||||
isFullScreen = isFullScreen != null ? isFullScreen : windows.main.isFullScreen()
|
||||
windows.main.setMenuBarVisibility(!isFullScreen)
|
||||
getMenuItem('Full Screen').checked = isFullScreen
|
||||
windows.main.send('fullscreenChanged', isFullScreen)
|
||||
}
|
||||
|
||||
function getMenuItem (label) {
|
||||
@@ -150,12 +154,12 @@ function getMenuTemplate () {
|
||||
if (process.platform === 'darwin') return 'Ctrl+Command+F'
|
||||
else return 'F11'
|
||||
})(),
|
||||
click: toggleFullScreen
|
||||
click: () => toggleFullScreen()
|
||||
},
|
||||
{
|
||||
label: 'Float on Top',
|
||||
type: 'checkbox',
|
||||
click: toggleFloatOnTop
|
||||
click: () => toggleFloatOnTop()
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
var windows = module.exports = {
|
||||
main: null,
|
||||
createMainWindow: createMainWindow
|
||||
}
|
||||
|
||||
var config = require('../config')
|
||||
var debug = require('debug')('webtorrent-app:windows')
|
||||
var electron = require('electron')
|
||||
|
||||
var app = electron.app
|
||||
|
||||
var windows = {
|
||||
main: null,
|
||||
createMainWindow: createMainWindow
|
||||
}
|
||||
var isQuitting = false
|
||||
|
||||
app.on('before-quit', function () {
|
||||
@@ -41,8 +42,8 @@ function createMainWindow (menu) {
|
||||
win.on('blur', menu.onWindowHide)
|
||||
win.on('focus', menu.onWindowShow)
|
||||
|
||||
win.on('enter-full-screen', menu.onToggleFullScreen)
|
||||
win.on('leave-full-screen', menu.onToggleFullScreen)
|
||||
win.on('enter-full-screen', () => menu.onToggleFullScreen(true))
|
||||
win.on('leave-full-screen', () => menu.onToggleFullScreen(false))
|
||||
|
||||
win.on('close', function (e) {
|
||||
if (process.platform === 'darwin' && !isQuitting) {
|
||||
@@ -55,5 +56,3 @@ function createMainWindow (menu) {
|
||||
windows.main = null
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = windows
|
||||
|
||||
@@ -63,7 +63,7 @@ body {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
animation: fadein 1s;
|
||||
animation: fadein 0.3s;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user