diff --git a/renderer/index.css b/renderer/index.css index 11dac2ed..8932b511 100644 --- a/renderer/index.css +++ b/renderer/index.css @@ -200,6 +200,10 @@ i:not(.disabled):hover { cursor: none; } +.app.hide-header .header { + display: none; +} + .header .title { opacity: 0.6; position: absolute; @@ -719,6 +723,47 @@ body.drag .torrent-placeholder span { color: #9af; } +/* + * ERRORS + */ + +.error-popover { + position: fixed; + z-index: 1001; + top: 36px; + margin: 0; + width: 100%; + overflow: hidden; +} + +.app.hide-header .error-popover { + top: 0px; +} + +.error-popover.hidden { + display: none; +} + +.error-popover .error, +.error-popover .title { + padding: 10px; + background-color: rgba(0, 0, 0, 0.8); + border-bottom: 1px solid #444; +} + +.error-popover .title { + font-weight: bold; + color: #c44; +} + +.error-popover .error { + color: #bbb; +} + +.error-popover .error:last-child { + border-bottom: none; +} + /* * MEDIA QUERIES */ diff --git a/renderer/index.js b/renderer/index.js index 755a8a58..fbadd52b 100644 --- a/renderer/index.js +++ b/renderer/index.js @@ -636,8 +636,11 @@ function restoreBounds () { function onError (err) { console.error(err.stack) - window.alert(err.message || err) playInterfaceSound(config.SOUND_ERROR) + state.errors.push({ + time: new Date().getTime(), + message: err.message || err + }) update() } diff --git a/renderer/state.js b/renderer/state.js index 0f43d18f..fb0d2ba2 100644 --- a/renderer/state.js +++ b/renderer/state.js @@ -38,6 +38,7 @@ module.exports = { badge: 0, progress: 0 }, + errors: [], /* user-facing errors */ /* * Saved state is read from and written to a file every time the app runs. diff --git a/renderer/views/app.js b/renderer/views/app.js index c7e066b0..3c8b0843 100644 --- a/renderer/views/app.js +++ b/renderer/views/app.js @@ -23,28 +23,41 @@ function App (state, dispatch) { !state.video.isPaused && state.video.location === 'local' + // Hide the header on Windows/Linux when in the player + // On OSX, the header appears as part of the title bar + var hideHeader = process.platform !== 'darwin' && state.url === 'player' + var cls = [ 'view-' + state.url, /* e.g. view-home, view-player */ 'is-' + process.platform /* e.g. is-darwin, is-win32, is-linux */ ] - if (state.window.isFullScreen) cls.push('is-fullscreen') if (state.window.isFocused) cls.push('is-focused') if (hideControls) cls.push('hide-video-controls') + if (hideHeader) cls.push('hide-header') + return hx`
- ${getHeader()} + ${Header(state, dispatch)} + ${getErrorPopover()}
${getView()}
${getModal()}
` - function getHeader () { - var isOSX = process.platform === 'darwin' - // Hide the header on Windows/Linux when in the player - if (isOSX || state.url !== 'player') { - return Header(state, dispatch) - } + function getErrorPopover () { + var now = new Date().getTime() + var recentErrors = state.errors.filter((x) => now - x.time < 5000) + + var errorElems = recentErrors.map(function (error) { + return hx`
${error.message}
` + }) + return hx` +
+
Error
+ ${errorElems} +
+ ` } function getModal () {