diff --git a/package.json b/package.json index 178dc84df..dc656400d 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "build": "yarn compile && electron-builder build", "postinstall": "electron-builder install-app-deps", "precommit": "lint-staged", - "lint": "eslint src/**/*.{js,jsx} --fix", - "pretty": "prettier src/**/*.{js,jsx,scss,json} --write" + "lint": "eslint 'src/**/*.{js,jsx}' --fix", + "pretty-print": "prettier 'src/**/*.{js,jsx,scss,json}' --write" }, "keywords": [ "lbry" diff --git a/src/main/index.js b/src/main/index.js index 67e16acca..6c83391ff 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,68 +1,39 @@ +/* eslint-disable no-console */ // Module imports -const { - app, - BrowserWindow, - ipcMain, - Menu, - Tray, - globalShortcut, -} = require("electron"); -const path = require("path"); -const url = require("url"); -const jayson = require("jayson"); -const semver = require("semver"); -const https = require("https"); -const keytar = require("keytar"); -// tree-kill has better cross-platform handling of -// killing a process. child-process.kill was unreliable -const kill = require("tree-kill"); -const child_process = require("child_process"); -const assert = require("assert"); +import Path from 'path'; +import Url from 'url'; +import Jayson from 'jayson'; +import Semver from 'semver'; +import Https from 'https'; +import Keytar from 'keytar'; +import ChildProcess from 'child_process'; +import Assert from 'assert'; +import { app, BrowserWindow, globalShortcut, ipcMain, Menu, Tray } from 'electron'; +import mainMenu from './menu/mainMenu'; const localVersion = app.getVersion(); -const setMenu = require("./menu/main-menu.js"); -export const contextMenu = require("./menu/context-menu"); +export { contextMenu as Default } from './menu/contextMenu'; // Debug configs -const isDevelopment = process.env.NODE_ENV === "development"; -if (isDevelopment) { - try { - const { - default: installExtension, - REACT_DEVELOPER_TOOLS, - REDUX_DEVTOOLS, - } = require("electron-devtools-installer"); - app.on("ready", () => { - [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => { - installExtension(extension) - .then(name => console.log(`Added Extension: ${name}`)) - .catch(err => console.log("An error occurred: ", err)); - }); - }); - } catch (err) { - console.error(err); - } -} +const isDevelopment = process.env.NODE_ENV === 'development'; // Misc constants -const LATEST_RELEASE_API_URL = - "https://api.github.com/repos/lbryio/lbry-app/releases/latest"; -const DAEMON_PATH = - process.env.LBRY_DAEMON || path.join(__static, "daemon/lbrynet-daemon"); +const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest'; +const DAEMON_PATH = process.env.LBRY_DAEMON || Path.join(__static, 'daemon/lbrynet-daemon'); const rendererUrl = isDevelopment ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` : `file://${__dirname}/index.html`; -const client = jayson.client.http({ - host: "localhost", +const client = Jayson.client.http({ + host: 'localhost', port: 5279, - path: "/", + path: '/', timeout: 1000, }); // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. -let win; +let rendererWindow; // Also keep the daemon subprocess alive let daemonSubprocess; @@ -95,8 +66,8 @@ function processRequestedUri(uri) { // lbry://channel/#claimid. We remove the slash here as well. // On Linux and Mac, we just return the URI as given. - if (process.platform === "win32") { - return uri.replace(/\/$/, "").replace("/#", "#"); + if (process.platform === 'win32') { + return uri.replace(/\/$/, '').replace('/#', '#'); } return uri; } @@ -109,223 +80,22 @@ function processRequestedUri(uri) { function openItem(fullPath) { const subprocOptions = { detached: true, - stdio: "ignore", + stdio: 'ignore', }; let child; - if (process.platform === "darwin") { - child = child_process.spawn("open", [fullPath], subprocOptions); - } else if (process.platform === "linux") { - child = child_process.spawn("xdg-open", [fullPath], subprocOptions); - } else if (process.platform === "win32") { - child = child_process.spawn( - fullPath, - Object.assign({}, subprocOptions, { shell: true }) - ); + if (process.platform === 'darwin') { + child = ChildProcess.spawn('open', [fullPath], subprocOptions); + } else if (process.platform === 'linux') { + child = ChildProcess.spawn('xdg-open', [fullPath], subprocOptions); + } else if (process.platform === 'win32') { + child = ChildProcess.spawn(fullPath, Object.assign({}, subprocOptions, { shell: true })); } // Causes child process reference to be garbage collected, allowing main process to exit child.unref(); } -function getPidsForProcessName(name) { - if (process.platform === "win32") { - const tasklistOut = child_process.execSync( - `tasklist /fi "Imagename eq ${name}.exe" /nh`, - { encoding: "utf8" } - ); - if (tasklistOut.startsWith("INFO")) { - return []; - } - return tasklistOut.match(/[^\r\n]+/g).map(line => line.split(/\s+/)[1]); // Second column of every non-empty line - } - const pgrepOut = child_process.spawnSync("pgrep", ["-x", name], { - encoding: "utf8", - }).stdout; - return pgrepOut.match(/\d+/g); -} - -function createWindow() { - // Disable renderer process's webSecurity on development to enable CORS. - win = isDevelopment - ? new BrowserWindow({ - backgroundColor: "#155B4A", - minWidth: 800, - minHeight: 600, - webPreferences: { webSecurity: false }, - }) - : new BrowserWindow({ - backgroundColor: "#155B4A", - minWidth: 800, - minHeight: 600, - }); - - win.webContents.session.setUserAgent(`LBRY/${localVersion}`); - - win.maximize(); - if (isDevelopment) { - win.webContents.openDevTools(); - } - win.loadURL(rendererUrl); - if (openUri) { - // We stored and received a URI that an external app requested before we had a window object - win.webContents.on("did-finish-load", () => { - win.webContents.send("open-uri-requested", openUri); - }); - } - - win.removeAllListeners(); - - win.on("close", event => { - if (minimize) { - event.preventDefault(); - win.hide(); - } - }); - - win.on("closed", () => { - win = null; - }); - - win.on("hide", () => { - // Checks what to show in the tray icon menu - if (minimize) updateTray(); - }); - - win.on("show", () => { - // Checks what to show in the tray icon menu - if (minimize) updateTray(); - }); - - win.on("blur", () => { - // Checks what to show in the tray icon menu - if (minimize) updateTray(); - - // Unregisters Alt+F4 shortcut - globalShortcut.unregister("Alt+F4"); - }); - - win.on("focus", () => { - // Checks what to show in the tray icon menu - if (minimize) updateTray(); - - // Registers shortcut for closing(quitting) the app - globalShortcut.register("Alt+F4", () => safeQuit()); - - win.webContents.send("window-is-focused", null); - }); - - // Menu bar - win.setAutoHideMenuBar(true); - win.setMenuBarVisibility(isDevelopment); - setMenu(); -} - -function createTray() { - // Minimize to tray logic follows: - // Set the tray icon - let iconPath; - if (process.platform === "darwin") { - // Using @2x for mac retina screens so the icon isn't blurry - // file name needs to include "Template" at the end for dark menu bar - iconPath = path.join(__static, "/img/fav/macTemplate@2x.png"); - } else { - iconPath = path.join(__static, "/img/fav/32x32.png"); - } - - tray = new Tray(iconPath); - tray.setToolTip("LBRY App"); - tray.setTitle("LBRY"); - tray.on("double-click", () => { - win.show(); - }); -} - -// This needs to be done as for linux the context menu doesn't update automatically(docs) -function updateTray() { - const contextMenu = Menu.buildFromTemplate(getMenuTemplate()); - if (tray) { - tray.setContextMenu(contextMenu); - } else { - console.log("How did update tray get called without a tray?"); - } -} - -function getMenuTemplate() { - return [ - getToggleItem(), - { - label: "Quit", - click: () => safeQuit(), - }, - ]; - - function getToggleItem() { - if (win.isVisible() && win.isFocused()) { - return { - label: "Hide LBRY App", - click: () => win.hide(), - }; - } - return { - label: "Show LBRY App", - click: () => win.show(), - }; - } -} - -function handleOpenUriRequested(uri) { - if (!win) { - // Window not created yet, so store up requested URI for when it is - openUri = processRequestedUri(uri); - } else { - if (win.isMinimized()) { - win.restore(); - } else if (!win.isVisible()) { - win.show(); - } - - win.focus(); - win.webContents.send("open-uri-requested", processRequestedUri(uri)); - } -} - -function handleDaemonSubprocessExited() { - console.log("The daemon has exited."); - daemonSubprocess = null; - if (!daemonStopRequested) { - // We didn't request to stop the daemon, so display a - // warning and schedule a quit. - // - // TODO: maybe it would be better to restart the daemon? - if (win) { - console.log("Did not request daemon stop, so quitting in 5 seconds."); - win.loadURL(`file://${__static}/warning.html`); - setTimeout(quitNow, 5000); - } else { - console.log("Did not request daemon stop, so quitting."); - quitNow(); - } - } -} - -function launchDaemon() { - assert(!daemonSubprocess, "Tried to launch daemon twice"); - - console.log("Launching daemon:", DAEMON_PATH); - daemonSubprocess = child_process.spawn(DAEMON_PATH); - // Need to handle the data event instead of attaching to - // process.stdout because the latter doesn't work. I believe on - // windows it buffers stdout and we don't get any meaningful output - daemonSubprocess.stdout.on("data", buf => { - console.log(String(buf).trim()); - }); - daemonSubprocess.stderr.on("data", buf => { - console.log(String(buf).trim()); - }); - daemonSubprocess.on("exit", handleDaemonSubprocessExited); -} - /* * Quits by first killing the daemon, the calling quitting for real. */ @@ -334,6 +104,155 @@ export function safeQuit() { app.quit(); } +function getMenuTemplate() { + function getToggleItem() { + if (rendererWindow.isVisible() && rendererWindow.isFocused()) { + return { + label: 'Hide LBRY App', + click: () => rendererWindow.hide(), + }; + } + return { + label: 'Show LBRY App', + click: () => rendererWindow.show(), + }; + } + + return [ + getToggleItem(), + { + label: 'Quit', + click: () => safeQuit(), + }, + ]; +} + +// This needs to be done as for linux the context menu doesn't update automatically(docs) +function updateTray() { + const trayContextMenu = Menu.buildFromTemplate(getMenuTemplate()); + if (tray) { + tray.setContextMenu(trayContextMenu); + } else { + console.log('How did update tray get called without a tray?'); + } +} + +function createWindow() { + // Disable renderer process's webSecurity on development to enable CORS. + let windowConfiguration = { + backgroundColor: '#155B4A', + minWidth: 800, + minHeight: 600, + autoHideMenuBar: true, + }; + + windowConfiguration = isDevelopment + ? { + ...windowConfiguration, + webPreferences: { + webSecurity: false, + }, + } + : windowConfiguration; + + let window = new BrowserWindow(windowConfiguration); + + window.webContents.session.setUserAgent(`LBRY/${localVersion}`); + + window.maximize(); + if (isDevelopment) { + window.webContents.openDevTools(); + } + window.loadURL(rendererUrl); + if (openUri) { + // We stored and received a URI that an external app requested before we had a window object + window.webContents.on('did-finish-load', () => { + window.webContents.send('open-uri-requested', openUri); + }); + } + + window.removeAllListeners(); + + window.on('close', event => { + if (minimize) { + event.preventDefault(); + window.hide(); + } + }); + + window.on('closed', () => { + window = null; + }); + + window.on('hide', () => { + // Checks what to show in the tray icon menu + if (minimize) updateTray(); + }); + + window.on('show', () => { + // Checks what to show in the tray icon menu + if (minimize) updateTray(); + }); + + window.on('blur', () => { + // Checks what to show in the tray icon menu + if (minimize) updateTray(); + + // Unregisters Alt+F4 shortcut + globalShortcut.unregister('Alt+F4'); + }); + + window.on('focus', () => { + // Checks what to show in the tray icon menu + if (minimize) updateTray(); + + // Registers shortcut for closing(quitting) the app + globalShortcut.register('Alt+F4', () => safeQuit()); + + window.webContents.send('window-is-focused', null); + }); + + mainMenu(); + + return window; +} + +function createTray() { + // Minimize to tray logic follows: + // Set the tray icon + let iconPath; + if (process.platform === 'darwin') { + // Using @2x for mac retina screens so the icon isn't blurry + // file name needs to include "Template" at the end for dark menu bar + iconPath = Path.join(__static, '/img/fav/macTemplate@2x.png'); + } else { + iconPath = Path.join(__static, '/img/fav/32x32.png'); + } + + tray = new Tray(iconPath); + tray.setToolTip('LBRY App'); + tray.setTitle('LBRY'); + tray.on('double-click', () => { + rendererWindow.show(); + }); +} + +function handleOpenUriRequested(uri) { + if (!rendererWindow) { + // Window not created yet, so store up requested URI for when it is + openUri = processRequestedUri(uri); + } else { + if (rendererWindow.isMinimized()) { + rendererWindow.restore(); + } else if (!rendererWindow.isVisible()) { + rendererWindow.show(); + } + + rendererWindow.focus(); + rendererWindow.webContents.send('open-uri-requested', processRequestedUri(uri)); + } +} + /* * Quits without any preparation. When a quit is requested (either through the * interface or through app.quit()), we abort the quit, try to shut down the daemon, @@ -344,16 +263,52 @@ function quitNow() { safeQuit(); } +function handleDaemonSubprocessExited() { + console.log('The daemon has exited.'); + daemonSubprocess = null; + if (!daemonStopRequested) { + // We didn't request to stop the daemon, so display a + // warning and schedule a quit. + // + // TODO: maybe it would be better to restart the daemon? + if (rendererWindow) { + console.log('Did not request daemon stop, so quitting in 5 seconds.'); + rendererWindow.loadURL(`file://${__static}/warning.html`); + setTimeout(quitNow, 5000); + } else { + console.log('Did not request daemon stop, so quitting.'); + quitNow(); + } + } +} + +function launchDaemon() { + Assert(!daemonSubprocess, 'Tried to launch daemon twice'); + + console.log('Launching daemon:', DAEMON_PATH); + daemonSubprocess = ChildProcess.spawn(DAEMON_PATH); + // Need to handle the data event instead of attaching to + // process.stdout because the latter doesn't work. I believe on + // windows it buffers stdout and we don't get any meaningful output + daemonSubprocess.stdout.on('data', buf => { + console.log(String(buf).trim()); + }); + daemonSubprocess.stderr.on('data', buf => { + console.log(String(buf).trim()); + }); + daemonSubprocess.on('exit', handleDaemonSubprocessExited); +} + const isSecondaryInstance = app.makeSingleInstance(argv => { if (argv.length >= 2) { handleOpenUriRequested(argv[1]); // This will handle restoring and focusing the window - } else if (win) { - if (win.isMinimized()) { - win.restore(); - } else if (!win.isVisible()) { - win.show(); + } else if (rendererWindow) { + if (rendererWindow.isMinimized()) { + rendererWindow.restore(); + } else if (!rendererWindow.isVisible()) { + rendererWindow.show(); } - win.focus(); + rendererWindow.focus(); } }); @@ -365,126 +320,44 @@ if (isSecondaryInstance) { function launchDaemonIfNotRunning() { // Check if the daemon is already running. If we get // an error its because its not running - console.log("Checking for lbrynet daemon"); - client.request("status", [], (err, res) => { + console.log('Checking for lbrynet daemon'); + client.request('status', [], err => { if (err) { - console.log("lbrynet daemon needs to be launched"); + console.log('lbrynet daemon needs to be launched'); launchDaemon(); } else { - console.log("lbrynet daemon is already running"); + console.log('lbrynet daemon is already running'); } }); } -/* - * Last resort for killing unresponsive daemon instances. - * Looks for any processes called "lbrynet-daemon" and - * tries to force kill them. - */ -function forceKillAllDaemonsAndQuit() { - console.log( - "Attempting to force kill any running lbrynet-daemon instances..." - ); - - const daemonPids = getPidsForProcessName("lbrynet-daemon"); - if (!daemonPids) { - console.log("No lbrynet-daemon found running."); - quitNow(); - } else { - console.log( - `Found ${ - daemonPids.length - } running daemon instances. Attempting to force kill...` - ); - - for (const pid of daemonPids) { - let daemonKillAttemptsComplete = 0; - kill(pid, "SIGKILL", err => { - daemonKillAttemptsComplete++; - if (err) { - console.log( - `Failed to force kill daemon task with pid ${pid}. Error message: ${ - err.message - }` - ); - } else { - console.log(`Force killed daemon task with pid ${pid}.`); - } - if (daemonKillAttemptsComplete >= daemonPids.length - 1) { - quitNow(); - } - }); +// Taken from webtorrent-desktop +function checkLinuxTraySupport(cb) { + // Check that we're on Ubuntu (or another debian system) and that we have + // libappindicator1. + ChildProcess.exec('dpkg --get-selections libappindicator1', (err, stdout) => { + if (err) return cb(err); + // Unfortunately there's no cleaner way, as far as I can tell, to check + // whether a debian package is installed: + if (stdout.endsWith('\tinstall\n')) { + return cb(null); } - } -} - -app.setAsDefaultProtocolClient("lbry"); - -app.on("ready", () => { - launchDaemonIfNotRunning(); - if (process.platform === "linux") { - checkLinuxTraySupport(err => { - if (!err) createTray(); - else minimize = false; - }); - } else { - createTray(); - } - createWindow(); -}); - -// Quit when all windows are closed. -app.on("window-all-closed", () => { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== "darwin") { - app.quit(); - } -}); - -app.on("before-quit", event => { - if (!readyToQuit) { - // We need to shutdown the daemon before we're ready to actually quit. This - // event will be triggered re-entrantly once preparation is done. - event.preventDefault(); - shutdownDaemonAndQuit(); - } else { - console.log("Quitting."); - } -}); - -app.on("activate", () => { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (win === null) { - createWindow(); - } -}); - -if (process.platform === "darwin") { - app.on("open-url", (event, uri) => { - handleOpenUriRequested(uri); + return cb(new Error('debian package not installed')); }); -} else if (process.argv.length >= 2) { - handleOpenUriRequested(process.argv[1]); } // When a quit is attempted, this is called. It attempts to shutdown the daemon, // then calls quitNow() to quit for real. function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { function doShutdown() { - console.log("Shutting down daemon"); + console.log('Shutting down daemon'); daemonStopRequested = true; - client.request("daemon_stop", [], (err, res) => { + client.request('daemon_stop', [], err => { if (err) { - console.log( - `received error when stopping lbrynet-daemon. Error message: ${ - err.message - }\n` - ); - console.log("You will need to manually kill the daemon."); + console.log(`received error when stopping lbrynet-daemon. Error message: ${err.message}\n`); + console.log('You will need to manually kill the daemon.'); } else { - console.log("Successfully stopped daemon via RPC call."); + console.log('Successfully stopped daemon via RPC call.'); quitNow(); } }); @@ -493,7 +366,7 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { if (daemonSubprocess) { doShutdown(); } else if (!evenIfNotStartedByApp) { - console.log("Not killing lbrynet-daemon because app did not start it"); + console.log('Not killing lbrynet-daemon because app did not start it'); quitNow(); } else { doShutdown(); @@ -503,111 +376,154 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { // If not, we should wait until the daemon is closed before we start the install. } -// Taken from webtorrent-desktop -function checkLinuxTraySupport(cb) { - // Check that we're on Ubuntu (or another debian system) and that we have - // libappindicator1. - child_process.exec( - "dpkg --get-selections libappindicator1", - (err, stdout) => { - if (err) return cb(err); - // Unfortunately there's no cleaner way, as far as I can tell, to check - // whether a debian package is installed: - if (stdout.endsWith("\tinstall\n")) { - cb(null); - } else { - cb(new Error("debian package not installed")); - } - } - ); +if (isDevelopment) { + import('devtron') + .then(({ install }) => { + install(); + console.log('Added Extension: Devtron'); + }) + .catch(error => { + console.error(error); + }); + import('electron-devtools-installer') + .then(({ default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS }) => { + app.on('ready', () => { + [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => { + installExtension(extension) + .then(name => console.log(`Added Extension: ${name}`)) + .catch(err => console.log('An error occurred: ', err)); + }); + }); + }) + .catch(error => { + console.error(error); + }); } -ipcMain.on("upgrade", (event, installerPath) => { - app.on("quit", () => { - console.log("Launching upgrade installer at", installerPath); +app.setAsDefaultProtocolClient('lbry'); + +app.on('ready', () => { + launchDaemonIfNotRunning(); + if (process.platform === 'linux') { + checkLinuxTraySupport(err => { + if (!err) createTray(); + else minimize = false; + }); + } else { + createTray(); + } + rendererWindow = createWindow(); +}); + +// Quit when all windows are closed. +app.on('window-all-closed', () => { + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +app.on('before-quit', event => { + if (!readyToQuit) { + // We need to shutdown the daemon before we're ready to actually quit. This + // event will be triggered re-entrantly once preparation is done. + event.preventDefault(); + shutdownDaemonAndQuit(); + } else { + console.log('Quitting.'); + } +}); + +app.on('activate', () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (rendererWindow === null) { + createWindow(); + } +}); + +if (process.platform === 'darwin') { + app.on('open-url', (event, uri) => { + handleOpenUriRequested(uri); + }); +} else if (process.argv.length >= 2) { + handleOpenUriRequested(process.argv[1]); +} + +ipcMain.on('upgrade', (event, installerPath) => { + app.on('quit', () => { + console.log('Launching upgrade installer at', installerPath); // This gets triggered called after *all* other quit-related events, so // we'll only get here if we're fully prepared and quitting for real. openItem(installerPath); }); - if (win) { - win.loadURL(`file://${__static}/upgrade.html`); + if (rendererWindow) { + rendererWindow.loadURL(`file://${__static}/upgrade.html`); } shutdownDaemonAndQuit(true); // wait for daemon to shut down before upgrading // what to do if no shutdown in a long time? - console.log("Update downloaded to", installerPath); + console.log('Update downloaded to', installerPath); console.log( - "The app will close, and you will be prompted to install the latest version of LBRY." + 'The app will close, and you will be prompted to install the latest version of LBRY.' ); - console.log("After the install is complete, please reopen the app."); + console.log('After the install is complete, please reopen the app.'); }); -ipcMain.on("version-info-requested", () => { +ipcMain.on('version-info-requested', () => { function formatRc(ver) { // Adds dash if needed to make RC suffix semver friendly - return ver.replace(/([^-])rc/, "$1-rc"); + return ver.replace(/([^-])rc/, '$1-rc'); } - let result = ""; + let result = ''; const opts = { headers: { - "User-Agent": `LBRY/${localVersion}`, + 'User-Agent': `LBRY/${localVersion}`, }, }; - const req = https.get( - Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)), - res => { - res.on("data", data => { - result += data; - }); - res.on("end", () => { - const tagName = JSON.parse(result).tag_name; - const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); - if (!remoteVersion) { - if (win) { - win.webContents.send("version-info-received", null); - } - } else { - const upgradeAvailable = semver.gt( - formatRc(remoteVersion), - formatRc(localVersion) - ); - if (win) { - win.webContents.send("version-info-received", { - remoteVersion, - localVersion, - upgradeAvailable, - }); - } + const req = Https.get(Object.assign(opts, Url.parse(LATEST_RELEASE_API_URL)), res => { + res.on('data', data => { + result += data; + }); + res.on('end', () => { + const tagName = JSON.parse(result).tag_name; + const [, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); + if (!remoteVersion) { + if (rendererWindow) { + rendererWindow.webContents.send('version-info-received', null); } - }); - } - ); + } else { + const upgradeAvailable = Semver.gt(formatRc(remoteVersion), formatRc(localVersion)); + if (rendererWindow) { + rendererWindow.webContents.send('version-info-received', { + remoteVersion, + localVersion, + upgradeAvailable, + }); + } + } + }); + }); - req.on("error", err => { - console.log("Failed to get current version from GitHub. Error:", err); - if (win) { - win.webContents.send("version-info-received", null); + req.on('error', err => { + console.log('Failed to get current version from GitHub. Error:', err); + if (rendererWindow) { + rendererWindow.webContents.send('version-info-received', null); } }); }); -ipcMain.on("get-auth-token", event => { - keytar.getPassword("LBRY", "auth_token").then(token => { - event.sender.send( - "auth-token-response", - token ? token.toString().trim() : null - ); +ipcMain.on('get-auth-token', event => { + Keytar.getPassword('LBRY', 'auth_token').then(token => { + event.sender.send('auth-token-response', token ? token.toString().trim() : null); }); }); -ipcMain.on("set-auth-token", (event, token) => { - keytar.setPassword( - "LBRY", - "auth_token", - token ? token.toString().trim() : null - ); +ipcMain.on('set-auth-token', (event, token) => { + Keytar.setPassword('LBRY', 'auth_token', token ? token.toString().trim() : null); }); diff --git a/src/main/menu/context-menu.js b/src/main/menu/context-menu.js deleted file mode 100644 index 26ed0f7de..000000000 --- a/src/main/menu/context-menu.js +++ /dev/null @@ -1,35 +0,0 @@ -const { Menu } = require("electron"); -const electron = require("electron"); - -const app = electron.app; - -const contextMenuTemplate = [ - { - role: "cut", - }, - { - role: "copy", - }, - { - role: "paste", - }, -]; - -module.exports = { - showContextMenu(win, posX, posY, showDevItems) { - const template = contextMenuTemplate.slice(); - if (showDevItems) { - template.push({ - type: "separator", - }); - template.push({ - label: "Inspect Element", - click() { - win.inspectElement(posX, posY); - }, - }); - } - - Menu.buildFromTemplate(template).popup(win); - }, -}; diff --git a/src/main/menu/contextMenu.js b/src/main/menu/contextMenu.js new file mode 100644 index 000000000..ad33c6bc2 --- /dev/null +++ b/src/main/menu/contextMenu.js @@ -0,0 +1,30 @@ +import { Menu } from 'electron'; + +const contextMenuTemplate = [ + { + role: 'cut', + }, + { + role: 'copy', + }, + { + role: 'paste', + }, +]; + +export default function contextMenu(win, posX, posY, showDevItems) { + const template = contextMenuTemplate.slice(); + if (showDevItems) { + template.push({ + type: 'separator', + }); + template.push({ + label: 'Inspect Element', + click() { + win.inspectElement(posX, posY); + }, + }); + } + + Menu.buildFromTemplate(template).popup(win); +} diff --git a/src/main/menu/main-menu.js b/src/main/menu/main-menu.js deleted file mode 100644 index c26bfd118..000000000 --- a/src/main/menu/main-menu.js +++ /dev/null @@ -1,136 +0,0 @@ -const { app, shell, Menu } = require("electron"); -const { safeQuit } = require("../index.js"); - -const baseTemplate = [ - { - label: "File", - submenu: [ - { - label: "Quit", - accelerator: "CommandOrControl+Q", - click: () => safeQuit(), - }, - ], - }, - { - label: "Edit", - submenu: [ - { - role: "undo", - }, - { - role: "redo", - }, - { - type: "separator", - }, - { - role: "cut", - }, - { - role: "copy", - }, - { - role: "paste", - }, - { - role: "selectall", - }, - ], - }, - { - label: "View", - submenu: [ - { - role: "reload", - }, - { - label: "Developer", - submenu: [ - { - role: "forcereload", - }, - { - role: "toggledevtools", - }, - ], - }, - { - type: "separator", - }, - { - role: "togglefullscreen", - }, - ], - }, - { - role: "help", - submenu: [ - { - label: "Learn More", - click(item, focusedWindow) { - if (focusedWindow) { - focusedWindow.webContents.send("open-menu", "/help"); - } - }, - }, - { - label: "Frequently Asked Questions", - click(item, focusedWindow) { - shell.openExternal("https://lbry.io/faq"); - }, - }, - { - type: "separator", - }, - { - label: "Report Issue", - click(item, focusedWindow) { - shell.openExternal("https://lbry.io/faq/contributing#report-a-bug"); - }, - }, - { - type: "separator", - }, - { - label: "Developer API Guide", - click(item, focusedWindow) { - shell.openExternal("https://lbry.io/quickstart"); - }, - }, - ], - }, -]; - -const macOSAppMenuTemplate = { - label: app.getName(), - submenu: [ - { - role: "about", - }, - { - type: "separator", - }, - { - role: "hide", - }, - { - role: "hideothers", - }, - { - role: "unhide", - }, - { - type: "separator", - }, - { - role: "quit", - }, - ], -}; - -module.exports = () => { - const template = baseTemplate.slice(); - process.platform === "darwin" && template.unshift(macOSAppMenuTemplate); - Menu.setApplicationMenu(Menu.buildFromTemplate(template)); -}; diff --git a/src/main/menu/mainMenu.js b/src/main/menu/mainMenu.js new file mode 100644 index 000000000..879ce8206 --- /dev/null +++ b/src/main/menu/mainMenu.js @@ -0,0 +1,138 @@ +import { app, Menu, shell } from 'electron'; +import { safeQuit } from '../index'; + +const baseTemplate = [ + { + label: 'File', + submenu: [ + { + label: 'Quit', + accelerator: 'CommandOrControl+Q', + click: () => safeQuit(), + }, + ], + }, + { + label: 'Edit', + submenu: [ + { + role: 'undo', + }, + { + role: 'redo', + }, + { + type: 'separator', + }, + { + role: 'cut', + }, + { + role: 'copy', + }, + { + role: 'paste', + }, + { + role: 'selectall', + }, + ], + }, + { + label: 'View', + submenu: [ + { + role: 'reload', + }, + { + label: 'Developer', + submenu: [ + { + role: 'forcereload', + }, + { + role: 'toggledevtools', + }, + ], + }, + { + type: 'separator', + }, + { + role: 'togglefullscreen', + }, + ], + }, + { + role: 'help', + submenu: [ + { + label: 'Learn More', + click(item, focusedWindow) { + if (focusedWindow) { + focusedWindow.webContents.send('open-menu', '/help'); + } + }, + }, + { + label: 'Frequently Asked Questions', + click() { + shell.openExternal('https://lbry.io/faq'); + }, + }, + { + type: 'separator', + }, + { + label: 'Report Issue', + click() { + shell.openExternal('https://lbry.io/faq/contributing#report-a-bug'); + }, + }, + { + type: 'separator', + }, + { + label: 'Developer API Guide', + click() { + shell.openExternal('https://lbry.io/quickstart'); + }, + }, + ], + }, +]; + +const macOSAppMenuTemplate = { + label: app.getName(), + submenu: [ + { + role: 'about', + }, + { + type: 'separator', + }, + { + role: 'hide', + }, + { + role: 'hideothers', + }, + { + role: 'unhide', + }, + { + type: 'separator', + }, + { + role: 'quit', + }, + ], +}; + +export default () => { + const template = baseTemplate.slice(); + if (process.platform === 'darwin') { + template.unshift(macOSAppMenuTemplate); + } + Menu.setApplicationMenu(Menu.buildFromTemplate(template)); +}; diff --git a/src/renderer/app.js b/src/renderer/app.js index ef3f24ce9..1e979db9e 100644 --- a/src/renderer/app.js +++ b/src/renderer/app.js @@ -1,17 +1,16 @@ -import store from "store"; -import { remote } from "electron"; -import path from "path"; +import store from 'store'; +import { remote } from 'electron'; +import path from 'path'; +import y18n from 'y18n'; -const env = process.env.NODE_ENV || "production"; +const env = process.env.NODE_ENV || 'production'; const config = { - ...require(`./config/${env}`), + ...import(`./config/${env}`), }; -const i18n = require("y18n")({ - directory: path - .join(remote.app.getAppPath(), "/../static/locales") - .replace(/\\/g, "\\\\"), +const i18n = y18n({ + directory: path.join(remote.app.getAppPath(), '/../static/locales').replace(/\\/g, '\\\\'), updateFiles: false, - locale: "en", + locale: 'en', }); const logs = []; @@ -26,8 +25,17 @@ const app = { }, }; -window.__ = i18n.__; -window.__n = i18n.__n; +// Workaround for https://github.com/electron-userland/electron-webpack/issues/52 +if (env !== 'development') { + window.staticResourcesPath = path + .join(remote.app.getAppPath(), '../static') + .replace(/\\/g, '\\\\'); +} else { + window.staticResourcesPath = ''; +} -global.app = app; -module.exports = app; +// eslint-disable-next-line no-underscore-dangle +window.__ = i18n.__; +// eslint-disable-next-line no-underscore-dangle +window.__n = i18n.__n; +window.app = app; diff --git a/src/renderer/constants/action_types.js b/src/renderer/constants/action_types.js index 594aa716a..1159d256b 100644 --- a/src/renderer/constants/action_types.js +++ b/src/renderer/constants/action_types.js @@ -1,166 +1,156 @@ -export const OPEN_MODAL = "OPEN_MODAL"; -export const CLOSE_MODAL = "CLOSE_MODAL"; -export const SHOW_SNACKBAR = "SHOW_SNACKBAR"; -export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK"; -export const WINDOW_FOCUSED = "WINDOW_FOCUSED"; -export const DAEMON_READY = "DAEMON_READY"; -export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH"; -export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH"; -export const VOLUME_CHANGED = "VOLUME_CHANGED"; +export const OPEN_MODAL = 'OPEN_MODAL'; +export const CLOSE_MODAL = 'CLOSE_MODAL'; +export const SHOW_SNACKBAR = 'SHOW_SNACKBAR'; +export const REMOVE_SNACKBAR_SNACK = 'REMOVE_SNACKBAR_SNACK'; +export const WINDOW_FOCUSED = 'WINDOW_FOCUSED'; +export const DAEMON_READY = 'DAEMON_READY'; +export const DAEMON_VERSION_MATCH = 'DAEMON_VERSION_MATCH'; +export const DAEMON_VERSION_MISMATCH = 'DAEMON_VERSION_MISMATCH'; +export const VOLUME_CHANGED = 'VOLUME_CHANGED'; // Navigation -export const CHANGE_AFTER_AUTH_PATH = "CHANGE_AFTER_AUTH_PATH"; -export const WINDOW_SCROLLED = "WINDOW_SCROLLED"; -export const HISTORY_NAVIGATE = "HISTORY_NAVIGATE"; +export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH'; +export const WINDOW_SCROLLED = 'WINDOW_SCROLLED'; +export const HISTORY_NAVIGATE = 'HISTORY_NAVIGATE'; // Upgrades -export const UPGRADE_CANCELLED = "UPGRADE_CANCELLED"; -export const DOWNLOAD_UPGRADE = "DOWNLOAD_UPGRADE"; -export const UPGRADE_DOWNLOAD_STARTED = "UPGRADE_DOWNLOAD_STARTED"; -export const UPGRADE_DOWNLOAD_COMPLETED = "UPGRADE_DOWNLOAD_COMPLETED"; -export const UPGRADE_DOWNLOAD_PROGRESSED = "UPGRADE_DOWNLOAD_PROGRESSED"; -export const CHECK_UPGRADE_AVAILABLE = "CHECK_UPGRADE_AVAILABLE"; -export const CHECK_UPGRADE_START = "CHECK_UPGRADE_START"; -export const CHECK_UPGRADE_SUCCESS = "CHECK_UPGRADE_SUCCESS"; -export const CHECK_UPGRADE_FAIL = "CHECK_UPGRADE_FAIL"; -export const CHECK_UPGRADE_SUBSCRIBE = "CHECK_UPGRADE_SUBSCRIBE"; -export const UPDATE_VERSION = "UPDATE_VERSION"; -export const UPDATE_REMOTE_VERSION = "UPDATE_REMOTE_VERSION"; -export const SKIP_UPGRADE = "SKIP_UPGRADE"; -export const START_UPGRADE = "START_UPGRADE"; +export const UPGRADE_CANCELLED = 'UPGRADE_CANCELLED'; +export const DOWNLOAD_UPGRADE = 'DOWNLOAD_UPGRADE'; +export const UPGRADE_DOWNLOAD_STARTED = 'UPGRADE_DOWNLOAD_STARTED'; +export const UPGRADE_DOWNLOAD_COMPLETED = 'UPGRADE_DOWNLOAD_COMPLETED'; +export const UPGRADE_DOWNLOAD_PROGRESSED = 'UPGRADE_DOWNLOAD_PROGRESSED'; +export const CHECK_UPGRADE_AVAILABLE = 'CHECK_UPGRADE_AVAILABLE'; +export const CHECK_UPGRADE_START = 'CHECK_UPGRADE_START'; +export const CHECK_UPGRADE_SUCCESS = 'CHECK_UPGRADE_SUCCESS'; +export const CHECK_UPGRADE_FAIL = 'CHECK_UPGRADE_FAIL'; +export const CHECK_UPGRADE_SUBSCRIBE = 'CHECK_UPGRADE_SUBSCRIBE'; +export const UPDATE_VERSION = 'UPDATE_VERSION'; +export const UPDATE_REMOTE_VERSION = 'UPDATE_REMOTE_VERSION'; +export const SKIP_UPGRADE = 'SKIP_UPGRADE'; +export const START_UPGRADE = 'START_UPGRADE'; // Wallet -export const GET_NEW_ADDRESS_STARTED = "GET_NEW_ADDRESS_STARTED"; -export const GET_NEW_ADDRESS_COMPLETED = "GET_NEW_ADDRESS_COMPLETED"; -export const FETCH_TRANSACTIONS_STARTED = "FETCH_TRANSACTIONS_STARTED"; -export const FETCH_TRANSACTIONS_COMPLETED = "FETCH_TRANSACTIONS_COMPLETED"; -export const UPDATE_BALANCE = "UPDATE_BALANCE"; -export const CHECK_ADDRESS_IS_MINE_STARTED = "CHECK_ADDRESS_IS_MINE_STARTED"; -export const CHECK_ADDRESS_IS_MINE_COMPLETED = - "CHECK_ADDRESS_IS_MINE_COMPLETED"; -export const SET_DRAFT_TRANSACTION_AMOUNT = "SET_DRAFT_TRANSACTION_AMOUNT"; -export const SET_DRAFT_TRANSACTION_ADDRESS = "SET_DRAFT_TRANSACTION_ADDRESS"; -export const SEND_TRANSACTION_STARTED = "SEND_TRANSACTION_STARTED"; -export const SEND_TRANSACTION_COMPLETED = "SEND_TRANSACTION_COMPLETED"; -export const SEND_TRANSACTION_FAILED = "SEND_TRANSACTION_FAILED"; -export const FETCH_BLOCK_SUCCESS = "FETCH_BLOCK_SUCCESS"; -export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; -export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; -export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; +export const GET_NEW_ADDRESS_STARTED = 'GET_NEW_ADDRESS_STARTED'; +export const GET_NEW_ADDRESS_COMPLETED = 'GET_NEW_ADDRESS_COMPLETED'; +export const FETCH_TRANSACTIONS_STARTED = 'FETCH_TRANSACTIONS_STARTED'; +export const FETCH_TRANSACTIONS_COMPLETED = 'FETCH_TRANSACTIONS_COMPLETED'; +export const UPDATE_BALANCE = 'UPDATE_BALANCE'; +export const CHECK_ADDRESS_IS_MINE_STARTED = 'CHECK_ADDRESS_IS_MINE_STARTED'; +export const CHECK_ADDRESS_IS_MINE_COMPLETED = 'CHECK_ADDRESS_IS_MINE_COMPLETED'; +export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT'; +export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS'; +export const SEND_TRANSACTION_STARTED = 'SEND_TRANSACTION_STARTED'; +export const SEND_TRANSACTION_COMPLETED = 'SEND_TRANSACTION_COMPLETED'; +export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED'; +export const FETCH_BLOCK_SUCCESS = 'FETCH_BLOCK_SUCCESS'; +export const SUPPORT_TRANSACTION_STARTED = 'SUPPORT_TRANSACTION_STARTED'; +export const SUPPORT_TRANSACTION_COMPLETED = 'SUPPORT_TRANSACTION_COMPLETED'; +export const SUPPORT_TRANSACTION_FAILED = 'SUPPORT_TRANSACTION_FAILED'; // Claims -export const FETCH_FEATURED_CONTENT_STARTED = "FETCH_FEATURED_CONTENT_STARTED"; -export const FETCH_FEATURED_CONTENT_COMPLETED = - "FETCH_FEATURED_CONTENT_COMPLETED"; -export const RESOLVE_URIS_STARTED = "RESOLVE_URIS_STARTED"; -export const RESOLVE_URIS_COMPLETED = "RESOLVE_URIS_COMPLETED"; -export const FETCH_CHANNEL_CLAIMS_STARTED = "FETCH_CHANNEL_CLAIMS_STARTED"; -export const FETCH_CHANNEL_CLAIMS_COMPLETED = "FETCH_CHANNEL_CLAIMS_COMPLETED"; -export const FETCH_CHANNEL_CLAIM_COUNT_STARTED = - "FETCH_CHANNEL_CLAIM_COUNT_STARTED"; -export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED = - "FETCH_CHANNEL_CLAIM_COUNT_COMPLETED"; -export const FETCH_CLAIM_LIST_MINE_STARTED = "FETCH_CLAIM_LIST_MINE_STARTED"; -export const FETCH_CLAIM_LIST_MINE_COMPLETED = - "FETCH_CLAIM_LIST_MINE_COMPLETED"; -export const ABANDON_CLAIM_STARTED = "ABANDON_CLAIM_STARTED"; -export const ABANDON_CLAIM_SUCCEEDED = "ABANDON_CLAIM_SUCCEEDED"; -export const FETCH_CHANNEL_LIST_MINE_STARTED = - "FETCH_CHANNEL_LIST_MINE_STARTED"; -export const FETCH_CHANNEL_LIST_MINE_COMPLETED = - "FETCH_CHANNEL_LIST_MINE_COMPLETED"; -export const CREATE_CHANNEL_STARTED = "CREATE_CHANNEL_STARTED"; -export const CREATE_CHANNEL_COMPLETED = "CREATE_CHANNEL_COMPLETED"; -export const PUBLISH_STARTED = "PUBLISH_STARTED"; -export const PUBLISH_COMPLETED = "PUBLISH_COMPLETED"; -export const PUBLISH_FAILED = "PUBLISH_FAILED"; -export const SET_PLAYING_URI = "PLAY_URI"; +export const FETCH_FEATURED_CONTENT_STARTED = 'FETCH_FEATURED_CONTENT_STARTED'; +export const FETCH_FEATURED_CONTENT_COMPLETED = 'FETCH_FEATURED_CONTENT_COMPLETED'; +export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED'; +export const RESOLVE_URIS_COMPLETED = 'RESOLVE_URIS_COMPLETED'; +export const FETCH_CHANNEL_CLAIMS_STARTED = 'FETCH_CHANNEL_CLAIMS_STARTED'; +export const FETCH_CHANNEL_CLAIMS_COMPLETED = 'FETCH_CHANNEL_CLAIMS_COMPLETED'; +export const FETCH_CHANNEL_CLAIM_COUNT_STARTED = 'FETCH_CHANNEL_CLAIM_COUNT_STARTED'; +export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED = 'FETCH_CHANNEL_CLAIM_COUNT_COMPLETED'; +export const FETCH_CLAIM_LIST_MINE_STARTED = 'FETCH_CLAIM_LIST_MINE_STARTED'; +export const FETCH_CLAIM_LIST_MINE_COMPLETED = 'FETCH_CLAIM_LIST_MINE_COMPLETED'; +export const ABANDON_CLAIM_STARTED = 'ABANDON_CLAIM_STARTED'; +export const ABANDON_CLAIM_SUCCEEDED = 'ABANDON_CLAIM_SUCCEEDED'; +export const FETCH_CHANNEL_LIST_MINE_STARTED = 'FETCH_CHANNEL_LIST_MINE_STARTED'; +export const FETCH_CHANNEL_LIST_MINE_COMPLETED = 'FETCH_CHANNEL_LIST_MINE_COMPLETED'; +export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED'; +export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED'; +export const PUBLISH_STARTED = 'PUBLISH_STARTED'; +export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED'; +export const PUBLISH_FAILED = 'PUBLISH_FAILED'; +export const SET_PLAYING_URI = 'PLAY_URI'; // Files -export const FILE_LIST_STARTED = "FILE_LIST_STARTED"; -export const FILE_LIST_SUCCEEDED = "FILE_LIST_SUCCEEDED"; -export const FETCH_FILE_INFO_STARTED = "FETCH_FILE_INFO_STARTED"; -export const FETCH_FILE_INFO_COMPLETED = "FETCH_FILE_INFO_COMPLETED"; -export const FETCH_COST_INFO_STARTED = "FETCH_COST_INFO_STARTED"; -export const FETCH_COST_INFO_COMPLETED = "FETCH_COST_INFO_COMPLETED"; -export const LOADING_VIDEO_STARTED = "LOADING_VIDEO_STARTED"; -export const LOADING_VIDEO_COMPLETED = "LOADING_VIDEO_COMPLETED"; -export const LOADING_VIDEO_FAILED = "LOADING_VIDEO_FAILED"; -export const DOWNLOADING_STARTED = "DOWNLOADING_STARTED"; -export const DOWNLOADING_PROGRESSED = "DOWNLOADING_PROGRESSED"; -export const DOWNLOADING_COMPLETED = "DOWNLOADING_COMPLETED"; -export const PLAY_VIDEO_STARTED = "PLAY_VIDEO_STARTED"; -export const FETCH_AVAILABILITY_STARTED = "FETCH_AVAILABILITY_STARTED"; -export const FETCH_AVAILABILITY_COMPLETED = "FETCH_AVAILABILITY_COMPLETED"; -export const FILE_DELETE = "FILE_DELETE"; +export const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; +export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; +export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED'; +export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED'; +export const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED'; +export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED'; +export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED'; +export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED'; +export const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED'; +export const DOWNLOADING_STARTED = 'DOWNLOADING_STARTED'; +export const DOWNLOADING_PROGRESSED = 'DOWNLOADING_PROGRESSED'; +export const DOWNLOADING_COMPLETED = 'DOWNLOADING_COMPLETED'; +export const PLAY_VIDEO_STARTED = 'PLAY_VIDEO_STARTED'; +export const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED'; +export const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED'; +export const FILE_DELETE = 'FILE_DELETE'; // Search -export const SEARCH_STARTED = "SEARCH_STARTED"; -export const SEARCH_COMPLETED = "SEARCH_COMPLETED"; -export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; +export const SEARCH_STARTED = 'SEARCH_STARTED'; +export const SEARCH_COMPLETED = 'SEARCH_COMPLETED'; +export const SEARCH_CANCELLED = 'SEARCH_CANCELLED'; // Settings -export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; -export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED"; +export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED'; +export const CLIENT_SETTING_CHANGED = 'CLIENT_SETTING_CHANGED'; // User -export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED"; -export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS"; -export const AUTHENTICATION_FAILURE = "AUTHENTICATION_FAILURE"; -export const USER_EMAIL_DECLINE = "USER_EMAIL_DECLINE"; -export const USER_EMAIL_NEW_STARTED = "USER_EMAIL_NEW_STARTED"; -export const USER_EMAIL_NEW_SUCCESS = "USER_EMAIL_NEW_SUCCESS"; -export const USER_EMAIL_NEW_EXISTS = "USER_EMAIL_NEW_EXISTS"; -export const USER_EMAIL_NEW_FAILURE = "USER_EMAIL_NEW_FAILURE"; -export const USER_EMAIL_VERIFY_STARTED = "USER_EMAIL_VERIFY_STARTED"; -export const USER_EMAIL_VERIFY_SUCCESS = "USER_EMAIL_VERIFY_SUCCESS"; -export const USER_EMAIL_VERIFY_FAILURE = "USER_EMAIL_VERIFY_FAILURE"; -export const USER_IDENTITY_VERIFY_STARTED = "USER_IDENTITY_VERIFY_STARTED"; -export const USER_IDENTITY_VERIFY_SUCCESS = "USER_IDENTITY_VERIFY_SUCCESS"; -export const USER_IDENTITY_VERIFY_FAILURE = "USER_IDENTITY_VERIFY_FAILURE"; -export const USER_FETCH_STARTED = "USER_FETCH_STARTED"; -export const USER_FETCH_SUCCESS = "USER_FETCH_SUCCESS"; -export const USER_FETCH_FAILURE = "USER_FETCH_FAILURE"; -export const USER_INVITE_STATUS_FETCH_STARTED = - "USER_INVITE_STATUS_FETCH_STARTED"; -export const USER_INVITE_STATUS_FETCH_SUCCESS = - "USER_INVITE_STATUS_FETCH_SUCCESS"; -export const USER_INVITE_STATUS_FETCH_FAILURE = - "USER_INVITE_STATUS_FETCH_FAILURE"; -export const USER_INVITE_NEW_STARTED = "USER_INVITE_NEW_STARTED"; -export const USER_INVITE_NEW_SUCCESS = "USER_INVITE_NEW_SUCCESS"; -export const USER_INVITE_NEW_FAILURE = "USER_INVITE_NEW_FAILURE"; -export const FETCH_ACCESS_TOKEN_SUCCESS = "FETCH_ACCESS_TOKEN_SUCCESS"; +export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED'; +export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS'; +export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE'; +export const USER_EMAIL_DECLINE = 'USER_EMAIL_DECLINE'; +export const USER_EMAIL_NEW_STARTED = 'USER_EMAIL_NEW_STARTED'; +export const USER_EMAIL_NEW_SUCCESS = 'USER_EMAIL_NEW_SUCCESS'; +export const USER_EMAIL_NEW_EXISTS = 'USER_EMAIL_NEW_EXISTS'; +export const USER_EMAIL_NEW_FAILURE = 'USER_EMAIL_NEW_FAILURE'; +export const USER_EMAIL_VERIFY_STARTED = 'USER_EMAIL_VERIFY_STARTED'; +export const USER_EMAIL_VERIFY_SUCCESS = 'USER_EMAIL_VERIFY_SUCCESS'; +export const USER_EMAIL_VERIFY_FAILURE = 'USER_EMAIL_VERIFY_FAILURE'; +export const USER_IDENTITY_VERIFY_STARTED = 'USER_IDENTITY_VERIFY_STARTED'; +export const USER_IDENTITY_VERIFY_SUCCESS = 'USER_IDENTITY_VERIFY_SUCCESS'; +export const USER_IDENTITY_VERIFY_FAILURE = 'USER_IDENTITY_VERIFY_FAILURE'; +export const USER_FETCH_STARTED = 'USER_FETCH_STARTED'; +export const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS'; +export const USER_FETCH_FAILURE = 'USER_FETCH_FAILURE'; +export const USER_INVITE_STATUS_FETCH_STARTED = 'USER_INVITE_STATUS_FETCH_STARTED'; +export const USER_INVITE_STATUS_FETCH_SUCCESS = 'USER_INVITE_STATUS_FETCH_SUCCESS'; +export const USER_INVITE_STATUS_FETCH_FAILURE = 'USER_INVITE_STATUS_FETCH_FAILURE'; +export const USER_INVITE_NEW_STARTED = 'USER_INVITE_NEW_STARTED'; +export const USER_INVITE_NEW_SUCCESS = 'USER_INVITE_NEW_SUCCESS'; +export const USER_INVITE_NEW_FAILURE = 'USER_INVITE_NEW_FAILURE'; +export const FETCH_ACCESS_TOKEN_SUCCESS = 'FETCH_ACCESS_TOKEN_SUCCESS'; // Rewards -export const FETCH_REWARDS_STARTED = "FETCH_REWARDS_STARTED"; -export const FETCH_REWARDS_COMPLETED = "FETCH_REWARDS_COMPLETED"; -export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED"; -export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS"; -export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; -export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; -export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; +export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED'; +export const FETCH_REWARDS_COMPLETED = 'FETCH_REWARDS_COMPLETED'; +export const CLAIM_REWARD_STARTED = 'CLAIM_REWARD_STARTED'; +export const CLAIM_REWARD_SUCCESS = 'CLAIM_REWARD_SUCCESS'; +export const CLAIM_REWARD_FAILURE = 'CLAIM_REWARD_FAILURE'; +export const CLAIM_REWARD_CLEAR_ERROR = 'CLAIM_REWARD_CLEAR_ERROR'; +export const FETCH_REWARD_CONTENT_COMPLETED = 'FETCH_REWARD_CONTENT_COMPLETED'; // Language -export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED"; -export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED"; +export const DOWNLOAD_LANGUAGE_SUCCEEDED = 'DOWNLOAD_LANGUAGE_SUCCEEDED'; +export const DOWNLOAD_LANGUAGE_FAILED = 'DOWNLOAD_LANGUAGE_FAILED'; // ShapeShift -export const GET_SUPPORTED_COINS_START = "GET_SUPPORTED_COINS_START"; -export const GET_SUPPORTED_COINS_SUCCESS = "GET_SUPPORTED_COINS_SUCCESS"; -export const GET_SUPPORTED_COINS_FAIL = "GET_SUPPORTED_COINS_FAIL"; -export const GET_COIN_STATS_START = "GET_COIN_STATS_START"; -export const GET_COIN_STATS_SUCCESS = "GET_COIN_STATS_SUCCESS"; -export const GET_COIN_STATS_FAIL = "GET_COIN_STATS_FAIL"; -export const PREPARE_SHAPE_SHIFT_START = "PREPARE_SHAPE_SHIFT_START"; -export const PREPARE_SHAPE_SHIFT_SUCCESS = "PREPARE_SHAPE_SHIFT_SUCCESS"; -export const PREPARE_SHAPE_SHIFT_FAIL = "PREPARE_SHAPE_SHIFT_FAIL"; -export const GET_ACTIVE_SHIFT_START = "GET_ACTIVE_SHIFT_START"; -export const GET_ACTIVE_SHIFT_SUCCESS = "GET_ACTIVE_SHIFT_SUCCESS"; -export const GET_ACTIVE_SHIFT_FAIL = "GET_ACTIVE_SHIFT_FAIL"; -export const CLEAR_SHAPE_SHIFT = "CLEAR_SHAPE_SHIFT"; +export const GET_SUPPORTED_COINS_START = 'GET_SUPPORTED_COINS_START'; +export const GET_SUPPORTED_COINS_SUCCESS = 'GET_SUPPORTED_COINS_SUCCESS'; +export const GET_SUPPORTED_COINS_FAIL = 'GET_SUPPORTED_COINS_FAIL'; +export const GET_COIN_STATS_START = 'GET_COIN_STATS_START'; +export const GET_COIN_STATS_SUCCESS = 'GET_COIN_STATS_SUCCESS'; +export const GET_COIN_STATS_FAIL = 'GET_COIN_STATS_FAIL'; +export const PREPARE_SHAPE_SHIFT_START = 'PREPARE_SHAPE_SHIFT_START'; +export const PREPARE_SHAPE_SHIFT_SUCCESS = 'PREPARE_SHAPE_SHIFT_SUCCESS'; +export const PREPARE_SHAPE_SHIFT_FAIL = 'PREPARE_SHAPE_SHIFT_FAIL'; +export const GET_ACTIVE_SHIFT_START = 'GET_ACTIVE_SHIFT_START'; +export const GET_ACTIVE_SHIFT_SUCCESS = 'GET_ACTIVE_SHIFT_SUCCESS'; +export const GET_ACTIVE_SHIFT_FAIL = 'GET_ACTIVE_SHIFT_FAIL'; +export const CLEAR_SHAPE_SHIFT = 'CLEAR_SHAPE_SHIFT'; // Subscriptions -export const CHANNEL_SUBSCRIBE = "CHANNEL_SUBSCRIBE"; -export const CHANNEL_UNSUBSCRIBE = "CHANNEL_UNSUBSCRIBE"; -export const HAS_FETCHED_SUBSCRIPTIONS = "HAS_FETCHED_SUBSCRIPTIONS"; +export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE'; +export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE'; +export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS'; diff --git a/src/renderer/constants/icons.js b/src/renderer/constants/icons.js index d28d7591e..728a8f196 100644 --- a/src/renderer/constants/icons.js +++ b/src/renderer/constants/icons.js @@ -1,5 +1,5 @@ -export const FEATURED = "rocket"; -export const LOCAL = "folder"; -export const FILE = "file"; -export const HISTORY = "history"; -export const HELP_CIRCLE = "question-circle"; +export const FEATURED = 'rocket'; +export const LOCAL = 'folder'; +export const FILE = 'file'; +export const HISTORY = 'history'; +export const HELP_CIRCLE = 'question-circle'; diff --git a/src/renderer/constants/languages.js b/src/renderer/constants/languages.js index f1879e904..8ae7c12cc 100644 --- a/src/renderer/constants/languages.js +++ b/src/renderer/constants/languages.js @@ -1,187 +1,187 @@ const LANGUAGES = { - aa: ["Afar", "Afar"], - ab: ["Abkhazian", "Аҧсуа"], - af: ["Afrikaans", "Afrikaans"], - ak: ["Akan", "Akana"], - am: ["Amharic", "አማርኛ"], - an: ["Aragonese", "Aragonés"], - ar: ["Arabic", "العربية"], - as: ["Assamese", "অসমীয়া"], - av: ["Avar", "Авар"], - ay: ["Aymara", "Aymar"], - az: ["Azerbaijani", "Azərbaycanca / آذربايجان"], - ba: ["Bashkir", "Башҡорт"], - be: ["Belarusian", "Беларуская"], - bg: ["Bulgarian", "Български"], - bh: ["Bihari", "भोजपुरी"], - bi: ["Bislama", "Bislama"], - bm: ["Bambara", "Bamanankan"], - bn: ["Bengali", "বাংলা"], - bo: ["Tibetan", "བོད་ཡིག / Bod skad"], - br: ["Breton", "Brezhoneg"], - bs: ["Bosnian", "Bosanski"], - ca: ["Catalan", "Català"], - ce: ["Chechen", "Нохчийн"], - ch: ["Chamorro", "Chamoru"], - co: ["Corsican", "Corsu"], - cr: ["Cree", "Nehiyaw"], - cs: ["Czech", "Česky"], - cu: ["Old Church Slavonic / Old Bulgarian", "словѣньскъ / slověnĭskŭ"], - cv: ["Chuvash", "Чăваш"], - cy: ["Welsh", "Cymraeg"], - da: ["Danish", "Dansk"], - de: ["German", "Deutsch"], - dv: ["Divehi", "ދިވެހިބަސް"], - dz: ["Dzongkha", "ཇོང་ཁ"], - ee: ["Ewe", "Ɛʋɛ"], - el: ["Greek", "Ελληνικά"], - en: ["English", "English"], - eo: ["Esperanto", "Esperanto"], - es: ["Spanish", "Español"], - et: ["Estonian", "Eesti"], - eu: ["Basque", "Euskara"], - fa: ["Persian", "فارسی"], - ff: ["Peul", "Fulfulde"], - fi: ["Finnish", "Suomi"], - fj: ["Fijian", "Na Vosa Vakaviti"], - fo: ["Faroese", "Føroyskt"], - fr: ["French", "Français"], - fy: ["West Frisian", "Frysk"], - ga: ["Irish", "Gaeilge"], - gd: ["Scottish Gaelic", "Gàidhlig"], - gl: ["Galician", "Galego"], - gn: ["Guarani", "Avañe'ẽ"], - gu: ["Gujarati", "ગુજરાતી"], - gv: ["Manx", "Gaelg"], - ha: ["Hausa", "هَوُسَ"], - he: ["Hebrew", "עברית"], - hi: ["Hindi", "हिन्दी"], - ho: ["Hiri Motu", "Hiri Motu"], - hr: ["Croatian", "Hrvatski"], - ht: ["Haitian", "Krèyol ayisyen"], - hu: ["Hungarian", "Magyar"], - hy: ["Armenian", "Հայերեն"], - hz: ["Herero", "Otsiherero"], - ia: ["Interlingua", "Interlingua"], - id: ["Indonesian", "Bahasa Indonesia"], - ie: ["Interlingue", "Interlingue"], - ig: ["Igbo", "Igbo"], - ii: ["Sichuan Yi", "ꆇꉙ / 四川彝语"], - ik: ["Inupiak", "Iñupiak"], - io: ["Ido", "Ido"], - is: ["Icelandic", "Íslenska"], - it: ["Italian", "Italiano"], - iu: ["Inuktitut", "ᐃᓄᒃᑎᑐᑦ"], - ja: ["Japanese", "日本語"], - jv: ["Javanese", "Basa Jawa"], - ka: ["Georgian", "ქართული"], - kg: ["Kongo", "KiKongo"], - ki: ["Kikuyu", "Gĩkũyũ"], - kj: ["Kuanyama", "Kuanyama"], - kk: ["Kazakh", "Қазақша"], - kl: ["Greenlandic", "Kalaallisut"], - km: ["Cambodian", "ភាសាខ្មែរ"], - kn: ["Kannada", "ಕನ್ನಡ"], - ko: ["Korean", "한국어"], - kr: ["Kanuri", "Kanuri"], - ks: ["Kashmiri", "कश्मीरी / كشميري"], - ku: ["Kurdish", "Kurdî / كوردی"], - kv: ["Komi", "Коми"], - kw: ["Cornish", "Kernewek"], - ky: ["Kirghiz", "Kırgızca / Кыргызча"], - la: ["Latin", "Latina"], - lb: ["Luxembourgish", "Lëtzebuergesch"], - lg: ["Ganda", "Luganda"], - li: ["Limburgian", "Limburgs"], - ln: ["Lingala", "Lingála"], - lo: ["Laotian", "ລາວ / Pha xa lao"], - lt: ["Lithuanian", "Lietuvių"], - lv: ["Latvian", "Latviešu"], - mg: ["Malagasy", "Malagasy"], - mh: ["Marshallese", "Kajin Majel / Ebon"], - mi: ["Maori", "Māori"], - mk: ["Macedonian", "Македонски"], - ml: ["Malayalam", "മലയാളം"], - mn: ["Mongolian", "Монгол"], - mo: ["Moldovan", "Moldovenească"], - mr: ["Marathi", "मराठी"], - ms: ["Malay", "Bahasa Melayu"], - mt: ["Maltese", "bil-Malti"], - my: ["Burmese", "Myanmasa"], - na: ["Nauruan", "Dorerin Naoero"], - nd: ["North Ndebele", "Sindebele"], - ne: ["Nepali", "नेपाली"], - ng: ["Ndonga", "Oshiwambo"], - nl: ["Dutch", "Nederlands"], - nn: ["Norwegian Nynorsk", "Norsk (nynorsk)"], - no: ["Norwegian", "Norsk (bokmål / riksmål)"], - nr: ["South Ndebele", "isiNdebele"], - nv: ["Navajo", "Diné bizaad"], - ny: ["Chichewa", "Chi-Chewa"], - oc: ["Occitan", "Occitan"], - oj: ["Ojibwa", "ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin"], - om: ["Oromo", "Oromoo"], - or: ["Oriya", "ଓଡ଼ିଆ"], - os: ["Ossetian / Ossetic", "Иронау"], - pa: ["Panjabi / Punjabi", "ਪੰਜਾਬੀ / पंजाबी / پنجابي"], - pi: ["Pali", "Pāli / पाऴि"], - pl: ["Polish", "Polski"], - ps: ["Pashto", "پښتو"], - pt: ["Portuguese", "Português"], - qu: ["Quechua", "Runa Simi"], - rm: ["Raeto Romance", "Rumantsch"], - rn: ["Kirundi", "Kirundi"], - ro: ["Romanian", "Română"], - ru: ["Russian", "Русский"], - rw: ["Rwandi", "Kinyarwandi"], - sa: ["Sanskrit", "संस्कृतम्"], - sc: ["Sardinian", "Sardu"], - sd: ["Sindhi", "सिनधि"], - se: ["Northern Sami", "Sámegiella"], - sg: ["Sango", "Sängö"], - sh: ["Serbo-Croatian", "Srpskohrvatski / Српскохрватски"], - si: ["Sinhalese", "සිංහල"], - sk: ["Slovak", "Slovenčina"], - sl: ["Slovenian", "Slovenščina"], - sm: ["Samoan", "Gagana Samoa"], - sn: ["Shona", "chiShona"], - so: ["Somalia", "Soomaaliga"], - sq: ["Albanian", "Shqip"], - sr: ["Serbian", "Српски"], - ss: ["Swati", "SiSwati"], - st: ["Southern Sotho", "Sesotho"], - su: ["Sundanese", "Basa Sunda"], - sv: ["Swedish", "Svenska"], - sw: ["Swahili", "Kiswahili"], - ta: ["Tamil", "தமிழ்"], - te: ["Telugu", "తెలుగు"], - tg: ["Tajik", "Тоҷикӣ"], - th: ["Thai", "ไทย / Phasa Thai"], - ti: ["Tigrinya", "ትግርኛ"], - tk: ["Turkmen", "Туркмен / تركمن"], - tl: ["Tagalog / Filipino", "Tagalog"], - tn: ["Tswana", "Setswana"], - to: ["Tonga", "Lea Faka-Tonga"], - tr: ["Turkish", "Türkçe"], - ts: ["Tsonga", "Xitsonga"], - tt: ["Tatar", "Tatarça"], - tw: ["Twi", "Twi"], - ty: ["Tahitian", "Reo Mā`ohi"], - ug: ["Uyghur", "Uyƣurqə / ئۇيغۇرچە"], - uk: ["Ukrainian", "Українська"], - ur: ["Urdu", "اردو"], - uz: ["Uzbek", "Ўзбек"], - ve: ["Venda", "Tshivenḓa"], - vi: ["Vietnamese", "Tiếng Việt"], - vo: ["Volapük", "Volapük"], - wa: ["Walloon", "Walon"], - wo: ["Wolof", "Wollof"], - xh: ["Xhosa", "isiXhosa"], - yi: ["Yiddish", "ייִדיש"], - yo: ["Yoruba", "Yorùbá"], - za: ["Zhuang", "Cuengh / Tôô / 壮语"], - zh: ["Chinese", "中文"], - zu: ["Zulu", "isiZulu"], + aa: ['Afar', 'Afar'], + ab: ['Abkhazian', 'Аҧсуа'], + af: ['Afrikaans', 'Afrikaans'], + ak: ['Akan', 'Akana'], + am: ['Amharic', 'አማርኛ'], + an: ['Aragonese', 'Aragonés'], + ar: ['Arabic', 'العربية'], + as: ['Assamese', 'অসমীয়া'], + av: ['Avar', 'Авар'], + ay: ['Aymara', 'Aymar'], + az: ['Azerbaijani', 'Azərbaycanca / آذربايجان'], + ba: ['Bashkir', 'Башҡорт'], + be: ['Belarusian', 'Беларуская'], + bg: ['Bulgarian', 'Български'], + bh: ['Bihari', 'भोजपुरी'], + bi: ['Bislama', 'Bislama'], + bm: ['Bambara', 'Bamanankan'], + bn: ['Bengali', 'বাংলা'], + bo: ['Tibetan', 'བོད་ཡིག / Bod skad'], + br: ['Breton', 'Brezhoneg'], + bs: ['Bosnian', 'Bosanski'], + ca: ['Catalan', 'Català'], + ce: ['Chechen', 'Нохчийн'], + ch: ['Chamorro', 'Chamoru'], + co: ['Corsican', 'Corsu'], + cr: ['Cree', 'Nehiyaw'], + cs: ['Czech', 'Česky'], + cu: ['Old Church Slavonic / Old Bulgarian', 'словѣньскъ / slověnĭskŭ'], + cv: ['Chuvash', 'Чăваш'], + cy: ['Welsh', 'Cymraeg'], + da: ['Danish', 'Dansk'], + de: ['German', 'Deutsch'], + dv: ['Divehi', 'ދިވެހިބަސް'], + dz: ['Dzongkha', 'ཇོང་ཁ'], + ee: ['Ewe', 'Ɛʋɛ'], + el: ['Greek', 'Ελληνικά'], + en: ['English', 'English'], + eo: ['Esperanto', 'Esperanto'], + es: ['Spanish', 'Español'], + et: ['Estonian', 'Eesti'], + eu: ['Basque', 'Euskara'], + fa: ['Persian', 'فارسی'], + ff: ['Peul', 'Fulfulde'], + fi: ['Finnish', 'Suomi'], + fj: ['Fijian', 'Na Vosa Vakaviti'], + fo: ['Faroese', 'Føroyskt'], + fr: ['French', 'Français'], + fy: ['West Frisian', 'Frysk'], + ga: ['Irish', 'Gaeilge'], + gd: ['Scottish Gaelic', 'Gàidhlig'], + gl: ['Galician', 'Galego'], + gn: ['Guarani', "Avañe'ẽ"], + gu: ['Gujarati', 'ગુજરાતી'], + gv: ['Manx', 'Gaelg'], + ha: ['Hausa', 'هَوُسَ'], + he: ['Hebrew', 'עברית'], + hi: ['Hindi', 'हिन्दी'], + ho: ['Hiri Motu', 'Hiri Motu'], + hr: ['Croatian', 'Hrvatski'], + ht: ['Haitian', 'Krèyol ayisyen'], + hu: ['Hungarian', 'Magyar'], + hy: ['Armenian', 'Հայերեն'], + hz: ['Herero', 'Otsiherero'], + ia: ['Interlingua', 'Interlingua'], + id: ['Indonesian', 'Bahasa Indonesia'], + ie: ['Interlingue', 'Interlingue'], + ig: ['Igbo', 'Igbo'], + ii: ['Sichuan Yi', 'ꆇꉙ / 四川彝语'], + ik: ['Inupiak', 'Iñupiak'], + io: ['Ido', 'Ido'], + is: ['Icelandic', 'Íslenska'], + it: ['Italian', 'Italiano'], + iu: ['Inuktitut', 'ᐃᓄᒃᑎᑐᑦ'], + ja: ['Japanese', '日本語'], + jv: ['Javanese', 'Basa Jawa'], + ka: ['Georgian', 'ქართული'], + kg: ['Kongo', 'KiKongo'], + ki: ['Kikuyu', 'Gĩkũyũ'], + kj: ['Kuanyama', 'Kuanyama'], + kk: ['Kazakh', 'Қазақша'], + kl: ['Greenlandic', 'Kalaallisut'], + km: ['Cambodian', 'ភាសាខ្មែរ'], + kn: ['Kannada', 'ಕನ್ನಡ'], + ko: ['Korean', '한국어'], + kr: ['Kanuri', 'Kanuri'], + ks: ['Kashmiri', 'कश्मीरी / كشميري'], + ku: ['Kurdish', 'Kurdî / كوردی'], + kv: ['Komi', 'Коми'], + kw: ['Cornish', 'Kernewek'], + ky: ['Kirghiz', 'Kırgızca / Кыргызча'], + la: ['Latin', 'Latina'], + lb: ['Luxembourgish', 'Lëtzebuergesch'], + lg: ['Ganda', 'Luganda'], + li: ['Limburgian', 'Limburgs'], + ln: ['Lingala', 'Lingála'], + lo: ['Laotian', 'ລາວ / Pha xa lao'], + lt: ['Lithuanian', 'Lietuvių'], + lv: ['Latvian', 'Latviešu'], + mg: ['Malagasy', 'Malagasy'], + mh: ['Marshallese', 'Kajin Majel / Ebon'], + mi: ['Maori', 'Māori'], + mk: ['Macedonian', 'Македонски'], + ml: ['Malayalam', 'മലയാളം'], + mn: ['Mongolian', 'Монгол'], + mo: ['Moldovan', 'Moldovenească'], + mr: ['Marathi', 'मराठी'], + ms: ['Malay', 'Bahasa Melayu'], + mt: ['Maltese', 'bil-Malti'], + my: ['Burmese', 'Myanmasa'], + na: ['Nauruan', 'Dorerin Naoero'], + nd: ['North Ndebele', 'Sindebele'], + ne: ['Nepali', 'नेपाली'], + ng: ['Ndonga', 'Oshiwambo'], + nl: ['Dutch', 'Nederlands'], + nn: ['Norwegian Nynorsk', 'Norsk (nynorsk)'], + no: ['Norwegian', 'Norsk (bokmål / riksmål)'], + nr: ['South Ndebele', 'isiNdebele'], + nv: ['Navajo', 'Diné bizaad'], + ny: ['Chichewa', 'Chi-Chewa'], + oc: ['Occitan', 'Occitan'], + oj: ['Ojibwa', 'ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin'], + om: ['Oromo', 'Oromoo'], + or: ['Oriya', 'ଓଡ଼ିଆ'], + os: ['Ossetian / Ossetic', 'Иронау'], + pa: ['Panjabi / Punjabi', 'ਪੰਜਾਬੀ / पंजाबी / پنجابي'], + pi: ['Pali', 'Pāli / पाऴि'], + pl: ['Polish', 'Polski'], + ps: ['Pashto', 'پښتو'], + pt: ['Portuguese', 'Português'], + qu: ['Quechua', 'Runa Simi'], + rm: ['Raeto Romance', 'Rumantsch'], + rn: ['Kirundi', 'Kirundi'], + ro: ['Romanian', 'Română'], + ru: ['Russian', 'Русский'], + rw: ['Rwandi', 'Kinyarwandi'], + sa: ['Sanskrit', 'संस्कृतम्'], + sc: ['Sardinian', 'Sardu'], + sd: ['Sindhi', 'सिनधि'], + se: ['Northern Sami', 'Sámegiella'], + sg: ['Sango', 'Sängö'], + sh: ['Serbo-Croatian', 'Srpskohrvatski / Српскохрватски'], + si: ['Sinhalese', 'සිංහල'], + sk: ['Slovak', 'Slovenčina'], + sl: ['Slovenian', 'Slovenščina'], + sm: ['Samoan', 'Gagana Samoa'], + sn: ['Shona', 'chiShona'], + so: ['Somalia', 'Soomaaliga'], + sq: ['Albanian', 'Shqip'], + sr: ['Serbian', 'Српски'], + ss: ['Swati', 'SiSwati'], + st: ['Southern Sotho', 'Sesotho'], + su: ['Sundanese', 'Basa Sunda'], + sv: ['Swedish', 'Svenska'], + sw: ['Swahili', 'Kiswahili'], + ta: ['Tamil', 'தமிழ்'], + te: ['Telugu', 'తెలుగు'], + tg: ['Tajik', 'Тоҷикӣ'], + th: ['Thai', 'ไทย / Phasa Thai'], + ti: ['Tigrinya', 'ትግርኛ'], + tk: ['Turkmen', 'Туркмен / تركمن'], + tl: ['Tagalog / Filipino', 'Tagalog'], + tn: ['Tswana', 'Setswana'], + to: ['Tonga', 'Lea Faka-Tonga'], + tr: ['Turkish', 'Türkçe'], + ts: ['Tsonga', 'Xitsonga'], + tt: ['Tatar', 'Tatarça'], + tw: ['Twi', 'Twi'], + ty: ['Tahitian', 'Reo Mā`ohi'], + ug: ['Uyghur', 'Uyƣurqə / ئۇيغۇرچە'], + uk: ['Ukrainian', 'Українська'], + ur: ['Urdu', 'اردو'], + uz: ['Uzbek', 'Ўзбек'], + ve: ['Venda', 'Tshivenḓa'], + vi: ['Vietnamese', 'Tiếng Việt'], + vo: ['Volapük', 'Volapük'], + wa: ['Walloon', 'Walon'], + wo: ['Wolof', 'Wollof'], + xh: ['Xhosa', 'isiXhosa'], + yi: ['Yiddish', 'ייִדיש'], + yo: ['Yoruba', 'Yorùbá'], + za: ['Zhuang', 'Cuengh / Tôô / 壮语'], + zh: ['Chinese', '中文'], + zu: ['Zulu', 'isiZulu'], }; export default LANGUAGES; diff --git a/src/renderer/constants/modal_types.js b/src/renderer/constants/modal_types.js index 3781ca220..9c6d457f9 100644 --- a/src/renderer/constants/modal_types.js +++ b/src/renderer/constants/modal_types.js @@ -1,15 +1,15 @@ -export const CONFIRM_FILE_REMOVE = "confirmFileRemove"; -export const INCOMPATIBLE_DAEMON = "incompatibleDaemon"; -export const FILE_TIMEOUT = "file_timeout"; -export const DOWNLOADING = "downloading"; -export const ERROR = "error"; -export const INSUFFICIENT_CREDITS = "insufficient_credits"; -export const UPGRADE = "upgrade"; -export const WELCOME = "welcome"; -export const EMAIL_COLLECTION = "email_collection"; -export const FIRST_REWARD = "first_reward"; -export const AUTHENTICATION_FAILURE = "auth_failure"; -export const TRANSACTION_FAILED = "transaction_failed"; -export const REWARD_APPROVAL_REQUIRED = "reward_approval_required"; -export const AFFIRM_PURCHASE = "affirm_purchase"; -export const CONFIRM_CLAIM_REVOKE = "confirmClaimRevoke"; +export const CONFIRM_FILE_REMOVE = 'confirmFileRemove'; +export const INCOMPATIBLE_DAEMON = 'incompatibleDaemon'; +export const FILE_TIMEOUT = 'file_timeout'; +export const DOWNLOADING = 'downloading'; +export const ERROR = 'error'; +export const INSUFFICIENT_CREDITS = 'insufficient_credits'; +export const UPGRADE = 'upgrade'; +export const WELCOME = 'welcome'; +export const EMAIL_COLLECTION = 'email_collection'; +export const FIRST_REWARD = 'first_reward'; +export const AUTHENTICATION_FAILURE = 'auth_failure'; +export const TRANSACTION_FAILED = 'transaction_failed'; +export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required'; +export const AFFIRM_PURCHASE = 'affirm_purchase'; +export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke'; diff --git a/src/renderer/constants/settings.js b/src/renderer/constants/settings.js index e8db70e32..dcb90ab07 100644 --- a/src/renderer/constants/settings.js +++ b/src/renderer/constants/settings.js @@ -1,13 +1,13 @@ /* hardcoded names still exist for these in reducers/settings.js - only discovered when debugging */ -/* Many settings are stored in the localStorage by their name - - be careful about changing the value of a settings constant, as doing so can invalidate existing settings */ -export const CREDIT_REQUIRED_ACKNOWLEDGED = "credit_required_acknowledged"; -export const NEW_USER_ACKNOWLEDGED = "welcome_acknowledged"; -export const EMAIL_COLLECTION_ACKNOWLEDGED = "email_collection_acknowledged"; -export const LANGUAGE = "language"; -export const SHOW_NSFW = "showNsfw"; -export const SHOW_UNAVAILABLE = "showUnavailable"; -export const INSTANT_PURCHASE_ENABLED = "instantPurchaseEnabled"; -export const INSTANT_PURCHASE_MAX = "instantPurchaseMax"; -export const THEME = "theme"; -export const THEMES = "themes"; +/* Many SETTINGS are stored in the localStorage by their name - + be careful about changing the value of a SETTINGS constant, as doing so can invalidate existing SETTINGS */ +export const CREDIT_REQUIRED_ACKNOWLEDGED = 'credit_required_acknowledged'; +export const NEW_USER_ACKNOWLEDGED = 'welcome_acknowledged'; +export const EMAIL_COLLECTION_ACKNOWLEDGED = 'email_collection_acknowledged'; +export const LANGUAGE = 'language'; +export const SHOW_NSFW = 'showNsfw'; +export const SHOW_UNAVAILABLE = 'showUnavailable'; +export const INSTANT_PURCHASE_ENABLED = 'instantPurchaseEnabled'; +export const INSTANT_PURCHASE_MAX = 'instantPurchaseMax'; +export const THEME = 'theme'; +export const THEMES = 'themes'; diff --git a/src/renderer/constants/shape_shift.js b/src/renderer/constants/shape_shift.js index d898f2fc2..1436f50d0 100644 --- a/src/renderer/constants/shape_shift.js +++ b/src/renderer/constants/shape_shift.js @@ -1,3 +1,3 @@ -export const NO_DEPOSITS = "no_deposits"; -export const RECEIVED = "received"; -export const COMPLETE = "complete"; +export const NO_DEPOSITS = 'no_deposits'; +export const RECEIVED = 'received'; +export const COMPLETE = 'complete'; diff --git a/src/renderer/constants/transaction_types.js b/src/renderer/constants/transaction_types.js index 89530f9f0..c12b68c15 100644 --- a/src/renderer/constants/transaction_types.js +++ b/src/renderer/constants/transaction_types.js @@ -1 +1,2 @@ -export const TIP = "tip"; +// eslint-disable-next-line import/prefer-default-export +export const TIP = 'tip'; diff --git a/src/renderer/flow-typed/reselect.js b/src/renderer/flow-typed/reselect.js index 9ee4a6a7f..487f653c5 100644 --- a/src/renderer/flow-typed/reselect.js +++ b/src/renderer/flow-typed/reselect.js @@ -1,3 +1,5 @@ +// @flow + declare module 'reselect' { declare module.exports: any; } diff --git a/src/renderer/index.js b/src/renderer/index.js index 66d5784e8..2506ed051 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -1,87 +1,71 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import App from "component/app/index.js"; -import SnackBar from "component/snackBar"; -import { Provider } from "react-redux"; -import store from "store.js"; -import SplashScreen from "component/splash"; -import { doDaemonReady } from "redux/actions/app"; -import { doNavigate } from "redux/actions/navigation"; -import { doDownloadLanguages } from "redux/actions/settings"; -import * as types from "constants/action_types"; -import amplitude from "amplitude-js"; -import lbry from "lbry"; -import "scss/all.scss"; +/* eslint-disable react/jsx-filename-extension */ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from 'component/app'; +import SnackBar from 'component/snackBar'; +import { Provider } from 'react-redux'; +import store from 'store'; +import SplashScreen from 'component/splash'; +import { doDaemonReady } from 'redux/actions/app'; +import { doNavigate } from 'redux/actions/navigation'; +import { doDownloadLanguages } from 'redux/actions/settings'; +import * as ACTIONS from 'constants/action_types'; +import amplitude from 'amplitude-js'; +import lbry from 'lbry'; +import 'scss/all.scss'; +import { ipcRenderer, remote, shell } from 'electron'; -const env = process.env.NODE_ENV || "production"; -const { remote, ipcRenderer, shell } = require("electron"); +const { contextMenu } = remote.require('./main.js'); -const contextMenu = remote.require("./main.js").contextMenu; -const app = require("./app"); - -// Workaround for https://github.com/electron-userland/electron-webpack/issues/52 -if (process.env.NODE_ENV !== "development") { - window.staticResourcesPath = require("path") - .join(remote.app.getAppPath(), "../static") - .replace(/\\/g, "\\\\"); -} else { - window.staticResourcesPath = ""; -} - -window.addEventListener("contextmenu", event => { +window.addEventListener('contextmenu', event => { contextMenu.showContextMenu( remote.getCurrentWindow(), event.x, event.y, - env === "development" + app.env === 'development' ); event.preventDefault(); }); -ipcRenderer.on("open-uri-requested", (event, uri) => { - if (uri && uri.startsWith("lbry://")) { - app.store.dispatch(doNavigate("/show", { uri })); +ipcRenderer.on('open-uri-requested', (event, uri) => { + if (uri && uri.startsWith('lbry://')) { + app.store.dispatch(doNavigate('/show', { uri })); } }); -ipcRenderer.on("open-menu", (event, uri) => { - if (uri && uri.startsWith("/help")) { - app.store.dispatch(doNavigate("/help")); +ipcRenderer.on('open-menu', (event, uri) => { + if (uri && uri.startsWith('/help')) { + app.store.dispatch(doNavigate('/help')); } }); -const dock = remote.app.dock; +const { dock } = remote.app; -ipcRenderer.on("window-is-focused", (event, data) => { +ipcRenderer.on('window-is-focused', () => { if (!dock) return; - app.store.dispatch({ type: types.WINDOW_FOCUSED }); - dock.setBadge(""); + app.store.dispatch({ type: ACTIONS.WINDOW_FOCUSED }); + dock.setBadge(''); }); -document.addEventListener("click", event => { - let target = event.target; +document.addEventListener('click', event => { + let { target } = event; while (target && target !== document) { - if (target.matches("a") || target.matches("button")) { + if (target.matches('a') || target.matches('button')) { // TODO: Look into using accessiblity labels (this would also make the app more accessible) - const hrefParts = window.location.href.split("#"); + const hrefParts = window.location.href.split('#'); const element = target.title || (target.text && target.text.trim()); if (element) { - amplitude.getInstance().logEvent("CLICK", { + amplitude.getInstance().logEvent('CLICK', { target: element, - location: - hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : "/", + location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/', }); } else { - amplitude.getInstance().logEvent("UNMARKED_CLICK", { - location: - hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : "/", + amplitude.getInstance().logEvent('UNMARKED_CLICK', { + location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/', }); } } - if ( - target.matches('a[href^="http"]') || - target.matches('a[href^="mailto"]') - ) { + if (target.matches('a[href^="http"]') || target.matches('a[href^="mailto"]')) { event.preventDefault(); shell.openExternal(target.href); return; @@ -90,20 +74,18 @@ document.addEventListener("click", event => { } }); -const initialState = app.store.getState(); - -const init = function() { +const init = function initializeReactApp() { app.store.dispatch(doDownloadLanguages()); function onDaemonReady() { lbry.status().then(info => { amplitude.getInstance().init( // Amplitude API Key - "0b130efdcbdbf86ec2f7f9eff354033e", + '0b130efdcbdbf86ec2f7f9eff354033e', info.lbry_id, null, () => { - window.sessionStorage.setItem("loaded", "y"); // once we've made it here once per session, we don't need to show splash again + window.sessionStorage.setItem('loaded', 'y'); // once we've made it here once per session, we don't need to show splash again app.store.dispatch(doDaemonReady()); ReactDOM.render( @@ -113,21 +95,21 @@ const init = function() { , - document.getElementById("app") + document.getElementById('app') ); } ); }); } - if (window.sessionStorage.getItem("loaded") == "y") { + if (window.sessionStorage.getItem('loaded') === 'y') { onDaemonReady(); } else { ReactDOM.render( , - document.getElementById("app") + document.getElementById('app') ); } }; diff --git a/src/renderer/jsonrpc.js b/src/renderer/jsonrpc.js index bf812d7ed..a94ba4fe8 100644 --- a/src/renderer/jsonrpc.js +++ b/src/renderer/jsonrpc.js @@ -1,76 +1,56 @@ const jsonrpc = {}; -jsonrpc.call = function( +jsonrpc.call = function callJsonRpc( connectionString, method, params, callback, errorCallback, - connectFailedCallback, - timeout + connectFailedCallback ) { function checkAndParse(response) { if (response.status >= 200 && response.status < 300) { return response.json(); } - return response - .json() - .then(json => { - let error; - if (json.error) { - error = new Error(json.error); - } else { - error = new Error("Protocol error with unknown response signature"); - } - return Promise.reject(error); - }) - .catch(e => { - console.error(e); - }); - } - - function makeRequest(url, options) { - return new Promise((resolve, reject) => { - fetch(url, options) - .then(resolve) - .catch(reject); - - if (timeout) { - const e = new Error(__("Protocol request timed out")); - setTimeout(() => reject(e), timeout); + return response.json().then(json => { + let error; + if (json.error) { + error = new Error(json.error); + } else { + error = new Error('Protocol error with unknown response signature'); } + return Promise.reject(error); }); } - const counter = parseInt(sessionStorage.getItem("JSONRPCCounter") || 0); + const counter = parseInt(sessionStorage.getItem('JSONRPCCounter') || 0, 10); const url = connectionString; const options = { - method: "POST", + method: 'POST', body: JSON.stringify({ - jsonrpc: "2.0", + jsonrpc: '2.0', method, params, id: counter, }), }; - sessionStorage.setItem("JSONRPCCounter", counter + 1); + sessionStorage.setItem('JSONRPCCounter', counter + 1); return fetch(url, options) .then(checkAndParse) .then(response => { - const error = - response.error || (response.result && response.result.error); + const error = response.error || (response.result && response.result.error); - if (!error && typeof callback === "function") { + if (!error && typeof callback === 'function') { return callback(response.result); } - if (error && typeof errorCallback === "function") { + if (error && typeof errorCallback === 'function') { return errorCallback(error); } - const errorEvent = new CustomEvent("unhandledError", { + const errorEvent = new CustomEvent('unhandledError', { detail: { connectionString, method, @@ -81,22 +61,25 @@ jsonrpc.call = function( }, }); document.dispatchEvent(errorEvent); + + return Promise.resolve(); }) - .catch(e => { + .catch(error => { if (connectFailedCallback) { - return connectFailedCallback(e); + return connectFailedCallback(error); } - const errorEvent = new CustomEvent("unhandledError", { + const errorEvent = new CustomEvent('unhandledError', { detail: { connectionString, method, params, - code: e.response && e.response.status, - message: __("Connection to API server failed"), + code: error.response && error.response.status, + message: __('Connection to API server failed'), }, }); document.dispatchEvent(errorEvent); + return Promise.resolve(); }); }; diff --git a/src/renderer/lbry.js b/src/renderer/lbry.js index 82d701f8a..27cd3ec14 100644 --- a/src/renderer/lbry.js +++ b/src/renderer/lbry.js @@ -1,5 +1,31 @@ -import jsonrpc from "./jsonrpc.js"; -import lbryuri from "./lbryuri.js"; +import jsonrpc from 'jsonrpc'; +import { ipcRenderer } from 'electron'; + +const CHECK_DAEMON_STARTED_TRY_NUMBER = 200; + +const Lbry = { + isConnected: false, + daemonConnectionString: 'http://localhost:5279', + pendingPublishTimeout: 20 * 60 * 1000, +}; + +function apiCall(method, params, resolve, reject) { + return jsonrpc.call(Lbry.daemonConnectionString, method, params, resolve, reject, reject); +} + +const lbryProxy = new Proxy(Lbry, { + get(target, name) { + if (name in target) { + return target[name]; + } + + return function(params = {}) { + return new Promise((resolve, reject) => { + apiCall(name, params, resolve, reject); + }); + }; + }, +}); function getLocal(key, fallback = undefined) { const itemRaw = localStorage.getItem(key); @@ -10,49 +36,24 @@ function setLocal(key, value) { localStorage.setItem(key, JSON.stringify(value)); } -const { remote, ipcRenderer } = require("electron"); - -let lbry = { - isConnected: false, - daemonConnectionString: "http://localhost:5279", - pendingPublishTimeout: 20 * 60 * 1000, -}; - -function apiCall(method, params, resolve, reject) { - return jsonrpc.call( - lbry.daemonConnectionString, - method, - params, - resolve, - reject, - reject - ); -} - /** * Records a publish attempt in local storage. Returns a dictionary with all the data needed to * needed to make a dummy claim or file info object. */ let pendingId = 0; -function savePendingPublish({ name, channel_name }) { - let uri; - if (channel_name) { - uri = lbryuri.build({ name: channel_name, path: name }, false); - } else { - uri = lbryuri.build({ name }, false); - } - ++pendingId; - const pendingPublishes = getLocal("pendingPublishes") || []; +function savePendingPublish({ name, channelName }) { + pendingId += 1; + const pendingPublishes = getLocal('pendingPublishes') || []; const newPendingPublish = { name, - channel_name, + channelName, claim_id: `pending-${pendingId}`, txid: `pending-${pendingId}`, nout: 0, outpoint: `pending-${pendingId}:0`, time: Date.now(), }; - setLocal("pendingPublishes", [...pendingPublishes, newPendingPublish]); + setLocal('pendingPublishes', [...pendingPublishes, newPendingPublish]); return newPendingPublish; } @@ -60,31 +61,27 @@ function savePendingPublish({ name, channel_name }) { * If there is a pending publish with the given name or outpoint, remove it. * A channel name may also be provided along with name. */ -function removePendingPublishIfNeeded({ name, channel_name, outpoint }) { +function removePendingPublishIfNeeded({ name, channelName, outpoint }) { function pubMatches(pub) { return ( pub.outpoint === outpoint || - (pub.name === name && - (!channel_name || pub.channel_name === channel_name)) + (pub.name === name && (!channelName || pub.channel_name === channelName)) ); } - setLocal( - "pendingPublishes", - lbry.getPendingPublishes().filter(pub => !pubMatches(pub)) - ); + setLocal('pendingPublishes', Lbry.getPendingPublishes().filter(pub => !pubMatches(pub))); } /** * Gets the current list of pending publish attempts. Filters out any that have timed out and * removes them from the list. */ -lbry.getPendingPublishes = function() { - const pendingPublishes = getLocal("pendingPublishes") || []; +Lbry.getPendingPublishes = function() { + const pendingPublishes = getLocal('pendingPublishes') || []; const newPendingPublishes = pendingPublishes.filter( - pub => Date.now() - pub.time <= lbry.pendingPublishTimeout + pub => Date.now() - pub.time <= Lbry.pendingPublishTimeout ); - setLocal("pendingPublishes", newPendingPublishes); + setLocal('pendingPublishes', newPendingPublishes); return newPendingPublishes; }; @@ -92,65 +89,52 @@ lbry.getPendingPublishes = function() { * Gets a pending publish attempt by its name or (fake) outpoint. A channel name can also be * provided along withe the name. If no pending publish is found, returns null. */ -function getPendingPublish({ name, channel_name, outpoint }) { - const pendingPublishes = lbry.getPendingPublishes(); +function getPendingPublish({ name, channelName, outpoint }) { + const pendingPublishes = Lbry.getPendingPublishes(); return ( pendingPublishes.find( pub => pub.outpoint === outpoint || - (pub.name === name && - (!channel_name || pub.channel_name === channel_name)) + (pub.name === name && (!channelName || pub.channel_name === channelName)) ) || null ); } -function pendingPublishToDummyClaim({ - channel_name, - name, - outpoint, - claim_id, - txid, - nout, -}) { - return { name, outpoint, claim_id, txid, nout, channel_name }; +function pendingPublishToDummyClaim({ channelName, name, outpoint, claimId, txid, nout }) { + return { name, outpoint, claimId, txid, nout, channelName }; } -function pendingPublishToDummyFileInfo({ name, outpoint, claim_id }) { - return { name, outpoint, claim_id, metadata: null }; +function pendingPublishToDummyFileInfo({ name, outpoint, claimId }) { + return { name, outpoint, claimId, metadata: null }; } // core -lbry._connectPromise = null; -lbry.connect = function() { - if (lbry._connectPromise === null) { - lbry._connectPromise = new Promise((resolve, reject) => { +Lbry.connectPromise = null; +Lbry.connect = function() { + if (Lbry.connectPromise === null) { + Lbry.connectPromise = new Promise((resolve, reject) => { let tryNum = 0; - function checkDaemonStartedFailed() { - if (tryNum <= 200) { - // Move # of tries into constant or config option - setTimeout(() => { - tryNum++; - checkDaemonStarted(); - }, tryNum < 50 ? 400 : 1000); - } else { - reject(new Error("Unable to connect to LBRY")); - } - } - // Check every half second to see if the daemon is accepting connections function checkDaemonStarted() { - lbry + tryNum += 1; + lbryProxy .status() .then(resolve) - .catch(checkDaemonStartedFailed); + .catch(() => { + if (tryNum <= CHECK_DAEMON_STARTED_TRY_NUMBER) { + setTimeout(checkDaemonStarted, tryNum < 50 ? 400 : 1000); + } else { + reject(new Error('Unable to connect to LBRY')); + } + }); } checkDaemonStarted(); }); } - return lbry._connectPromise; + return Lbry.connectPromise; }; /** @@ -160,13 +144,24 @@ lbry.connect = function() { * This currently includes a work-around to cache the file in local storage so that the pending * publish can appear in the UI immediately. */ -lbry.publishDeprecated = function( - params, - fileListedCallback, - publishedCallback, - errorCallback -) { - lbry.publish(params).then( +Lbry.publishDeprecated = function(params, fileListedCallback, publishedCallback, errorCallback) { + // Give a short grace period in case publish() returns right away or (more likely) gives an error + const returnPendingTimeout = setTimeout( + () => { + const { name, channel_name: channelName } = params; + if (publishedCallback || fileListedCallback) { + savePendingPublish({ + name, + channelName, + }); + publishedCallback(true); + } + }, + 2000, + { once: true } + ); + + lbryProxy.publish(params).then( result => { if (returnPendingTimeout) clearTimeout(returnPendingTimeout); publishedCallback(result); @@ -176,66 +171,40 @@ lbry.publishDeprecated = function( errorCallback(err); } ); - - // Give a short grace period in case publish() returns right away or (more likely) gives an error - const returnPendingTimeout = setTimeout( - () => { - if (publishedCallback) { - savePendingPublish({ - name: params.name, - channel_name: params.channel_name, - }); - publishedCallback(true); - } - - if (fileListedCallback) { - const { name, channel_name } = params; - savePendingPublish({ - name: params.name, - channel_name: params.channel_name, - }); - fileListedCallback(true); - } - }, - 2000, - { once: true } - ); }; -lbry.imagePath = function(file) { +Lbry.imagePath = function(file) { return `${staticResourcesPath}/img/${file}`; }; -lbry.getMediaType = function(contentType, fileName) { +Lbry.getMediaType = function(contentType, fileName) { if (contentType) { return /^[^/]+/.exec(contentType)[0]; } else if (fileName) { - const dotIndex = fileName.lastIndexOf("."); - if (dotIndex == -1) { - return "unknown"; + const dotIndex = fileName.lastIndexOf('.'); + if (dotIndex === -1) { + return 'unknown'; } const ext = fileName.substr(dotIndex + 1); if (/^mp4|m4v|webm|flv|f4v|ogv$/i.test(ext)) { - return "video"; + return 'video'; } else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) { - return "audio"; - } else if ( - /^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext) - ) { - return "document"; + return 'audio'; + } else if (/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext)) { + return 'document'; } - return "unknown"; + return 'unknown'; } - return "unknown"; + return 'unknown'; }; -lbry.getAppVersionInfo = function() { - return new Promise((resolve, reject) => { - ipcRenderer.once("version-info-received", (event, versionInfo) => { +Lbry.getAppVersionInfo = function() { + return new Promise(resolve => { + ipcRenderer.once('version-info-received', (event, versionInfo) => { resolve(versionInfo); }); - ipcRenderer.send("version-info-requested"); + ipcRenderer.send('version-info-requested'); }); }; @@ -248,9 +217,9 @@ lbry.getAppVersionInfo = function() { * Returns results from the file_list API method, plus dummy entries for pending publishes. * (If a real publish with the same name is found, the pending publish will be ignored and removed.) */ -lbry.file_list = function(params = {}) { +Lbry.file_list = function(params = {}) { return new Promise((resolve, reject) => { - const { name, channel_name, outpoint } = params; + const { name, channel_name: channelName, outpoint } = params; /** * If we're searching by outpoint, check first to see if there's a matching pending publish. @@ -266,16 +235,14 @@ lbry.file_list = function(params = {}) { } apiCall( - "file_list", + 'file_list', params, fileInfos => { - removePendingPublishIfNeeded({ name, channel_name, outpoint }); + removePendingPublishIfNeeded({ name, channelName, outpoint }); // if a naked file_list call, append the pending file infos - if (!name && !channel_name && !outpoint) { - const dummyFileInfos = lbry - .getPendingPublishes() - .map(pendingPublishToDummyFileInfo); + if (!name && !channelName && !outpoint) { + const dummyFileInfos = Lbry.getPendingPublishes().map(pendingPublishToDummyFileInfo); resolve([...fileInfos, ...dummyFileInfos]); } else { @@ -287,23 +254,21 @@ lbry.file_list = function(params = {}) { }); }; -lbry.claim_list_mine = function(params = {}) { +Lbry.claim_list_mine = function(params = {}) { return new Promise((resolve, reject) => { apiCall( - "claim_list_mine", + 'claim_list_mine', params, claims => { - for (const { name, channel_name, txid, nout } of claims) { + claims.forEach(({ name, channel_name: channelName, txid, nout }) => { removePendingPublishIfNeeded({ name, - channel_name, + channelName, outpoint: `${txid}:${nout}`, }); - } + }); - const dummyClaims = lbry - .getPendingPublishes() - .map(pendingPublishToDummyClaim); + const dummyClaims = Lbry.getPendingPublishes().map(pendingPublishToDummyClaim); resolve([...claims, ...dummyClaims]); }, reject @@ -311,13 +276,13 @@ lbry.claim_list_mine = function(params = {}) { }); }; -lbry.resolve = function(params = {}) { +Lbry.resolve = function(params = {}) { return new Promise((resolve, reject) => { apiCall( - "resolve", + 'resolve', params, data => { - if ("uri" in params) { + if ('uri' in params) { // If only a single URI was requested, don't nest the results in an object resolve(data && data[params.uri] ? data[params.uri] : {}); } else { @@ -329,18 +294,4 @@ lbry.resolve = function(params = {}) { }); }; -lbry = new Proxy(lbry, { - get(target, name) { - if (name in target) { - return target[name]; - } - - return function(params = {}) { - return new Promise((resolve, reject) => { - apiCall(name, params, resolve, reject); - }); - }; - }, -}); - -export default lbry; +export default lbryProxy; diff --git a/src/renderer/lbryio.js b/src/renderer/lbryio.js index 430dd7f36..694f83ed7 100644 --- a/src/renderer/lbryio.js +++ b/src/renderer/lbryio.js @@ -1,48 +1,46 @@ -import lbry from "./lbry.js"; +import Lbry from 'lbry'; +import querystring from 'querystring'; +import { ipcRenderer } from 'electron'; -const querystring = require("querystring"); -const { ipcRenderer } = require("electron"); - -const lbryio = { +const Lbryio = { enabled: true, - _authenticationPromise: null, - _exchangePromise: null, - _exchangeLastFetched: null, + authenticationPromise: null, + exchangePromise: null, + exchangeLastFetched: null, }; const CONNECTION_STRING = process.env.LBRY_APP_API_URL - ? process.env.LBRY_APP_API_URL.replace(/\/*$/, "/") // exactly one slash at the end - : "https://api.lbry.io/"; + ? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end + : 'https://api.lbry.io/'; const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000; -lbryio.getExchangeRates = function() { +Lbryio.getExchangeRates = function() { if ( - !lbryio._exchangeLastFetched || - Date.now() - lbryio._exchangeLastFetched > EXCHANGE_RATE_TIMEOUT + !Lbryio.exchangeLastFetched || + Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT ) { - lbryio._exchangePromise = new Promise((resolve, reject) => { - lbryio - .call("lbc", "exchange_rate", {}, "get", true) - .then(({ lbc_usd, lbc_btc, btc_usd }) => { - const rates = { lbc_usd, lbc_btc, btc_usd }; + Lbryio.exchangePromise = new Promise((resolve, reject) => { + Lbryio.call('lbc', 'exchange_rate', {}, 'get', true) + .then(({ lbc_usd: LBC_USD, lbc_btc: LBC_BTC, btc_usd: BTC_USD }) => { + const rates = { LBC_USD, LBC_BTC, BTC_USD }; resolve(rates); }) .catch(reject); }); - lbryio._exchangeLastFetched = Date.now(); + Lbryio.exchangeLastFetched = Date.now(); } - return lbryio._exchangePromise; + return Lbryio.exchangePromise; }; -lbryio.call = function(resource, action, params = {}, method = "get") { - if (!lbryio.enabled) { - console.log(__("Internal API disabled")); - return Promise.reject(new Error(__("LBRY internal API is disabled"))); +Lbryio.call = function(resource, action, params = {}, method = 'get') { + if (!Lbryio.enabled) { + console.log(__('Internal API disabled')); + return Promise.reject(new Error(__('LBRY internal API is disabled'))); } - if (!(method == "get" || method == "post")) { - return Promise.reject(new Error(__("Invalid method"))); + if (!(method === 'get' || method === 'post')) { + return Promise.reject(new Error(__('Invalid method'))); } function checkAndParse(response) { @@ -54,7 +52,7 @@ lbryio.call = function(resource, action, params = {}, method = "get") { if (json.error) { error = new Error(json.error); } else { - error = new Error("Unknown API error signature"); + error = new Error('Unknown API error signature'); } error.response = response; // this is primarily a hack used in actions/user.js return Promise.reject(error); @@ -65,20 +63,20 @@ lbryio.call = function(resource, action, params = {}, method = "get") { return fetch(url, options).then(checkAndParse); } - return lbryio.getAuthToken().then(token => { + return Lbryio.getAuthToken().then(token => { const fullParams = { auth_token: token, ...params }; const qs = querystring.stringify(fullParams); let url = `${CONNECTION_STRING}${resource}/${action}?${qs}`; let options = { - method: "GET", + method: 'GET', }; - if (method == "post") { + if (method === 'post') { options = { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/x-www-form-urlencoded", + 'Content-Type': 'application/x-www-form-urlencoded', }, body: qs, }; @@ -89,35 +87,35 @@ lbryio.call = function(resource, action, params = {}, method = "get") { }); }; -lbryio._authToken = null; +Lbryio.authToken = null; -lbryio.getAuthToken = () => - new Promise((resolve, reject) => { - if (lbryio._authToken) { - resolve(lbryio._authToken); +Lbryio.getAuthToken = () => + new Promise(resolve => { + if (Lbryio.authToken) { + resolve(Lbryio.authToken); } else { - ipcRenderer.once("auth-token-response", (event, token) => { - lbryio._authToken = token; + ipcRenderer.once('auth-token-response', (event, token) => { + Lbryio.authToken = token; return resolve(token); }); - ipcRenderer.send("get-auth-token"); + ipcRenderer.send('get-auth-token'); } }); -lbryio.setAuthToken = token => { - lbryio._authToken = token ? token.toString().trim() : null; - ipcRenderer.send("set-auth-token", token); +Lbryio.setAuthToken = token => { + Lbryio.authToken = token ? token.toString().trim() : null; + ipcRenderer.send('set-auth-token', token); }; -lbryio.getCurrentUser = () => lbryio.call("user", "me"); +Lbryio.getCurrentUser = () => Lbryio.call('user', 'me'); -lbryio.authenticate = function() { - if (!lbryio.enabled) { - return new Promise((resolve, reject) => { +Lbryio.authenticate = function() { + if (!Lbryio.enabled) { + return new Promise(resolve => { resolve({ id: 1, - language: "en", - primary_email: "disabled@lbry.io", + language: 'en', + primary_email: 'disabled@lbry.io', has_verified_email: true, is_identity_verified: true, is_reward_approved: false, @@ -125,58 +123,55 @@ lbryio.authenticate = function() { }); } - if (lbryio._authenticationPromise === null) { - lbryio._authenticationPromise = new Promise((resolve, reject) => { - lbryio - .getAuthToken() + if (Lbryio.authenticationPromise === null) { + Lbryio.authenticationPromise = new Promise((resolve, reject) => { + Lbryio.getAuthToken() .then(token => { if (!token || token.length > 60) { return false; } // check that token works - return lbryio - .getCurrentUser() + return Lbryio.getCurrentUser() .then(() => true) .catch(() => false); }) .then(isTokenValid => { if (isTokenValid) { - return; + return reject; } - return lbry - .status() + return Lbry.status() .then(status => - lbryio.call( - "user", - "new", + Lbryio.call( + 'user', + 'new', { - auth_token: "", - language: "en", + auth_token: '', + language: 'en', app_id: status.installation_id, }, - "post" + 'post' ) ) .then(response => { if (!response.auth_token) { - throw new Error(__("auth_token is missing from response")); + throw new Error(__('auth_token is missing from response')); } - return lbryio.setAuthToken(response.auth_token); + return Lbryio.setAuthToken(response.auth_token); }); }) - .then(lbryio.getCurrentUser) + .then(Lbryio.getCurrentUser) .then(resolve, reject); }); } - return lbryio._authenticationPromise; + return Lbryio.authenticationPromise; }; -lbryio.getStripeToken = () => - CONNECTION_STRING.startsWith("http://localhost:") - ? "pk_test_NoL1JWL7i1ipfhVId5KfDZgo" - : "pk_live_e8M4dRNnCCbmpZzduEUZBgJO"; +Lbryio.getStripeToken = () => + CONNECTION_STRING.startsWith('http://localhost:') + ? 'pk_test_NoL1JWL7i1ipfhVId5KfDZgo' + : 'pk_live_e8M4dRNnCCbmpZzduEUZBgJO'; -export default lbryio; +export default Lbryio; diff --git a/src/renderer/lbryuri.js b/src/renderer/lbryuri.js index 7d4be33c0..d9ce508dc 100644 --- a/src/renderer/lbryuri.js +++ b/src/renderer/lbryuri.js @@ -1,10 +1,10 @@ const CHANNEL_NAME_MIN_LEN = 1; const CLAIM_ID_MAX_LEN = 40; -const lbryuri = {}; +const Lbryuri = {}; -lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g; -lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; +Lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g; +Lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; /** * Parses a LBRY name into its component parts. Throws errors with user-friendly @@ -28,13 +28,13 @@ lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; * - contentName (string): For anon claims, the name; for channel claims, the path * - channelName (string, if present): Channel name without @ */ -lbryuri.parse = function(uri, requireProto = false) { +Lbryuri.parse = function(uri, requireProto = false) { // Break into components. Empty sub-matches are converted to null const componentsRegex = new RegExp( - "^((?:lbry://)?)" + // protocol - "([^:$#/]*)" + // name (stops at the first separator or end) - "([:$#]?)([^/]*)" + // modifier separator, modifier (stops at the first path separator or end) - "(/?)(.*)" // path separator, path + '^((?:lbry://)?)' + // protocol + '([^:$#/]*)' + // name (stops at the first separator or end) + '([:$#]?)([^/]*)' + // modifier separator, modifier (stops at the first path separator or end) + '(/?)(.*)' // path separator, path ); const [proto, name, modSep, modVal, pathSep, path] = componentsRegex .exec(uri) @@ -45,57 +45,54 @@ lbryuri.parse = function(uri, requireProto = false) { // Validate protocol if (requireProto && !proto) { - throw new Error(__("LBRY URIs must include a protocol prefix (lbry://).")); + throw new Error(__('LBRY URIs must include a protocol prefix (lbry://).')); } // Validate and process name if (!name) { - throw new Error(__("URI does not include name.")); + throw new Error(__('URI does not include name.')); } - const isChannel = name.startsWith("@"); + const isChannel = name.startsWith('@'); const channelName = isChannel ? name.slice(1) : name; if (isChannel) { if (!channelName) { - throw new Error(__("No channel name after @.")); + throw new Error(__('No channel name after @.')); } if (channelName.length < CHANNEL_NAME_MIN_LEN) { - throw new Error( - __( - `Channel names must be at least %s characters.`, - CHANNEL_NAME_MIN_LEN - ) - ); + throw new Error(__(`Channel names must be at least %s characters.`, CHANNEL_NAME_MIN_LEN)); } contentName = path; } - const nameBadChars = (channelName || name).match(lbryuri.REGEXP_INVALID_URI); + const nameBadChars = (channelName || name).match(Lbryuri.REGEXP_INVALID_URI); if (nameBadChars) { throw new Error( __( `Invalid character %s in name: %s.`, - nameBadChars.length == 1 ? "" : "s", - nameBadChars.join(", ") + nameBadChars.length === 1 ? '' : 's', + nameBadChars.join(', ') ) ); } // Validate and process modifier (claim ID, bid position or claim sequence) - let claimId, claimSequence, bidPosition; + let claimId; + let claimSequence; + let bidPosition; if (modSep) { if (!modVal) { throw new Error(__(`No modifier provided after separator %s.`, modSep)); } - if (modSep == "#") { + if (modSep === '#') { claimId = modVal; - } else if (modSep == ":") { + } else if (modSep === ':') { claimSequence = modVal; - } else if (modSep == "$") { + } else if (modSep === '$') { bidPosition = modVal; } } @@ -109,29 +106,27 @@ lbryuri.parse = function(uri, requireProto = false) { } if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) { - throw new Error(__("Claim sequence must be a number.")); + throw new Error(__('Claim sequence must be a number.')); } if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) { - throw new Error(__("Bid position must be a number.")); + throw new Error(__('Bid position must be a number.')); } // Validate and process path if (path) { if (!isChannel) { - throw new Error(__("Only channel URIs may have a path.")); + throw new Error(__('Only channel URIs may have a path.')); } - const pathBadChars = path.match(lbryuri.REGEXP_INVALID_URI); + const pathBadChars = path.match(Lbryuri.REGEXP_INVALID_URI); if (pathBadChars) { - throw new Error( - __(`Invalid character in path: %s`, pathBadChars.join(", ")) - ); + throw new Error(__(`Invalid character in path: %s`, pathBadChars.join(', '))); } contentName = path; } else if (pathSep) { - throw new Error(__("No path provided after /")); + throw new Error(__('No path provided after /')); } return { @@ -140,8 +135,8 @@ lbryuri.parse = function(uri, requireProto = false) { isChannel, ...(contentName ? { contentName } : {}), ...(channelName ? { channelName } : {}), - ...(claimSequence ? { claimSequence: parseInt(claimSequence) } : {}), - ...(bidPosition ? { bidPosition: parseInt(bidPosition) } : {}), + ...(claimSequence ? { claimSequence: parseInt(claimSequence, 10) } : {}), + ...(bidPosition ? { bidPosition: parseInt(bidPosition, 10) } : {}), ...(claimId ? { claimId } : {}), ...(path ? { path } : {}), }; @@ -152,21 +147,13 @@ lbryuri.parse = function(uri, requireProto = false) { * * The channelName key will accept names with or without the @ prefix. */ -lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) { - let { - name, - claimId, - claimSequence, - bidPosition, - path, - contentName, - channelName, - } = uriObj; +Lbryuri.build = function(uriObj, includeProto = true) { + const { claimId, claimSequence, bidPosition, contentName, channelName } = uriObj; + + let { name, path } = uriObj; if (channelName) { - const channelNameFormatted = channelName.startsWith("@") - ? channelName - : `@${channelName}`; + const channelNameFormatted = channelName.startsWith('@') ? channelName : `@${channelName}`; if (!name) { name = channelNameFormatted; } else if (name !== channelNameFormatted) { @@ -187,52 +174,50 @@ lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) { if (path && path !== contentName) { throw new Error( __( - "Path and contentName do not match. Only one is required; most likely you wanted contentName." + 'Path and contentName do not match. Only one is required; most likely you wanted contentName.' ) ); } } return ( - (includeProto ? "lbry://" : "") + + (includeProto ? 'lbry://' : '') + name + - (claimId ? `#${claimId}` : "") + - (claimSequence ? `:${claimSequence}` : "") + - (bidPosition ? `\$${bidPosition}` : "") + - (path ? `/${path}` : "") + (claimId ? `#${claimId}` : '') + + (claimSequence ? `:${claimSequence}` : '') + + (bidPosition ? `${bidPosition}` : '') + + (path ? `/${path}` : '') ); }; /* Takes a parseable LBRY URI and converts it to standard, canonical format (currently this just * consists of adding the lbry:// prefix if needed) */ -lbryuri.normalize = function(uri) { +Lbryuri.normalize = function(uri) { if (uri.match(/pending_claim/)) return uri; - const { name, path, bidPosition, claimSequence, claimId } = lbryuri.parse( - uri - ); - return lbryuri.build({ name, path, claimSequence, bidPosition, claimId }); + const { name, path, bidPosition, claimSequence, claimId } = Lbryuri.parse(uri); + return Lbryuri.build({ name, path, claimSequence, bidPosition, claimId }); }; -lbryuri.isValid = function(uri) { +Lbryuri.isValid = function(uri) { let parts; try { - parts = lbryuri.parse(lbryuri.normalize(uri)); + parts = Lbryuri.parse(Lbryuri.normalize(uri)); } catch (error) { return false; } return parts && parts.name; }; -lbryuri.isValidName = function(name, checkCase = true) { - const regexp = new RegExp("^[a-z0-9-]+$", checkCase ? "" : "i"); +Lbryuri.isValidName = function(name, checkCase = true) { + const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i'); return regexp.test(name); }; -lbryuri.isClaimable = function(uri) { +Lbryuri.isClaimable = function(uri) { let parts; try { - parts = lbryuri.parse(lbryuri.normalize(uri)); + parts = Lbryuri.parse(Lbryuri.normalize(uri)); } catch (error) { return false; } @@ -247,5 +232,5 @@ lbryuri.isClaimable = function(uri) { ); }; -window.lbryuri = lbryuri; -export default lbryuri; +window.lbryuri = Lbryuri; +export default Lbryuri; diff --git a/src/renderer/redux/actions/app.js b/src/renderer/redux/actions/app.js index 031b129f1..b0f8d3811 100644 --- a/src/renderer/redux/actions/app.js +++ b/src/renderer/redux/actions/app.js @@ -1,5 +1,5 @@ -import * as types from "constants/action_types"; -import lbry from "lbry"; +import * as ACTIONS from 'constants/action_types'; +import Lbry from 'lbry'; import { selectUpdateUrl, selectUpgradeDownloadPath, @@ -7,27 +7,26 @@ import { selectUpgradeFilename, selectIsUpgradeSkipped, selectRemoteVersion, -} from "redux/selectors/app"; -import { doFetchDaemonSettings } from "redux/actions/settings"; -import { doBalanceSubscribe, doFetchTransactions } from "redux/actions/wallet"; -import { doAuthenticate } from "redux/actions/user"; -import { doFetchFileInfosAndPublishedClaims } from "redux/actions/file_info"; -import * as modals from "constants/modal_types"; -import { doFetchRewardedContent } from "redux/actions/content"; -import { selectCurrentModal } from "redux/selectors/app"; + selectCurrentModal, +} from 'redux/selectors/app'; +import { doFetchDaemonSettings } from 'redux/actions/settings'; +import { doBalanceSubscribe, doFetchTransactions } from 'redux/actions/wallet'; +import { doAuthenticate } from 'redux/actions/user'; +import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info'; +import * as MODALS from 'constants/modal_types'; +import { doFetchRewardedContent } from 'redux/actions/content'; +import { ipcRenderer, remote } from 'electron'; +import Path from 'path'; -const { remote, ipcRenderer, shell } = require("electron"); -const path = require("path"); - -const { download } = remote.require("electron-dl"); -const fs = remote.require("fs"); -const { lbrySettings: config } = require("package.json"); +const { download } = remote.require('electron-dl'); +const Fs = remote.require('fs'); +const { lbrySettings: config } = require('package.json'); const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000; export function doOpenModal(modal, modalProps = {}) { return { - type: types.OPEN_MODAL, + type: ACTIONS.OPEN_MODAL, data: { modal, modalProps, @@ -37,13 +36,13 @@ export function doOpenModal(modal, modalProps = {}) { export function doCloseModal() { return { - type: types.CLOSE_MODAL, + type: ACTIONS.CLOSE_MODAL, }; } export function doUpdateDownloadProgress(percent) { return { - type: types.UPGRADE_DOWNLOAD_PROGRESSED, + type: ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED, data: { percent, }, @@ -52,7 +51,7 @@ export function doUpdateDownloadProgress(percent) { export function doSkipUpgrade() { return { - type: types.SKIP_UPGRADE, + type: ACTIONS.SKIP_UPGRADE, }; } @@ -61,7 +60,7 @@ export function doStartUpgrade() { const state = getState(); const upgradeDownloadPath = selectUpgradeDownloadPath(state); - ipcRenderer.send("upgrade", upgradeDownloadPath); + ipcRenderer.send('upgrade', upgradeDownloadPath); }; } @@ -69,40 +68,36 @@ export function doDownloadUpgrade() { return function(dispatch, getState) { const state = getState(); // Make a new directory within temp directory so the filename is guaranteed to be available - const dir = fs.mkdtempSync( - remote.app.getPath("temp") + require("path").sep - ), - upgradeFilename = selectUpgradeFilename(state); + const dir = Fs.mkdtempSync(remote.app.getPath('temp') + Path.sep); + const upgradeFilename = selectUpgradeFilename(state); const options = { onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))), directory: dir, }; - download(remote.getCurrentWindow(), selectUpdateUrl(state), options).then( - downloadItem => { - /** - * TODO: get the download path directly from the download object. It should just be - * downloadItem.getSavePath(), but the copy on the main process is being garbage collected - * too soon. - */ + download(remote.getCurrentWindow(), selectUpdateUrl(state), options).then(downloadItem => { + /** + * TODO: get the download path directly from the download object. It should just be + * downloadItem.getSavePath(), but the copy on the main process is being garbage collected + * too soon. + */ - dispatch({ - type: types.UPGRADE_DOWNLOAD_COMPLETED, - data: { - downloadItem, - path: path.join(dir, upgradeFilename), - }, - }); - } - ); + dispatch({ + type: ACTIONS.UPGRADE_DOWNLOAD_COMPLETED, + data: { + downloadItem, + path: Path.join(dir, upgradeFilename), + }, + }); + }); dispatch({ - type: types.UPGRADE_DOWNLOAD_STARTED, + type: ACTIONS.UPGRADE_DOWNLOAD_STARTED, }); dispatch({ - type: types.OPEN_MODAL, + type: ACTIONS.OPEN_MODAL, data: { - modal: modals.DOWNLOADING, + modal: MODALS.DOWNLOADING, }, }); }; @@ -127,7 +122,7 @@ export function doCancelUpgrade() { } } - dispatch({ type: types.UPGRADE_CANCELLED }); + dispatch({ type: ACTIONS.UPGRADE_CANCELLED }); }; } @@ -135,12 +130,12 @@ export function doCheckUpgradeAvailable() { return function(dispatch, getState) { const state = getState(); dispatch({ - type: types.CHECK_UPGRADE_START, + type: ACTIONS.CHECK_UPGRADE_START, }); const success = ({ remoteVersion, upgradeAvailable }) => { dispatch({ - type: types.CHECK_UPGRADE_SUCCESS, + type: ACTIONS.CHECK_UPGRADE_SUCCESS, data: { upgradeAvailable, remoteVersion, @@ -150,13 +145,12 @@ export function doCheckUpgradeAvailable() { if ( upgradeAvailable && !selectCurrentModal(state) && - (!selectIsUpgradeSkipped(state) || - remoteVersion !== selectRemoteVersion(state)) + (!selectIsUpgradeSkipped(state) || remoteVersion !== selectRemoteVersion(state)) ) { dispatch({ - type: types.OPEN_MODAL, + type: ACTIONS.OPEN_MODAL, data: { - modal: modals.UPGRADE, + modal: MODALS.UPGRADE, }, }); } @@ -164,11 +158,11 @@ export function doCheckUpgradeAvailable() { const fail = () => { dispatch({ - type: types.CHECK_UPGRADE_FAIL, + type: ACTIONS.CHECK_UPGRADE_FAIL, }); }; - lbry.getAppVersionInfo().then(success, fail); + Lbry.getAppVersionInfo().then(success, fail); }; } @@ -182,32 +176,31 @@ export function doCheckUpgradeSubscribe() { CHECK_UPGRADE_INTERVAL ); dispatch({ - type: types.CHECK_UPGRADE_SUBSCRIBE, + type: ACTIONS.CHECK_UPGRADE_SUBSCRIBE, data: { checkUpgradeTimer }, }); }; } export function doCheckDaemonVersion() { - return function(dispatch, getState) { - lbry.version().then(({ lbrynet_version }) => { + return function(dispatch) { + Lbry.version().then(({ lbrynet_version: lbrynetVersion }) => { dispatch({ type: - config.lbrynetDaemonVersion == lbrynet_version - ? types.DAEMON_VERSION_MATCH - : types.DAEMON_VERSION_MISMATCH, + config.lbrynetDaemonVersion === lbrynetVersion + ? ACTIONS.DAEMON_VERSION_MATCH + : ACTIONS.DAEMON_VERSION_MISMATCH, }); }); }; } export function doAlertError(errorList) { - return function(dispatch, getState) { - const state = getState(); + return function(dispatch) { dispatch({ - type: types.OPEN_MODAL, + type: ACTIONS.OPEN_MODAL, data: { - modal: modals.ERROR, + modal: MODALS.ERROR, modalProps: { error: errorList }, }, }); @@ -219,7 +212,7 @@ export function doDaemonReady() { const state = getState(); dispatch(doAuthenticate()); - dispatch({ type: types.DAEMON_READY }); + dispatch({ type: ACTIONS.DAEMON_READY }); dispatch(doFetchDaemonSettings()); dispatch(doBalanceSubscribe()); dispatch(doFetchFileInfosAndPublishedClaims()); @@ -234,19 +227,19 @@ export function doDaemonReady() { export function doShowSnackBar(data) { return { - type: types.SHOW_SNACKBAR, + type: ACTIONS.SHOW_SNACKBAR, data, }; } export function doRemoveSnackBarSnack() { return { - type: types.REMOVE_SNACKBAR_SNACK, + type: ACTIONS.REMOVE_SNACKBAR_SNACK, }; } export function doClearCache() { - return function(dispatch, getState) { + return function() { window.cacheStore.purge(); return Promise.resolve(); @@ -254,15 +247,15 @@ export function doClearCache() { } export function doQuit() { - return function(dispatch, getState) { + return function() { remote.app.quit(); }; } export function doChangeVolume(volume) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.VOLUME_CHANGED, + type: ACTIONS.VOLUME_CHANGED, data: { volume, }, diff --git a/src/renderer/redux/actions/availability.js b/src/renderer/redux/actions/availability.js index 5be5eb760..2382cbbf8 100644 --- a/src/renderer/redux/actions/availability.js +++ b/src/renderer/redux/actions/availability.js @@ -1,32 +1,27 @@ -import * as types from "constants/action_types"; -import lbry from "lbry"; -import { selectFetchingAvailability } from "redux/selectors/availability"; - -export function doFetchAvailability(uri) { - return function(dispatch, getState) { +// eslint-disable-next-line import/prefer-default-export +export function doFetchAvailability() { + return function() { /* this is disabled atm - Jeremy */ - return; - - const state = getState(); - const alreadyFetching = !!selectFetchingAvailability(state)[uri]; - - if (!alreadyFetching) { - dispatch({ - type: types.FETCH_AVAILABILITY_STARTED, - data: { uri }, - }); - - lbry.get_availability({ uri }).then(availability => { - dispatch({ - type: types.FETCH_AVAILABILITY_COMPLETED, - data: { - availability, - uri, - }, - }); - }); - } + // const state = getState(); + // const alreadyFetching = !!selectFetchingAvailability(state)[uri]; + // + // if (!alreadyFetching) { + // dispatch({ + // type: ACTIONS.FETCH_AVAILABILITY_STARTED, + // data: { uri }, + // }); + // + // lbry.get_availability({ uri }).then(availability => { + // dispatch({ + // type: ACTIONS.FETCH_AVAILABILITY_COMPLETED, + // data: { + // availability, + // uri, + // }, + // }); + // }); + // } }; } diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index 10c24791a..0dbab879c 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -1,65 +1,63 @@ -import * as types from "constants/action_types"; -import * as settings from "constants/settings"; -import lbry from "lbry"; -import lbryio from "lbryio"; -import lbryuri from "lbryuri"; -import { makeSelectClientSetting } from "redux/selectors/settings"; -import { selectBalance, selectTransactionItems } from "redux/selectors/wallet"; +import { ipcRenderer } from 'electron'; +import * as ACTIONS from 'constants/action_types'; +import * as SETTINGS from 'constants/settings'; +import Lbry from 'lbry'; +import Lbryio from 'lbryio'; +import Lbryuri from 'lbryuri'; +import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { selectBalance, selectTransactionItems } from 'redux/selectors/wallet'; import { makeSelectFileInfoForUri, selectDownloadingByOutpoint, -} from "redux/selectors/file_info"; -import { selectResolvingUris } from "redux/selectors/content"; -import { makeSelectCostInfoForUri } from "redux/selectors/cost_info"; -import { doAlertError, doOpenModal } from "redux/actions/app"; -import { doClaimEligiblePurchaseRewards } from "redux/actions/rewards"; -import { selectBadgeNumber } from "redux/selectors/app"; -import { selectTotalDownloadProgress } from "redux/selectors/file_info"; -import setBadge from "util/setBadge"; -import setProgressBar from "util/setProgressBar"; -import batchActions from "util/batchActions"; -import * as modals from "constants/modal_types"; - -const { ipcRenderer } = require("electron"); + selectTotalDownloadProgress, +} from 'redux/selectors/file_info'; +import { selectResolvingUris } from 'redux/selectors/content'; +import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info'; +import { doAlertError, doOpenModal } from 'redux/actions/app'; +import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards'; +import { selectBadgeNumber } from 'redux/selectors/app'; +import setBadge from 'util/setBadge'; +import setProgressBar from 'util/setProgressBar'; +import batchActions from 'util/batchActions'; +import * as MODALS from 'constants/modal_types'; const DOWNLOAD_POLL_INTERVAL = 250; export function doResolveUris(uris) { return function(dispatch, getState) { - uris = uris.map(lbryuri.normalize); + const normalizedUris = uris.map(Lbryuri.normalize); const state = getState(); // Filter out URIs that are already resolving const resolvingUris = selectResolvingUris(state); - const urisToResolve = uris.filter(uri => !resolvingUris.includes(uri)); + const urisToResolve = normalizedUris.filter(uri => !resolvingUris.includes(uri)); if (urisToResolve.length === 0) { return; } dispatch({ - type: types.RESOLVE_URIS_STARTED, - data: { uris }, + type: ACTIONS.RESOLVE_URIS_STARTED, + data: { uris: normalizedUris }, }); const resolveInfo = {}; - lbry.resolve({ uris: urisToResolve }).then(result => { - for (const [uri, uriResolveInfo] of Object.entries(result)) { + Lbry.resolve({ uris: urisToResolve }).then(result => { + Object.entries(result).forEach(([uri, uriResolveInfo]) => { const fallbackResolveInfo = { claim: null, - claims_in_channel: null, + claimsInChannel: null, certificate: null, }; - const { claim, certificate, claims_in_channel } = - uriResolveInfo && !uriResolveInfo.error - ? uriResolveInfo - : fallbackResolveInfo; - resolveInfo[uri] = { claim, certificate, claims_in_channel }; - } + const { claim, certificate, claims_in_channel: claimsInChannel } = + uriResolveInfo && !uriResolveInfo.error ? uriResolveInfo : fallbackResolveInfo; + + resolveInfo[uri] = { claim, certificate, claimsInChannel }; + }); dispatch({ - type: types.RESOLVE_URIS_COMPLETED, + type: ACTIONS.RESOLVE_URIS_COMPLETED, data: { resolveInfo }, }); }); @@ -71,23 +69,21 @@ export function doResolveUri(uri) { } export function doFetchFeaturedUris() { - return function(dispatch, getState) { - const state = getState(); - + return function(dispatch) { dispatch({ - type: types.FETCH_FEATURED_CONTENT_STARTED, + type: ACTIONS.FETCH_FEATURED_CONTENT_STARTED, }); const success = ({ Uris }) => { let urisToResolve = []; - for (const category in Uris) { + Object.keys(Uris).forEach(category => { urisToResolve = [...urisToResolve, ...Uris[category]]; - } + }); const actions = [ doResolveUris(urisToResolve), { - type: types.FETCH_FEATURED_CONTENT_COMPLETED, + type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED, data: { uris: Uris, success: true, @@ -99,24 +95,22 @@ export function doFetchFeaturedUris() { const failure = () => { dispatch({ - type: types.FETCH_FEATURED_CONTENT_COMPLETED, + type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED, data: { uris: {}, }, }); }; - lbryio.call("file", "list_homepage").then(success, failure); + Lbryio.call('file', 'list_homepage').then(success, failure); }; } export function doFetchRewardedContent() { - return function(dispatch, getState) { - const state = getState(); - + return function(dispatch) { const success = nameToClaimId => { dispatch({ - type: types.FETCH_REWARD_CONTENT_COMPLETED, + type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED, data: { claimIds: Object.values(nameToClaimId), success: true, @@ -126,7 +120,7 @@ export function doFetchRewardedContent() { const failure = () => { dispatch({ - type: types.FETCH_REWARD_CONTENT_COMPLETED, + type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED, data: { claimIds: [], success: false, @@ -134,73 +128,69 @@ export function doFetchRewardedContent() { }); }; - lbryio.call("reward", "list_featured").then(success, failure); + Lbryio.call('reward', 'list_featured').then(success, failure); }; } export function doUpdateLoadStatus(uri, outpoint) { return function(dispatch, getState) { - const state = getState(); + Lbry.file_list({ + outpoint, + full_status: true, + }).then(([fileInfo]) => { + if (!fileInfo || fileInfo.written_bytes === 0) { + // download hasn't started yet + setTimeout(() => { + dispatch(doUpdateLoadStatus(uri, outpoint)); + }, DOWNLOAD_POLL_INTERVAL); + } else if (fileInfo.completed) { + // TODO this isn't going to get called if they reload the client before + // the download finished + dispatch({ + type: ACTIONS.DOWNLOADING_COMPLETED, + data: { + uri, + outpoint, + fileInfo, + }, + }); - lbry - .file_list({ - outpoint, - full_status: true, - }) - .then(([fileInfo]) => { - if (!fileInfo || fileInfo.written_bytes == 0) { - // download hasn't started yet - setTimeout(() => { - dispatch(doUpdateLoadStatus(uri, outpoint)); - }, DOWNLOAD_POLL_INTERVAL); - } else if (fileInfo.completed) { - // TODO this isn't going to get called if they reload the client before - // the download finished - dispatch({ - type: types.DOWNLOADING_COMPLETED, - data: { - uri, - outpoint, - fileInfo, - }, - }); + const badgeNumber = selectBadgeNumber(getState()); + setBadge(badgeNumber === 0 ? '' : `${badgeNumber}`); - const badgeNumber = selectBadgeNumber(getState()); - setBadge(badgeNumber === 0 ? "" : `${badgeNumber}`); + const totalProgress = selectTotalDownloadProgress(getState()); + setProgressBar(totalProgress); - const totalProgress = selectTotalDownloadProgress(getState()); - setProgressBar(totalProgress); + const notif = new window.Notification('LBRY Download Complete', { + body: fileInfo.metadata.stream.metadata.title, + silent: false, + }); + notif.onclick = () => { + ipcRenderer.send('focusWindow', 'main'); + }; + } else { + // ready to play + const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo; + const progress = writtenBytes / totalBytes * 100; - const notif = new window.Notification("LBRY Download Complete", { - body: fileInfo.metadata.stream.metadata.title, - silent: false, - }); - notif.onclick = () => { - ipcRenderer.send("focusWindow", "main"); - }; - } else { - // ready to play - const { total_bytes, written_bytes } = fileInfo; - const progress = written_bytes / total_bytes * 100; + dispatch({ + type: ACTIONS.DOWNLOADING_PROGRESSED, + data: { + uri, + outpoint, + fileInfo, + progress, + }, + }); - dispatch({ - type: types.DOWNLOADING_PROGRESSED, - data: { - uri, - outpoint, - fileInfo, - progress, - }, - }); + const totalProgress = selectTotalDownloadProgress(getState()); + setProgressBar(totalProgress); - const totalProgress = selectTotalDownloadProgress(getState()); - setProgressBar(totalProgress); - - setTimeout(() => { - dispatch(doUpdateLoadStatus(uri, outpoint)); - }, DOWNLOAD_POLL_INTERVAL); - } - }); + setTimeout(() => { + dispatch(doUpdateLoadStatus(uri, outpoint)); + }, DOWNLOAD_POLL_INTERVAL); + } + }); }; } @@ -209,16 +199,16 @@ export function doStartDownload(uri, outpoint) { const state = getState(); if (!outpoint) { - throw new Error("outpoint is required to begin a download"); + throw new Error('outpoint is required to begin a download'); } const { downloadingByOutpoint = {} } = state.fileInfo; if (downloadingByOutpoint[outpoint]) return; - lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => { + Lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => { dispatch({ - type: types.DOWNLOADING_STARTED, + type: ACTIONS.DOWNLOADING_STARTED, data: { uri, outpoint, @@ -232,50 +222,50 @@ export function doStartDownload(uri, outpoint) { } export function doDownloadFile(uri, streamInfo) { - return function(dispatch, getState) { - const state = getState(); - + return function(dispatch) { dispatch(doStartDownload(uri, streamInfo.outpoint)); - lbryio - .call("file", "view", { - uri, - outpoint: streamInfo.outpoint, - claim_id: streamInfo.claim_id, - }) - .catch(() => {}); + Lbryio.call('file', 'view', { + uri, + outpoint: streamInfo.outpoint, + claim_id: streamInfo.claim_id, + }).catch(() => {}); dispatch(doClaimEligiblePurchaseRewards()); }; } -export function doLoadVideo(uri) { - return function(dispatch, getState) { - const state = getState(); - +export function doSetPlayingUri(uri) { + return function(dispatch) { dispatch({ - type: types.LOADING_VIDEO_STARTED, + type: ACTIONS.SET_PLAYING_URI, + data: { uri }, + }); + }; +} + +export function doLoadVideo(uri) { + return function(dispatch) { + dispatch({ + type: ACTIONS.LOADING_VIDEO_STARTED, data: { uri, }, }); - lbry - .get({ uri }) + Lbry.get({ uri }) .then(streamInfo => { const timeout = - streamInfo === null || - typeof streamInfo !== "object" || - streamInfo.error == "Timeout"; + streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout'; if (timeout) { dispatch(doSetPlayingUri(null)); dispatch({ - type: types.LOADING_VIDEO_FAILED, + type: ACTIONS.LOADING_VIDEO_FAILED, data: { uri }, }); - dispatch(doOpenModal(modals.FILE_TIMEOUT, { uri })); + dispatch(doOpenModal(MODALS.FILE_TIMEOUT, { uri })); } else { dispatch(doDownloadFile(uri, streamInfo)); } @@ -283,7 +273,7 @@ export function doLoadVideo(uri) { .catch(() => { dispatch(doSetPlayingUri(null)); dispatch({ - type: types.LOADING_VIDEO_FAILED, + type: ACTIONS.LOADING_VIDEO_FAILED, data: { uri }, }); dispatch( @@ -303,12 +293,11 @@ export function doPurchaseUri(uri) { const balance = selectBalance(state); const fileInfo = makeSelectFileInfoForUri(uri)(state); const downloadingByOutpoint = selectDownloadingByOutpoint(state); - const alreadyDownloading = - fileInfo && !!downloadingByOutpoint[fileInfo.outpoint]; + const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint]; function attemptPlay(cost, instantPurchaseMax = null) { if (cost > 0 && (!instantPurchaseMax || cost > instantPurchaseMax)) { - dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri })); + dispatch(doOpenModal(MODALS.AFFIRM_PURCHASE, { uri })); } else { dispatch(doLoadVideo(uri)); } @@ -321,12 +310,14 @@ export function doPurchaseUri(uri) { // doLoadVideo action to reconstruct the file from the blobs if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri)); - return Promise.resolve(); + Promise.resolve(); + return; } // we are already downloading the file if (alreadyDownloading) { - return Promise.resolve(); + Promise.resolve(); + return; } const costInfo = makeSelectCostInfoForUri(uri)(state); @@ -334,25 +325,21 @@ export function doPurchaseUri(uri) { if (cost > balance) { dispatch(doSetPlayingUri(null)); - dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS)); - return Promise.resolve(); + dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS)); + Promise.resolve(); + return; } - if ( - cost == 0 || - !makeSelectClientSetting(settings.INSTANT_PURCHASE_ENABLED)(state) - ) { + if (cost === 0 || !makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED)(state)) { attemptPlay(cost); } else { - const instantPurchaseMax = makeSelectClientSetting( - settings.INSTANT_PURCHASE_MAX - )(state); - if (instantPurchaseMax.currency == "LBC") { + const instantPurchaseMax = makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_MAX)(state); + if (instantPurchaseMax.currency === 'LBC') { attemptPlay(cost, instantPurchaseMax.amount); } else { // Need to convert currency of instant purchase maximum before trying to play - lbryio.getExchangeRates().then(({ lbc_usd }) => { - attemptPlay(cost, instantPurchaseMax.amount / lbc_usd); + Lbryio.getExchangeRates().then(({ LBC_USD }) => { + attemptPlay(cost, instantPurchaseMax.amount / LBC_USD); }); } } @@ -360,22 +347,22 @@ export function doPurchaseUri(uri) { } export function doFetchClaimsByChannel(uri, page) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.FETCH_CHANNEL_CLAIMS_STARTED, + type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED, data: { uri, page }, }); - lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => { + Lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => { const claimResult = result[uri] || {}; - const { claims_in_channel, returned_page } = claimResult; + const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult; dispatch({ - type: types.FETCH_CHANNEL_CLAIMS_COMPLETED, + type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED, data: { uri, - claims: claims_in_channel || [], - page: returned_page || undefined, + claims: claimsInChannel || [], + page: returnedPage || undefined, }, }); }); @@ -383,18 +370,18 @@ export function doFetchClaimsByChannel(uri, page) { } export function doFetchClaimCountByChannel(uri) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.FETCH_CHANNEL_CLAIM_COUNT_STARTED, + type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_STARTED, data: { uri }, }); - lbry.claim_list_by_channel({ uri }).then(result => { - const claimResult = result[uri], - totalClaims = claimResult ? claimResult.claims_in_channel : 0; + Lbry.claim_list_by_channel({ uri }).then(result => { + const claimResult = result[uri]; + const totalClaims = claimResult ? claimResult.claims_in_channel : 0; dispatch({ - type: types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED, + type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED, data: { uri, totalClaims, @@ -405,14 +392,14 @@ export function doFetchClaimCountByChannel(uri) { } export function doFetchClaimListMine() { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.FETCH_CLAIM_LIST_MINE_STARTED, + type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED, }); - lbry.claim_list_mine().then(claims => { + Lbry.claim_list_mine().then(claims => { dispatch({ - type: types.FETCH_CLAIM_LIST_MINE_COMPLETED, + type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED, data: { claims, }, @@ -422,69 +409,59 @@ export function doFetchClaimListMine() { } export function doPlayUri(uri) { - return function(dispatch, getState) { + return function(dispatch) { dispatch(doSetPlayingUri(uri)); dispatch(doPurchaseUri(uri)); }; } -export function doSetPlayingUri(uri) { - return function(dispatch, getState) { - dispatch({ - type: types.SET_PLAYING_URI, - data: { uri }, - }); - }; -} - export function doFetchChannelListMine() { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.FETCH_CHANNEL_LIST_MINE_STARTED, + type: ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED, }); const callback = channels => { dispatch({ - type: types.FETCH_CHANNEL_LIST_MINE_COMPLETED, + type: ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED, data: { claims: channels }, }); }; - lbry.channel_list_mine().then(callback); + Lbry.channel_list_mine().then(callback); }; } export function doCreateChannel(name, amount) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.CREATE_CHANNEL_STARTED, + type: ACTIONS.CREATE_CHANNEL_STARTED, }); return new Promise((resolve, reject) => { - lbry - .channel_new({ - channel_name: name, - amount: parseFloat(amount), - }) - .then( - channelClaim => { - channelClaim.name = name; - dispatch({ - type: types.CREATE_CHANNEL_COMPLETED, - data: { channelClaim }, - }); - resolve(channelClaim); - }, - err => { - reject(err); - } - ); + Lbry.channel_new({ + channel_name: name, + amount: parseFloat(amount), + }).then( + channelClaim => { + const newChannelClaim = channelClaim; + newChannelClaim.name = name; + dispatch({ + type: ACTIONS.CREATE_CHANNEL_COMPLETED, + data: { newChannelClaim }, + }); + resolve(newChannelClaim); + }, + error => { + reject(error); + } + ); }); }; } export function doPublish(params) { - return function(dispatch, getState) { + return function(dispatch) { return new Promise((resolve, reject) => { const success = claim => { resolve(claim); @@ -497,7 +474,7 @@ export function doPublish(params) { }; const failure = err => reject(err); - lbry.publishDeprecated(params, null, success, failure); + Lbry.publishDeprecated(params, null, success, failure); }); }; } @@ -507,40 +484,38 @@ export function doAbandonClaim(txid, nout) { const state = getState(); const transactionItems = selectTransactionItems(state); const { claim_id: claimId, claim_name: name } = transactionItems.find( - claim => claim.txid == txid && claim.nout == nout + claim => claim.txid === txid && claim.nout === nout ); dispatch({ - type: types.ABANDON_CLAIM_STARTED, + type: ACTIONS.ABANDON_CLAIM_STARTED, data: { claimId, }, }); - const errorCallback = error => { - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + const errorCallback = () => { + dispatch(doOpenModal(MODALS.TRANSACTION_FAILED)); }; const successCallback = results => { if (results.txid) { dispatch({ - type: types.ABANDON_CLAIM_SUCCEEDED, + type: ACTIONS.ABANDON_CLAIM_SUCCEEDED, data: { claimId, }, }); - dispatch(doResolveUri(lbryuri.build({ name, claimId }))); + dispatch(doResolveUri(Lbryuri.build({ name, claimId }))); dispatch(doFetchClaimListMine()); } else { - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + dispatch(doOpenModal(MODALS.TRANSACTION_FAILED)); } }; - lbry - .claim_abandon({ - txid, - nout, - }) - .then(successCallback, errorCallback); + Lbry.claim_abandon({ + txid, + nout, + }).then(successCallback, errorCallback); }; } diff --git a/src/renderer/redux/actions/cost_info.js b/src/renderer/redux/actions/cost_info.js index 8420e3cd4..acd0dc8cc 100644 --- a/src/renderer/redux/actions/cost_info.js +++ b/src/renderer/redux/actions/cost_info.js @@ -1,31 +1,18 @@ -import * as types from "constants/action_types"; -import lbry from "lbry"; -import lbryio from "lbryio"; -import { doResolveUri } from "redux/actions/content"; -import { selectResolvingUris } from "redux/selectors/content"; -import { selectClaimsByUri } from "redux/selectors/claims"; -import { selectSettingsIsGenerous } from "redux/selectors/settings"; +import * as ACTIONS from 'constants/action_types'; +import Lbryio from 'lbryio'; +import { selectClaimsByUri } from 'redux/selectors/claims'; +// eslint-disable-next-line import/prefer-default-export export function doFetchCostInfoForUri(uri) { return function(dispatch, getState) { - const state = getState(), - claim = selectClaimsByUri(state)[uri], - isGenerous = selectSettingsIsGenerous(state); + const state = getState(); + const claim = selectClaimsByUri(state)[uri]; - if (!claim) return null; - - function begin() { - dispatch({ - type: types.FETCH_COST_INFO_STARTED, - data: { - uri, - }, - }); - } + if (!claim) return; function resolve(costInfo) { dispatch({ - type: types.FETCH_COST_INFO_COMPLETED, + type: ACTIONS.FETCH_COST_INFO_COMPLETED, data: { uri, costInfo, @@ -33,18 +20,6 @@ export function doFetchCostInfoForUri(uri) { }); } - /** - * "Generous" check below is disabled. We're no longer attempting to include or estimate data fees regardless of settings. - * - * This should be modified when lbry.stream_cost_estimate is reliable and performant. - */ - - /* - lbry.stream_cost_estimate({ uri }).then(cost => { - cacheAndResolve(cost); - }, reject); - */ - const fee = claim.value && claim.value.stream && claim.value.stream.metadata ? claim.value.stream.metadata.fee @@ -52,35 +27,12 @@ export function doFetchCostInfoForUri(uri) { if (fee === undefined) { resolve({ cost: 0, includesData: true }); - } else if (fee.currency == "LBC") { + } else if (fee.currency === 'LBC') { resolve({ cost: fee.amount, includesData: true }); } else { - // begin(); - lbryio.getExchangeRates().then(({ lbc_usd }) => { - resolve({ cost: fee.amount / lbc_usd, includesData: true }); + Lbryio.getExchangeRates().then(({ LBC_USD }) => { + resolve({ cost: fee.amount / LBC_USD, includesData: true }); }); } - - // if (isGenerous && claim) { - // let cost; - // const fee = claim.value && - // claim.value.stream && - // claim.value.stream.metadata - // ? claim.value.stream.metadata.fee - // : undefined; - // if (fee === undefined) { - // resolve({ cost: 0, includesData: true }); - // } else if (fee.currency == "LBC") { - // resolve({ cost: fee.amount, includesData: true }); - // } else { - // // begin(); - // lbryio.getExchangeRates().then(({ lbc_usd }) => { - // resolve({ cost: fee.amount / lbc_usd, includesData: true }); - // }); - // } - // } else { - // begin(); - // lbry.getCostInfo(uri).then(resolve); - // } }; } diff --git a/src/renderer/redux/actions/file_info.js b/src/renderer/redux/actions/file_info.js index 68743bd05..d18bd2533 100644 --- a/src/renderer/redux/actions/file_info.js +++ b/src/renderer/redux/actions/file_info.js @@ -1,23 +1,22 @@ -import * as types from "constants/action_types"; -import lbry from "lbry"; -import { doFetchClaimListMine, doAbandonClaim } from "redux/actions/content"; +import * as ACTIONS from 'constants/action_types'; +import Lbry from 'lbry'; +import { doFetchClaimListMine, doAbandonClaim } from 'redux/actions/content'; import { selectClaimsByUri, selectIsFetchingClaimListMine, selectMyClaimsOutpoints, -} from "redux/selectors/claims"; +} from 'redux/selectors/claims'; import { selectIsFetchingFileList, selectFileInfosByOutpoint, selectUrisLoading, selectTotalDownloadProgress, -} from "redux/selectors/file_info"; -import { doCloseModal } from "redux/actions/app"; -import { doNavigate, doHistoryBack } from "redux/actions/navigation"; -import setProgressBar from "util/setProgressBar"; -import batchActions from "util/batchActions"; - -const { shell } = require("electron"); +} from 'redux/selectors/file_info'; +import { doCloseModal } from 'redux/actions/app'; +import { doHistoryBack } from 'redux/actions/navigation'; +import setProgressBar from 'util/setProgressBar'; +import batchActions from 'util/batchActions'; +import { shell } from 'electron'; export function doFetchFileInfo(uri) { return function(dispatch, getState) { @@ -28,15 +27,15 @@ export function doFetchFileInfo(uri) { if (!alreadyFetching) { dispatch({ - type: types.FETCH_FILE_INFO_STARTED, + type: ACTIONS.FETCH_FILE_INFO_STARTED, data: { outpoint, }, }); - lbry.file_list({ outpoint, full_status: true }).then(fileInfos => { + Lbry.file_list({ outpoint, full_status: true }).then(fileInfos => { dispatch({ - type: types.FETCH_FILE_INFO_COMPLETED, + type: ACTIONS.FETCH_FILE_INFO_COMPLETED, data: { outpoint, fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null, @@ -54,12 +53,12 @@ export function doFileList() { if (!isFetching) { dispatch({ - type: types.FILE_LIST_STARTED, + type: ACTIONS.FILE_LIST_STARTED, }); - lbry.file_list().then(fileInfos => { + Lbry.file_list().then(fileInfos => { dispatch({ - type: types.FILE_LIST_SUCCEEDED, + type: ACTIONS.FILE_LIST_SUCCEEDED, data: { fileInfos, }, @@ -69,8 +68,14 @@ export function doFileList() { }; } +export function doOpenFileInFolder(path) { + return function() { + shell.showItemInFolder(path); + }; +} + export function doOpenFileInShell(path) { - return function(dispatch, getState) { + return function(dispatch) { const success = shell.openItem(path); if (!success) { dispatch(doOpenFileInFolder(path)); @@ -78,17 +83,11 @@ export function doOpenFileInShell(path) { }; } -export function doOpenFileInFolder(path) { - return function(dispatch, getState) { - shell.showItemInFolder(path); - }; -} - export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { return function(dispatch, getState) { const state = getState(); - lbry.file_delete({ + Lbry.file_delete({ outpoint, delete_from_download_dir: deleteFromComputer, }); @@ -108,7 +107,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { } dispatch({ - type: types.FILE_DELETE, + type: ACTIONS.FILE_DELETE, data: { outpoint, }, @@ -119,12 +118,8 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { }; } -export function doDeleteFileAndGoBack( - fileInfo, - deleteFromComputer, - abandonClaim -) { - return function(dispatch, getState) { +export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim) { + return function(dispatch) { const actions = []; actions.push(doCloseModal()); actions.push(doHistoryBack()); @@ -135,9 +130,9 @@ export function doDeleteFileAndGoBack( export function doFetchFileInfosAndPublishedClaims() { return function(dispatch, getState) { - const state = getState(), - isFetchingClaimListMine = selectIsFetchingClaimListMine(state), - isFetchingFileInfo = selectIsFetchingFileList(state); + const state = getState(); + const isFetchingClaimListMine = selectIsFetchingClaimListMine(state); + const isFetchingFileInfo = selectIsFetchingFileList(state); if (!isFetchingClaimListMine) dispatch(doFetchClaimListMine()); if (!isFetchingFileInfo) dispatch(doFileList()); diff --git a/src/renderer/redux/actions/navigation.js b/src/renderer/redux/actions/navigation.js index 89028458c..57d0ada19 100644 --- a/src/renderer/redux/actions/navigation.js +++ b/src/renderer/redux/actions/navigation.js @@ -1,18 +1,10 @@ -import * as types from "constants/action_types"; -import { - computePageFromPath, - selectPageTitle, - selectCurrentPage, - selectCurrentParams, - selectHistoryStack, - selectHistoryIndex, -} from "redux/selectors/navigation"; -import { doSearch } from "redux/actions/search"; -import { toQueryString } from "util/query_params"; -import amplitude from "amplitude-js"; +import * as ACTIONS from 'constants/action_types'; +import { selectHistoryStack, selectHistoryIndex } from 'redux/selectors/navigation'; +import { toQueryString } from 'util/query_params'; +import amplitude from 'amplitude-js'; export function doNavigate(path, params = {}, options = {}) { - return function(dispatch, getState) { + return function(dispatch) { if (!path) { return; } @@ -22,40 +14,38 @@ export function doNavigate(path, params = {}, options = {}) { url += `?${toQueryString(params)}`; } - const scrollY = options.scrollY; + const { scrollY } = options; - amplitude.getInstance().logEvent("NAVIGATION", { destination: url }); + amplitude.getInstance().logEvent('NAVIGATION', { destination: url }); dispatch({ - type: types.HISTORY_NAVIGATE, + type: ACTIONS.HISTORY_NAVIGATE, data: { url, index: options.index, scrollY }, }); }; } export function doAuthNavigate(pathAfterAuth = null, params = {}) { - return function(dispatch, getState) { + return function(dispatch) { if (pathAfterAuth) { dispatch({ - type: types.CHANGE_AFTER_AUTH_PATH, + type: ACTIONS.CHANGE_AFTER_AUTH_PATH, data: { path: `${pathAfterAuth}?${toQueryString(params)}`, }, }); } - dispatch(doNavigate("/auth")); + dispatch(doNavigate('/auth')); }; } export function doHistoryTraverse(dispatch, state, modifier) { - const stack = selectHistoryStack(state), - index = selectHistoryIndex(state) + modifier; + const stack = selectHistoryStack(state); + const index = selectHistoryIndex(state) + modifier; if (index >= 0 && index < stack.length) { const historyItem = stack[index]; - return dispatch( - doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index }) - ); + dispatch(doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index })); } } @@ -72,9 +62,9 @@ export function doHistoryForward() { } export function doRecordScroll(scroll) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.WINDOW_SCROLLED, + type: ACTIONS.WINDOW_SCROLLED, data: { scrollY: scroll }, }); }; diff --git a/src/renderer/redux/actions/rewards.js b/src/renderer/redux/actions/rewards.js index 67200a63e..4c4a278cd 100644 --- a/src/renderer/redux/actions/rewards.js +++ b/src/renderer/redux/actions/rewards.js @@ -1,30 +1,26 @@ -import * as types from "constants/action_types"; -import * as modals from "constants/modal_types"; -import lbryio from "lbryio"; -import rewards from "rewards"; -import { selectUnclaimedRewardsByType } from "redux/selectors/rewards"; -import { selectUserIsRewardApproved } from "redux/selectors/user"; -import { selectClaimedRewardsById } from "../selectors/rewards"; +import * as ACTIONS from 'constants/action_types'; +import * as MODALS from 'constants/modal_types'; +import Lbryio from 'lbryio'; +import rewards from 'rewards'; +import { selectUnclaimedRewardsByType } from 'redux/selectors/rewards'; +import { selectUserIsRewardApproved } from 'redux/selectors/user'; export function doRewardList() { - return function(dispatch, getState) { - const state = getState(); - + return function(dispatch) { dispatch({ - type: types.FETCH_REWARDS_STARTED, + type: ACTIONS.FETCH_REWARDS_STARTED, }); - lbryio - .call("reward", "list", { multiple_rewards_per_type: true }) + Lbryio.call('reward', 'list', { multiple_rewards_per_type: true }) .then(userRewards => { dispatch({ - type: types.FETCH_REWARDS_COMPLETED, + type: ACTIONS.FETCH_REWARDS_COMPLETED, data: { userRewards }, }); }) .catch(() => { dispatch({ - type: types.FETCH_REWARDS_COMPLETED, + type: ACTIONS.FETCH_REWARDS_COMPLETED, data: { userRewards: [] }, }); }); @@ -33,10 +29,10 @@ export function doRewardList() { export function doClaimRewardType(rewardType) { return function(dispatch, getState) { - const state = getState(), - rewardsByType = selectUnclaimedRewardsByType(state), - reward = rewardsByType[rewardType], - userIsRewardApproved = selectUserIsRewardApproved(state); + const state = getState(); + const rewardsByType = selectUnclaimedRewardsByType(state); + const reward = rewardsByType[rewardType]; + const userIsRewardApproved = selectUserIsRewardApproved(state); if (!reward || reward.transaction_id) { // already claimed or doesn't exist, do nothing @@ -44,35 +40,37 @@ export function doClaimRewardType(rewardType) { } if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) { - return dispatch({ - type: types.OPEN_MODAL, - data: { modal: modals.REWARD_APPROVAL_REQUIRED }, + dispatch({ + type: ACTIONS.OPEN_MODAL, + data: { modal: MODALS.REWARD_APPROVAL_REQUIRED }, }); + + return; } dispatch({ - type: types.CLAIM_REWARD_STARTED, + type: ACTIONS.CLAIM_REWARD_STARTED, data: { reward }, }); - const success = reward => { + const success = successReward => { dispatch({ - type: types.CLAIM_REWARD_SUCCESS, + type: ACTIONS.CLAIM_REWARD_SUCCESS, data: { - reward, + reward: successReward, }, }); - if (reward.reward_type == rewards.TYPE_CONFIRM_EMAIL) { + if (successReward.reward_type === rewards.TYPE_CONFIRM_EMAIL) { dispatch({ - type: types.OPEN_MODAL, - data: { modal: modals.FIRST_REWARD }, + type: ACTIONS.OPEN_MODAL, + data: { modal: MODALS.FIRST_REWARD }, }); } }; const failure = error => { dispatch({ - type: types.CLAIM_REWARD_FAILURE, + type: ACTIONS.CLAIM_REWARD_FAILURE, data: { reward, error }, }); }; @@ -83,30 +81,28 @@ export function doClaimRewardType(rewardType) { export function doClaimEligiblePurchaseRewards() { return function(dispatch, getState) { - const state = getState(), - rewardsByType = selectUnclaimedRewardsByType(state), - userIsRewardApproved = selectUserIsRewardApproved(state); + const state = getState(); + const rewardsByType = selectUnclaimedRewardsByType(state); + const userIsRewardApproved = selectUserIsRewardApproved(state); - if (!userIsRewardApproved || !lbryio.enabled) { + if (!userIsRewardApproved || !Lbryio.enabled) { return; } if (rewardsByType[rewards.TYPE_FIRST_STREAM]) { dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM)); } else { - [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach( - type => { - dispatch(doClaimRewardType(type)); - } - ); + [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => { + dispatch(doClaimRewardType(type)); + }); } }; } export function doClaimRewardClearError(reward) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.CLAIM_REWARD_CLEAR_ERROR, + type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR, data: { reward }, }); }; diff --git a/src/renderer/redux/actions/search.js b/src/renderer/redux/actions/search.js index aa881f50d..66de54ef1 100644 --- a/src/renderer/redux/actions/search.js +++ b/src/renderer/redux/actions/search.js @@ -1,30 +1,32 @@ -import * as types from "constants/action_types"; -import lbryuri from "lbryuri"; -import { doResolveUri } from "redux/actions/content"; -import { doNavigate } from "redux/actions/navigation"; -import { selectCurrentPage } from "redux/selectors/navigation"; -import batchActions from "util/batchActions"; +import * as ACTIONS from 'constants/action_types'; +import Lbryuri from 'lbryuri'; +import { doResolveUri } from 'redux/actions/content'; +import { doNavigate } from 'redux/actions/navigation'; +import { selectCurrentPage } from 'redux/selectors/navigation'; +import batchActions from 'util/batchActions'; +// eslint-disable-next-line import/prefer-default-export export function doSearch(rawQuery) { return function(dispatch, getState) { const state = getState(); const page = selectCurrentPage(state); - const query = rawQuery.replace(/^lbry:\/\//i, ""); + const query = rawQuery.replace(/^lbry:\/\//i, ''); if (!query) { - return dispatch({ - type: types.SEARCH_CANCELLED, + dispatch({ + type: ACTIONS.SEARCH_CANCELLED, }); + return; } dispatch({ - type: types.SEARCH_STARTED, + type: ACTIONS.SEARCH_STARTED, data: { query }, }); - if (page != "search") { - dispatch(doNavigate("search", { query })); + if (page !== 'search') { + dispatch(doNavigate('search', { query })); } else { fetch(`https://lighthouse.lbry.io/search?s=${query}`) .then( @@ -38,7 +40,7 @@ export function doSearch(rawQuery) { const actions = []; data.forEach(result => { - const uri = lbryuri.build({ + const uri = Lbryuri.build({ name: result.name, claimId: result.claimId, }); @@ -47,7 +49,7 @@ export function doSearch(rawQuery) { }); actions.push({ - type: types.SEARCH_COMPLETED, + type: ACTIONS.SEARCH_COMPLETED, data: { query, uris, @@ -55,9 +57,9 @@ export function doSearch(rawQuery) { }); dispatch(batchActions(...actions)); }) - .catch(err => { + .catch(() => { dispatch({ - type: types.SEARCH_CANCELLED, + type: ACTIONS.SEARCH_CANCELLED, }); }); } diff --git a/src/renderer/redux/actions/settings.js b/src/renderer/redux/actions/settings.js index ba8b5ebcd..ec6506b15 100644 --- a/src/renderer/redux/actions/settings.js +++ b/src/renderer/redux/actions/settings.js @@ -1,17 +1,15 @@ -import * as types from "constants/action_types"; -import * as settings from "constants/settings"; -import { doAlertError } from "redux/actions/app"; -import batchActions from "util/batchActions"; +import * as ACTIONS from 'constants/action_types'; +import * as SETTINGS from 'constants/settings'; -import lbry from "lbry"; -import fs from "fs"; -import http from "http"; +import Lbry from 'lbry'; +import Fs from 'fs'; +import Http from 'http'; export function doFetchDaemonSettings() { - return function(dispatch, getState) { - lbry.settings_get().then(settings => { + return function(dispatch) { + Lbry.settings_get().then(settings => { dispatch({ - type: types.DAEMON_SETTINGS_RECEIVED, + type: ACTIONS.DAEMON_SETTINGS_RECEIVED, data: { settings, }, @@ -21,15 +19,15 @@ export function doFetchDaemonSettings() { } export function doSetDaemonSetting(key, value) { - return function(dispatch, getState) { + return function(dispatch) { const settings = {}; settings[key] = value; - lbry.settings_set(settings).then(settings); - lbry.settings_get().then(settings => { + Lbry.settings_set(settings).then(settings); + Lbry.settings_get().then(remoteSettings => { dispatch({ - type: types.DAEMON_SETTINGS_RECEIVED, + type: ACTIONS.DAEMON_SETTINGS_RECEIVED, data: { - settings, + remoteSettings, }, }); }); @@ -38,7 +36,7 @@ export function doSetDaemonSetting(key, value) { export function doSetClientSetting(key, value) { return { - type: types.CLIENT_SETTING_CHANGED, + type: ACTIONS.CLIENT_SETTING_CHANGED, data: { key, value, @@ -47,100 +45,98 @@ export function doSetClientSetting(key, value) { } export function doGetThemes() { - return function(dispatch, getState) { - const themes = ["light", "dark"]; - dispatch(doSetClientSetting(settings.THEMES, themes)); + return function(dispatch) { + const themes = ['light', 'dark']; + dispatch(doSetClientSetting(SETTINGS.THEMES, themes)); }; } export function doDownloadLanguage(langFile) { - return function(dispatch, getState) { + return function(dispatch) { const destinationPath = `${app.i18n.directory}/${langFile}`; - const language = langFile.replace(".json", ""); - const req = http.get( + const language = langFile.replace('.json', ''); + const errorHandler = () => { + Fs.unlink(destinationPath, () => {}); // Delete the file async. (But we don't check the result) + + dispatch({ + type: ACTIONS.DOWNLOAD_LANGUAGE_FAILED, + data: { language }, + }); + }; + + const req = Http.get( { headers: { - "Content-Type": "text/html", + 'Content-Type': 'text/html', }, - host: "i18n.lbry.io", + host: 'i18n.lbry.io', path: `/langs/${langFile}`, }, response => { if (response.statusCode === 200) { - const file = fs.createWriteStream(destinationPath); + const file = Fs.createWriteStream(destinationPath); - file.on("error", errorHandler); - file.on("finish", () => { + file.on('error', errorHandler); + file.on('finish', () => { file.close(); // push to our local list dispatch({ - type: types.DOWNLOAD_LANGUAGE_SUCCEEDED, + type: ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED, data: { language }, }); }); response.pipe(file); } else { - errorHandler(new Error("Language request failed.")); + errorHandler(new Error('Language request failed.')); } } ); - const errorHandler = err => { - fs.unlink(destinationPath, () => {}); // Delete the file async. (But we don't check the result) - - dispatch({ - type: types.DOWNLOAD_LANGUAGE_FAILED, - data: { language }, - }); - }; - req.setTimeout(30000, () => { req.abort(); }); - req.on("error", errorHandler); + req.on('error', errorHandler); req.end(); }; } export function doDownloadLanguages() { - return function(dispatch, getState) { + return function() { // temporarily disable i18n so I can get a working build out -- Jeremy - return; - - if (!fs.existsSync(app.i18n.directory)) { - fs.mkdirSync(app.i18n.directory); - } - - function checkStatus(response) { - if (response.status >= 200 && response.status < 300) { - return response; - } - throw new Error( - __("The list of available languages could not be retrieved.") - ); - } - - function parseJSON(response) { - return response.json(); - } - - return fetch("http://i18n.lbry.io") - .then(checkStatus) - .then(parseJSON) - .then(files => { - const actions = files.map(doDownloadLanguage); - dispatch(batchActions(...actions)); - }); + // if (!Fs.existsSync(app.i18n.directory)) { + // Fs.mkdirSync(app.i18n.directory); + // } + // + // function checkStatus(response) { + // if (response.status >= 200 && response.status < 300) { + // return response; + // } + // throw new Error( + // __("The list of available languages could not be retrieved.") + // ); + // } + // + // function parseJSON(response) { + // return response.json(); + // } + // + // return fetch("http://i18n.lbry.io") + // .then(checkStatus) + // .then(parseJSON) + // .then(files => { + // const actions = files.map(doDownloadLanguage); + // dispatch(batchActions(...actions)); + // }); }; } export function doChangeLanguage(language) { - return function(dispatch, getState) { - dispatch(doSetClientSetting(settings.LANGUAGE, language)); + return function(dispatch) { + dispatch(doSetClientSetting(SETTINGS.LANGUAGE, language)); app.i18n.setLocale(language); }; } diff --git a/src/renderer/redux/actions/shape_shift.js b/src/renderer/redux/actions/shape_shift.js index 520dff9cb..293b565ef 100644 --- a/src/renderer/redux/actions/shape_shift.js +++ b/src/renderer/redux/actions/shape_shift.js @@ -1,7 +1,7 @@ // @flow -import Promise from "bluebird"; -import * as types from "constants/action_types"; -import { coinRegexPatterns } from "util/shape_shift"; +import Promise from 'bluebird'; +import * as ACTIONS from 'constants/action_types'; +import { coinRegexPatterns } from 'util/shape_shift'; import type { GetSupportedCoinsSuccess, GetCoinStatsStart, @@ -11,26 +11,26 @@ import type { PrepareShapeShiftFail, GetActiveShiftSuccess, GetActiveShiftFail, -} from "redux/reducers/shape_shift"; -import type { FormikActions } from "types/common"; +} from 'redux/reducers/shape_shift'; +import type { FormikActions } from 'types/common'; // use promise chains instead of callbacks for shapeshift api -const shapeShift = Promise.promisifyAll(require("shapeshift.io")); +const shapeShift = Promise.promisifyAll(require('shapeshift.io')); // All ShapeShift actions // Action types defined in the reducer will contain some payload export type Action = - | { type: types.GET_SUPPORTED_COINS_START } - | { type: types.GET_SUPPORTED_COINS_FAIL } + | { type: ACTIONS.GET_SUPPORTED_COINS_START } + | { type: ACTIONS.GET_SUPPORTED_COINS_FAIL } | GetSupportedCoinsSuccess | GetCoinStatsStart - | { type: types.GET_COIN_STATS_START } + | { type: ACTIONS.GET_COIN_STATS_START } | GetCoinStatsFail | GetCoinStatsSuccess - | { type: types.PREPARE_SHAPE_SHIFT_START } + | { type: ACTIONS.PREPARE_SHAPE_SHIFT_START } | PrepareShapeShiftFail | PrepareShapeShiftSuccess - | { type: types.GET_ACTIVE_SHIFT_START } + | { type: ACTIONS.GET_ACTIVE_SHIFT_START } | GetActiveShiftFail | GetActiveShiftSuccess; @@ -38,10 +38,8 @@ export type Action = // It would be nice to import these from types/common // Not sure how that would work since they rely on the Action type type PromiseAction = Promise; +export type Dispatch = (action: Action | PromiseAction | Array) => any; type ThunkAction = (dispatch: Dispatch) => any; -export type Dispatch = ( - action: Action | ThunkAction | PromiseAction | Array -) => any; // ShapeShift form values export type ShapeShiftFormValues = { @@ -50,15 +48,26 @@ export type ShapeShiftFormValues = { receiveAddress: string, }; +export const getCoinStats = (coin: string) => (dispatch: Dispatch): ThunkAction => { + const pair = `${coin.toLowerCase()}_lbc`; + + dispatch({ type: ACTIONS.GET_COIN_STATS_START, data: coin }); + + return shapeShift + .marketInfoAsync(pair) + .then(marketInfo => dispatch({ type: ACTIONS.GET_COIN_STATS_SUCCESS, data: marketInfo })) + .catch(err => dispatch({ type: ACTIONS.GET_COIN_STATS_FAIL, data: err })); +}; + export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => { - dispatch({ type: types.GET_SUPPORTED_COINS_START }); + dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_START }); return shapeShift .coinsAsync() .then(coinData => { let supportedCoins = []; Object.keys(coinData).forEach(symbol => { - if (coinData[symbol].status === "available") { + if (coinData[symbol].status === 'available') { supportedCoins.push(coinData[symbol]); } }); @@ -69,69 +78,43 @@ export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => { .map(coin => coin.symbol); dispatch({ - type: types.GET_SUPPORTED_COINS_SUCCESS, + type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS, data: supportedCoins, }); dispatch(getCoinStats(supportedCoins[0])); }) - .catch(err => - dispatch({ type: types.GET_SUPPORTED_COINS_FAIL, data: err }) - ); + .catch(err => dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_FAIL, data: err })); }; -export const getCoinStats = (coin: string) => ( +export const createShapeShift = (values: ShapeShiftFormValues, actions: FormikActions) => ( dispatch: Dispatch ): ThunkAction => { - const pair = `${coin.toLowerCase()}_lbc`; - - dispatch({ type: types.GET_COIN_STATS_START, data: coin }); - - return shapeShift - .marketInfoAsync(pair) - .then(marketInfo => - dispatch({ type: types.GET_COIN_STATS_SUCCESS, data: marketInfo }) - ) - .catch(err => dispatch({ type: types.GET_COIN_STATS_FAIL, data: err })); -}; - -export const createShapeShift = ( - values: ShapeShiftFormValues, - actions: FormikActions -) => (dispatch: Dispatch): ThunkAction => { - const { - originCoin, - returnAddress, - receiveAddress: withdrawalAddress, - } = values; + const { originCoin, returnAddress, receiveAddress: withdrawalAddress } = values; const pair = `${originCoin.toLowerCase()}_lbc`; const options = { returnAddress, }; - dispatch({ type: types.PREPARE_SHAPE_SHIFT_START }); + dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_START }); return shapeShift .shiftAsync(withdrawalAddress, pair, options) - .then(res => - dispatch({ type: types.PREPARE_SHAPE_SHIFT_SUCCESS, data: res }) - ) + .then(res => dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS, data: res })) .catch(err => { - dispatch({ type: types.PREPARE_SHAPE_SHIFT_FAIL, data: err }); + dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_FAIL, data: err }); // for formik to stop the submit actions.setSubmitting(false); }); }; -export const getActiveShift = (depositAddress: string) => ( - dispatch: Dispatch -): ThunkAction => { - dispatch({ type: types.GET_ACTIVE_SHIFT_START }); +export const getActiveShift = (depositAddress: string) => (dispatch: Dispatch): ThunkAction => { + dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_START }); return shapeShift .statusAsync(depositAddress) - .then(res => dispatch({ type: types.GET_ACTIVE_SHIFT_SUCCESS, data: res })) - .catch(err => dispatch({ type: types.GET_ACTIVE_SHIFT_FAIL, data: err })); + .then(res => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_SUCCESS, data: res })) + .catch(err => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_FAIL, data: err })); }; export const clearShapeShift = () => (dispatch: Dispatch): Action => - dispatch({ type: types.CLEAR_SHAPE_SHIFT }); + dispatch({ type: ACTIONS.CLEAR_SHAPE_SHIFT }); diff --git a/src/renderer/redux/actions/subscriptions.js b/src/renderer/redux/actions/subscriptions.js index 6963b95bf..e3eb939ed 100644 --- a/src/renderer/redux/actions/subscriptions.js +++ b/src/renderer/redux/actions/subscriptions.js @@ -1,27 +1,18 @@ // @flow -import * as actions from "constants/action_types"; -import type { - Subscription, - Action, - Dispatch, -} from "redux/reducers/subscriptions"; -import lbry from "lbry"; +import * as ACTIONS from 'constants/action_types'; +import type { Subscription, Dispatch } from 'redux/reducers/subscriptions'; -export const doChannelSubscribe = (subscription: Subscription) => ( - dispatch: Dispatch -) => +export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) => dispatch({ - type: actions.CHANNEL_SUBSCRIBE, + type: ACTIONS.CHANNEL_SUBSCRIBE, data: subscription, }); -export const doChannelUnsubscribe = (subscription: Subscription) => ( - dispatch: Dispatch -) => +export const doChannelUnsubscribe = (subscription: Subscription) => (dispatch: Dispatch) => dispatch({ - type: actions.CHANNEL_UNSUBSCRIBE, + type: ACTIONS.CHANNEL_UNSUBSCRIBE, data: subscription, }); export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) => - dispatch({ type: actions.HAS_FETCHED_SUBSCRIPTIONS }); + dispatch({ type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS }); diff --git a/src/renderer/redux/actions/user.js b/src/renderer/redux/actions/user.js index 3fb7f8f43..1dfbee4ca 100644 --- a/src/renderer/redux/actions/user.js +++ b/src/renderer/redux/actions/user.js @@ -1,30 +1,54 @@ -import * as types from "constants/action_types"; -import * as modals from "constants/modal_types"; -import lbryio from "lbryio"; -import { doOpenModal, doShowSnackBar } from "redux/actions/app"; -import { doRewardList, doClaimRewardType } from "redux/actions/rewards"; -import { selectEmailToVerify, selectUser } from "redux/selectors/user"; -import rewards from "rewards"; +import * as ACTIONS from 'constants/action_types'; +import * as MODALS from 'constants/modal_types'; +import Lbryio from 'lbryio'; +import { doOpenModal, doShowSnackBar } from 'redux/actions/app'; +import { doRewardList, doClaimRewardType } from 'redux/actions/rewards'; +import { selectEmailToVerify } from 'redux/selectors/user'; +import rewards from 'rewards'; + +export function doFetchInviteStatus() { + return function(dispatch) { + dispatch({ + type: ACTIONS.USER_INVITE_STATUS_FETCH_STARTED, + }); + + Lbryio.call('user', 'invite_status') + .then(status => { + dispatch({ + type: ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS, + data: { + invitesRemaining: status.invites_remaining ? status.invites_remaining : 0, + invitees: status.invitees, + }, + }); + }) + .catch(error => { + dispatch({ + type: ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE, + data: { error }, + }); + }); + }; +} export function doAuthenticate() { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.AUTHENTICATION_STARTED, + type: ACTIONS.AUTHENTICATION_STARTED, }); - lbryio - .authenticate() + Lbryio.authenticate() .then(user => { dispatch({ - type: types.AUTHENTICATION_SUCCESS, + type: ACTIONS.AUTHENTICATION_SUCCESS, data: { user }, }); dispatch(doRewardList()); dispatch(doFetchInviteStatus()); }) .catch(error => { - dispatch(doOpenModal(modals.AUTHENTICATION_FAILURE)); + dispatch(doOpenModal(MODALS.AUTHENTICATION_FAILURE)); dispatch({ - type: types.AUTHENTICATION_FAILURE, + type: ACTIONS.AUTHENTICATION_FAILURE, data: { error }, }); }); @@ -32,23 +56,22 @@ export function doAuthenticate() { } export function doUserFetch() { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.USER_FETCH_STARTED, + type: ACTIONS.USER_FETCH_STARTED, }); - lbryio - .getCurrentUser() + Lbryio.getCurrentUser() .then(user => { dispatch(doRewardList()); dispatch({ - type: types.USER_FETCH_SUCCESS, + type: ACTIONS.USER_FETCH_SUCCESS, data: { user }, }); }) .catch(error => { dispatch({ - type: types.USER_FETCH_FAILURE, + type: ACTIONS.USER_FETCH_FAILURE, data: { error }, }); }); @@ -56,15 +79,15 @@ export function doUserFetch() { } export function doUserEmailNew(email) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.USER_EMAIL_NEW_STARTED, + type: ACTIONS.USER_EMAIL_NEW_STARTED, email, }); const success = () => { dispatch({ - type: types.USER_EMAIL_NEW_SUCCESS, + type: ACTIONS.USER_EMAIL_NEW_SUCCESS, data: { email }, }); dispatch(doUserFetch()); @@ -72,28 +95,20 @@ export function doUserEmailNew(email) { const failure = error => { dispatch({ - type: types.USER_EMAIL_NEW_FAILURE, + type: ACTIONS.USER_EMAIL_NEW_FAILURE, data: { error }, }); }; - lbryio - .call( - "user_email", - "new", - { email, send_verification_email: true }, - "post" - ) + Lbryio.call('user_email', 'new', { email, send_verification_email: true }, 'post') .catch(error => { - if (error.response && error.response.status == 409) { - return lbryio - .call( - "user_email", - "resend_token", - { email, only_if_expired: true }, - "post" - ) - .then(success, failure); + if (error.response && error.response.status === 409) { + return Lbryio.call( + 'user_email', + 'resend_token', + { email, only_if_expired: true }, + 'post' + ).then(success, failure); } throw error; }) @@ -104,35 +119,34 @@ export function doUserEmailNew(email) { export function doUserEmailVerify(verificationToken) { return function(dispatch, getState) { const email = selectEmailToVerify(getState()); - verificationToken = verificationToken.toString().trim(); + const trimmedVerificationToken = verificationToken.toString().trim(); dispatch({ - type: types.USER_EMAIL_VERIFY_STARTED, - code: verificationToken, + type: ACTIONS.USER_EMAIL_VERIFY_STARTED, + code: trimmedVerificationToken, }); - lbryio - .call( - "user_email", - "confirm", - { verification_token: verificationToken, email }, - "post" - ) + Lbryio.call( + 'user_email', + 'confirm', + { verification_token: trimmedVerificationToken, email }, + 'post' + ) .then(userEmail => { if (userEmail.is_verified) { dispatch({ - type: types.USER_EMAIL_VERIFY_SUCCESS, + type: ACTIONS.USER_EMAIL_VERIFY_SUCCESS, data: { email }, }); - dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL)), - dispatch(doUserFetch()); + dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL)); + dispatch(doUserFetch()); } else { - throw new Error("Your email is still not verified."); // shouldn't happen + throw new Error('Your email is still not verified.'); // shouldn't happen } }) .catch(error => { dispatch({ - type: types.USER_EMAIL_VERIFY_FAILURE, + type: ACTIONS.USER_EMAIL_VERIFY_FAILURE, data: { error }, }); }); @@ -140,30 +154,27 @@ export function doUserEmailVerify(verificationToken) { } export function doUserIdentityVerify(stripeToken) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.USER_IDENTITY_VERIFY_STARTED, + type: ACTIONS.USER_IDENTITY_VERIFY_STARTED, token: stripeToken, }); - lbryio - .call("user", "verify_identity", { stripe_token: stripeToken }, "post") + Lbryio.call('user', 'verify_identity', { stripe_token: stripeToken }, 'post') .then(user => { if (user.is_identity_verified) { dispatch({ - type: types.USER_IDENTITY_VERIFY_SUCCESS, + type: ACTIONS.USER_IDENTITY_VERIFY_SUCCESS, data: { user }, }); dispatch(doClaimRewardType(rewards.TYPE_NEW_USER)); } else { - throw new Error( - "Your identity is still not verified. This should not happen." - ); // shouldn't happen + throw new Error('Your identity is still not verified. This should not happen.'); // shouldn't happen } }) .catch(error => { dispatch({ - type: types.USER_IDENTITY_VERIFY_FAILURE, + type: ACTIONS.USER_IDENTITY_VERIFY_FAILURE, data: { error: error.toString() }, }); }); @@ -171,61 +182,32 @@ export function doUserIdentityVerify(stripeToken) { } export function doFetchAccessToken() { - return function(dispatch, getState) { + return function(dispatch) { const success = token => dispatch({ - type: types.FETCH_ACCESS_TOKEN_SUCCESS, + type: ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS, data: { token }, }); - lbryio.getAuthToken().then(success); - }; -} - -export function doFetchInviteStatus() { - return function(dispatch, getState) { - dispatch({ - type: types.USER_INVITE_STATUS_FETCH_STARTED, - }); - - lbryio - .call("user", "invite_status") - .then(status => { - dispatch({ - type: types.USER_INVITE_STATUS_FETCH_SUCCESS, - data: { - invitesRemaining: status.invites_remaining - ? status.invites_remaining - : 0, - invitees: status.invitees, - }, - }); - }) - .catch(error => { - dispatch({ - type: types.USER_INVITE_STATUS_FETCH_FAILURE, - data: { error }, - }); - }); + Lbryio.getAuthToken().then(success); }; } export function doUserInviteNew(email) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.USER_INVITE_NEW_STARTED, + type: ACTIONS.USER_INVITE_NEW_STARTED, }); - lbryio - .call("user", "invite", { email }, "post") - .then(invite => { + Lbryio.call('user', 'invite', { email }, 'post') + .then(() => { dispatch({ - type: types.USER_INVITE_NEW_SUCCESS, + type: ACTIONS.USER_INVITE_NEW_SUCCESS, data: { email }, }); dispatch( doShowSnackBar({ - message: __("Invite sent to %s", email), + message: __('Invite sent to %s', email), }) ); @@ -233,7 +215,7 @@ export function doUserInviteNew(email) { }) .catch(error => { dispatch({ - type: types.USER_INVITE_NEW_FAILURE, + type: ACTIONS.USER_INVITE_NEW_FAILURE, data: { error }, }); }); diff --git a/src/renderer/redux/actions/wallet.js b/src/renderer/redux/actions/wallet.js index 0d8d44429..10974085e 100644 --- a/src/renderer/redux/actions/wallet.js +++ b/src/renderer/redux/actions/wallet.js @@ -1,19 +1,19 @@ -import * as types from "constants/action_types"; -import lbry from "lbry"; +import * as ACTIONS from 'constants/action_types'; +import Lbry from 'lbry'; import { selectDraftTransaction, selectDraftTransactionAmount, selectBalance, -} from "redux/selectors/wallet"; -import { doOpenModal, doShowSnackBar } from "redux/actions/app"; -import { doNavigate } from "redux/actions/navigation"; -import * as modals from "constants/modal_types"; +} from 'redux/selectors/wallet'; +import { doOpenModal, doShowSnackBar } from 'redux/actions/app'; +import { doNavigate } from 'redux/actions/navigation'; +import * as MODALS from 'constants/modal_types'; export function doUpdateBalance() { - return function(dispatch, getState) { - lbry.wallet_balance().then(balance => + return function(dispatch) { + Lbry.wallet_balance().then(balance => dispatch({ - type: types.UPDATE_BALANCE, + type: ACTIONS.UPDATE_BALANCE, data: { balance, }, @@ -23,36 +23,34 @@ export function doUpdateBalance() { } export function doBalanceSubscribe() { - return function(dispatch, getState) { + return function(dispatch) { dispatch(doUpdateBalance()); setInterval(() => dispatch(doUpdateBalance()), 5000); }; } export function doFetchTransactions(fetch_tip_info = true) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.FETCH_TRANSACTIONS_STARTED, + type: ACTIONS.FETCH_TRANSACTIONS_STARTED, }); - lbry - .transaction_list({ include_tip_info: fetch_tip_info }) - .then(results => { - dispatch({ - type: types.FETCH_TRANSACTIONS_COMPLETED, - data: { - transactions: results, - }, - }); + Lbry.transaction_list({ include_tip_info: fetch_tip_info }).then(results => { + dispatch({ + type: ACTIONS.FETCH_TRANSACTIONS_COMPLETED, + data: { + transactions: results, + }, }); + }); }; } export function doFetchBlock(height) { - return function(dispatch, getState) { - lbry.block_show({ height }).then(block => { + return function(dispatch) { + Lbry.block_show({ height }).then(block => { dispatch({ - type: types.FETCH_BLOCK_SUCCESS, + type: ACTIONS.FETCH_BLOCK_SUCCESS, data: { block }, }); }); @@ -60,15 +58,15 @@ export function doFetchBlock(height) { } export function doGetNewAddress() { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.GET_NEW_ADDRESS_STARTED, + type: ACTIONS.GET_NEW_ADDRESS_STARTED, }); - lbry.wallet_new_address().then(address => { - localStorage.setItem("wallet_address", address); + Lbry.wallet_new_address().then(address => { + localStorage.setItem('wallet_address', address); dispatch({ - type: types.GET_NEW_ADDRESS_COMPLETED, + type: ACTIONS.GET_NEW_ADDRESS_COMPLETED, data: { address }, }); }); @@ -76,16 +74,16 @@ export function doGetNewAddress() { } export function doCheckAddressIsMine(address) { - return function(dispatch, getState) { + return function(dispatch) { dispatch({ - type: types.CHECK_ADDRESS_IS_MINE_STARTED, + type: ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED, }); - lbry.wallet_is_address_mine({ address }).then(isMine => { + Lbry.wallet_is_address_mine({ address }).then(isMine => { if (!isMine) dispatch(doGetNewAddress()); dispatch({ - type: types.CHECK_ADDRESS_IS_MINE_COMPLETED, + type: ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED, }); }); }; @@ -99,113 +97,111 @@ export function doSendDraftTransaction() { const amount = selectDraftTransactionAmount(state); if (balance - amount <= 0) { - return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS)); + dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS)); + return; } dispatch({ - type: types.SEND_TRANSACTION_STARTED, + type: ACTIONS.SEND_TRANSACTION_STARTED, }); const successCallback = results => { if (results === true) { dispatch({ - type: types.SEND_TRANSACTION_COMPLETED, + type: ACTIONS.SEND_TRANSACTION_COMPLETED, }); dispatch( doShowSnackBar({ message: __(`You sent ${amount} LBC`), - linkText: __("History"), - linkTarget: __("/wallet"), + linkText: __('History'), + linkTarget: __('/wallet'), }) ); } else { dispatch({ - type: types.SEND_TRANSACTION_FAILED, + type: ACTIONS.SEND_TRANSACTION_FAILED, data: { error: results }, }); - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + dispatch(doOpenModal(MODALS.TRANSACTION_FAILED)); } }; const errorCallback = error => { dispatch({ - type: types.SEND_TRANSACTION_FAILED, + type: ACTIONS.SEND_TRANSACTION_FAILED, data: { error: error.message }, }); - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + dispatch(doOpenModal(MODALS.TRANSACTION_FAILED)); }; - lbry - .wallet_send({ - amount: draftTx.amount, - address: draftTx.address, - }) - .then(successCallback, errorCallback); + Lbry.wallet_send({ + amount: draftTx.amount, + address: draftTx.address, + }).then(successCallback, errorCallback); }; } export function doSetDraftTransactionAmount(amount) { return { - type: types.SET_DRAFT_TRANSACTION_AMOUNT, + type: ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT, data: { amount }, }; } export function doSetDraftTransactionAddress(address) { return { - type: types.SET_DRAFT_TRANSACTION_ADDRESS, + type: ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS, data: { address }, }; } -export function doSendSupport(amount, claim_id, uri) { +export function doSendSupport(amount, claimId, uri) { return function(dispatch, getState) { const state = getState(); const balance = selectBalance(state); if (balance - amount <= 0) { - return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS)); + dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS)); + return; } dispatch({ - type: types.SUPPORT_TRANSACTION_STARTED, + type: ACTIONS.SUPPORT_TRANSACTION_STARTED, }); const successCallback = results => { if (results.txid) { dispatch({ - type: types.SUPPORT_TRANSACTION_COMPLETED, + type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED, }); dispatch( doShowSnackBar({ message: __(`You sent ${amount} LBC as support, Mahalo!`), - linkText: __("History"), - linkTarget: __("/wallet"), + linkText: __('History'), + linkTarget: __('/wallet'), }) ); - dispatch(doNavigate("/show", { uri })); + dispatch(doNavigate('/show', { uri })); } else { dispatch({ - type: types.SUPPORT_TRANSACTION_FAILED, + type: ACTIONS.SUPPORT_TRANSACTION_FAILED, data: { error: results.code }, }); - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + dispatch(doOpenModal(MODALS.TRANSACTION_FAILED)); } }; const errorCallback = error => { dispatch({ - type: types.SUPPORT_TRANSACTION_FAILED, + type: ACTIONS.SUPPORT_TRANSACTION_FAILED, data: { error: error.code }, }); - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + dispatch(doOpenModal(MODALS.TRANSACTION_FAILED)); }; - lbry - .wallet_send({ - claim_id, - amount, - }) - .then(successCallback, errorCallback); + Lbry.wallet_send({ + claimId, + amount, + }).then(successCallback, errorCallback); }; } diff --git a/src/renderer/redux/reducers/app.js b/src/renderer/redux/reducers/app.js index b18062e0c..c8a821fa8 100644 --- a/src/renderer/redux/reducers/app.js +++ b/src/renderer/redux/reducers/app.js @@ -1,11 +1,10 @@ // @flow -import * as types from "constants/action_types"; -import * as modalTypes from "constants/modal_types"; +import * as ACTIONS from 'constants/action_types'; +import * as MODALS from 'constants/modal_types'; -const { remote } = require("electron"); +const { remote } = require('electron'); -const application = remote.app; const win = remote.BrowserWindow.getFocusedWindow(); const reducers = {}; @@ -41,12 +40,12 @@ const defaultState: AppState = { modal: null, modalProps: {}, platform: process.platform, - upgradeSkipped: sessionStorage.getItem("upgradeSkipped") === "true", + upgradeSkipped: sessionStorage.getItem('upgradeSkipped') === 'true', daemonVersionMatched: null, daemonReady: false, hasSignature: false, badgeNumber: 0, - volume: Number(sessionStorage.getItem("volume")) || 1, + volume: Number(sessionStorage.getItem('volume')) || 1, downloadProgress: undefined, upgradeDownloading: undefined, @@ -57,26 +56,26 @@ const defaultState: AppState = { snackBar: undefined, }; -reducers[types.DAEMON_READY] = function(state, action) { +reducers[ACTIONS.DAEMON_READY] = function(state) { return Object.assign({}, state, { daemonReady: true, }); }; -reducers[types.DAEMON_VERSION_MATCH] = function(state, action) { +reducers[ACTIONS.DAEMON_VERSION_MATCH] = function(state) { return Object.assign({}, state, { daemonVersionMatched: true, }); }; -reducers[types.DAEMON_VERSION_MISMATCH] = function(state, action) { +reducers[ACTIONS.DAEMON_VERSION_MISMATCH] = function(state) { return Object.assign({}, state, { daemonVersionMatched: false, - modal: modalTypes.INCOMPATIBLE_DAEMON, + modal: MODALS.INCOMPATIBLE_DAEMON, }); }; -reducers[types.UPGRADE_CANCELLED] = function(state, action) { +reducers[ACTIONS.UPGRADE_CANCELLED] = function(state) { return Object.assign({}, state, { downloadProgress: null, upgradeDownloadComplete: false, @@ -84,7 +83,7 @@ reducers[types.UPGRADE_CANCELLED] = function(state, action) { }); }; -reducers[types.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) { +reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) { return Object.assign({}, state, { downloadPath: action.data.path, upgradeDownloading: false, @@ -92,14 +91,14 @@ reducers[types.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) { }); }; -reducers[types.UPGRADE_DOWNLOAD_STARTED] = function(state, action) { +reducers[ACTIONS.UPGRADE_DOWNLOAD_STARTED] = function(state) { return Object.assign({}, state, { upgradeDownloading: true, }); }; -reducers[types.SKIP_UPGRADE] = function(state, action) { - sessionStorage.setItem("upgradeSkipped", "true"); +reducers[ACTIONS.SKIP_UPGRADE] = function(state) { + sessionStorage.setItem('upgradeSkipped', 'true'); return Object.assign({}, state, { isUpgradeSkipped: true, @@ -107,46 +106,46 @@ reducers[types.SKIP_UPGRADE] = function(state, action) { }); }; -reducers[types.UPDATE_VERSION] = function(state, action) { +reducers[ACTIONS.UPDATE_VERSION] = function(state, action) { return Object.assign({}, state, { version: action.data.version, }); }; -reducers[types.CHECK_UPGRADE_SUCCESS] = function(state, action) { +reducers[ACTIONS.CHECK_UPGRADE_SUCCESS] = function(state, action) { return Object.assign({}, state, { isUpgradeAvailable: action.data.upgradeAvailable, remoteVersion: action.data.remoteVersion, }); }; -reducers[types.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) { +reducers[ACTIONS.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) { return Object.assign({}, state, { checkUpgradeTimer: action.data.checkUpgradeTimer, }); }; -reducers[types.OPEN_MODAL] = function(state, action) { +reducers[ACTIONS.OPEN_MODAL] = function(state, action) { return Object.assign({}, state, { modal: action.data.modal, modalProps: action.data.modalProps || {}, }); }; -reducers[types.CLOSE_MODAL] = function(state, action) { +reducers[ACTIONS.CLOSE_MODAL] = function(state) { return Object.assign({}, state, { modal: undefined, modalProps: {}, }); }; -reducers[types.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) { +reducers[ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) { return Object.assign({}, state, { downloadProgress: action.data.percent, }); }; -reducers[types.SHOW_SNACKBAR] = function(state, action) { +reducers[ACTIONS.SHOW_SNACKBAR] = function(state, action) { const { message, linkText, linkTarget, isError } = action.data; const snackBar = Object.assign({}, state.snackBar); const snacks = Object.assign([], snackBar.snacks); @@ -165,7 +164,7 @@ reducers[types.SHOW_SNACKBAR] = function(state, action) { }); }; -reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) { +reducers[ACTIONS.REMOVE_SNACKBAR_SNACK] = function(state) { const snackBar = Object.assign({}, state.snackBar); const snacks = Object.assign([], snackBar.snacks); snacks.shift(); @@ -179,8 +178,8 @@ reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) { }); }; -reducers[types.DOWNLOADING_COMPLETED] = function(state, action) { - const badgeNumber = state.badgeNumber; +reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state) { + const { badgeNumber } = state; // Don't update the badge number if the window is focused if (win && win.isFocused()) return Object.assign({}, state); @@ -190,13 +189,13 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) { }); }; -reducers[types.WINDOW_FOCUSED] = function(state, action) { +reducers[ACTIONS.WINDOW_FOCUSED] = function(state) { return Object.assign({}, state, { badgeNumber: 0, }); }; -reducers[types.VOLUME_CHANGED] = function(state, action) { +reducers[ACTIONS.VOLUME_CHANGED] = function(state, action) { return Object.assign({}, state, { volume: action.data.volume, }); diff --git a/src/renderer/redux/reducers/availability.js b/src/renderer/redux/reducers/availability.js index 2c4a4dc93..48133ff50 100644 --- a/src/renderer/redux/reducers/availability.js +++ b/src/renderer/redux/reducers/availability.js @@ -1,9 +1,9 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_AVAILABILITY_STARTED] = function(state, action) { const { uri } = action.data; const newFetching = Object.assign({}, state.fetching); @@ -14,7 +14,7 @@ reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) { }); }; -reducers[types.FETCH_AVAILABILITY_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_AVAILABILITY_COMPLETED] = function(state, action) { const { uri, availability } = action.data; const newFetching = Object.assign({}, state.fetching); diff --git a/src/renderer/redux/reducers/claims.js b/src/renderer/redux/reducers/claims.js index 60f5e042b..6547dd5f4 100644 --- a/src/renderer/redux/reducers/claims.js +++ b/src/renderer/redux/reducers/claims.js @@ -1,15 +1,15 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) { +reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) { const { resolveInfo } = action.data; const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); - for (const [uri, { certificate, claim }] of Object.entries(resolveInfo)) { + Object.entries(resolveInfo).forEach(([uri, { certificate, claim }]) => { if (claim) { byId[claim.claim_id] = claim; byUri[uri] = claim.claim_id; @@ -25,7 +25,7 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) { } else { byUri[uri] = null; } - } + }); return Object.assign({}, state, { byId, @@ -33,37 +33,32 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) { }); }; -reducers[types.FETCH_CLAIM_LIST_MINE_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = function(state) { return Object.assign({}, state, { isFetchingClaimListMine: true, }); }; -reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) { const { claims } = action.data; - const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); const pendingById = Object.assign({}, state.pendingById); - const abandoningById = Object.assign({}, state.abandoningById); - claims - .filter(claim => claim.category && claim.category.match(/claim/)) - .forEach(claim => { - byId[claim.claim_id] = claim; + claims.filter(claim => claim.category && claim.category.match(/claim/)).forEach(claim => { + byId[claim.claim_id] = claim; - const pending = Object.values(pendingById).find( - pendingClaim => - pendingClaim.name == claim.name && - pendingClaim.channel_name == claim.channel_name - ); + const pending = Object.values(pendingById).find( + pendingClaim => + pendingClaim.name === claim.name && pendingClaim.channel_name === claim.channel_name + ); - if (pending) { - delete pendingById[pending.claim_id]; - } - }); + if (pending) { + delete pendingById[pending.claim_id]; + } + }); // Remove old timed out pending publishes - const old = Object.values(pendingById) + Object.values(pendingById) .filter(pendingClaim => Date.now() - pendingClaim.time >= 20 * 60 * 1000) .forEach(pendingClaim => { delete pendingById[pendingClaim.claim_id]; @@ -77,11 +72,11 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) { }); }; -reducers[types.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state) { return Object.assign({}, state, { fetchingMyChannels: true }); }; -reducers[types.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) { const { claims } = action.data; const myChannelClaims = new Set(state.myChannelClaims); const byId = Object.assign({}, state.byId); @@ -98,7 +93,7 @@ reducers[types.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) { }); }; -reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) { const { uri, page } = action.data; const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims); @@ -109,7 +104,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) { }); }; -reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { const { uri, claims, page } = action.data; const claimsByChannel = Object.assign({}, state.claimsByChannel); @@ -139,7 +134,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { }); }; -reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) { +reducers[ACTIONS.ABANDON_CLAIM_STARTED] = function(state, action) { const { claimId } = action.data; const abandoningById = Object.assign({}, state.abandoningById); @@ -150,7 +145,7 @@ reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) { }); }; -reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) { +reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = function(state, action) { const { claimId } = action.data; const byId = Object.assign({}, state.byId); const claimsByUri = Object.assign({}, state.claimsByUri); @@ -169,7 +164,7 @@ reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) { }); }; -reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) { +reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = function(state, action) { const { channelClaim } = action.data; const byId = Object.assign({}, state.byId); const myChannelClaims = new Set(state.myChannelClaims); diff --git a/src/renderer/redux/reducers/content.js b/src/renderer/redux/reducers/content.js index 9c3dabac5..b16c911b1 100644 --- a/src/renderer/redux/reducers/content.js +++ b/src/renderer/redux/reducers/content.js @@ -1,4 +1,4 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = { @@ -7,13 +7,13 @@ const defaultState = { channelClaimCounts: {}, }; -reducers[types.FETCH_FEATURED_CONTENT_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_FEATURED_CONTENT_STARTED] = function(state) { return Object.assign({}, state, { fetchingFeaturedContent: true, }); }; -reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) { const { uris, success } = action.data; return Object.assign({}, state, { @@ -23,42 +23,40 @@ reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) { }); }; -reducers[types.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) { - const { claimIds, success } = action.data; +reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) { + const { claimIds } = action.data; return Object.assign({}, state, { rewardedContentClaimIds: claimIds, }); }; -reducers[types.RESOLVE_URIS_STARTED] = function(state, action) { +reducers[ACTIONS.RESOLVE_URIS_STARTED] = function(state, action) { const { uris } = action.data; const oldResolving = state.resolvingUris || []; const newResolving = Object.assign([], oldResolving); - for (const uri of uris) { + uris.forEach(uri => { if (!newResolving.includes(uri)) { newResolving.push(uri); } - } + }); return Object.assign({}, state, { resolvingUris: newResolving, }); }; -reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) { +reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) { const { resolveInfo } = action.data; const channelClaimCounts = Object.assign({}, state.channelClaimCounts); - for (const [uri, { certificate, claims_in_channel }] of Object.entries( - resolveInfo - )) { - if (certificate && !isNaN(claims_in_channel)) { - channelClaimCounts[uri] = claims_in_channel; + Object.entries(resolveInfo).forEach(([uri, { certificate, claimsInChannel }]) => { + if (certificate && !Number.isNaN(claimsInChannel)) { + channelClaimCounts[uri] = claimsInChannel; } - } + }); return Object.assign({}, state, { channelClaimCounts, @@ -66,12 +64,12 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) { }); }; -reducers[types.SET_PLAYING_URI] = (state, action) => +reducers[ACTIONS.SET_PLAYING_URI] = (state, action) => Object.assign({}, state, { playingUri: action.data.uri, }); -reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) { const channelClaimCounts = Object.assign({}, state.channelClaimCounts); const { uri, totalClaims } = action.data; diff --git a/src/renderer/redux/reducers/cost_info.js b/src/renderer/redux/reducers/cost_info.js index 27e04f0a3..18c6214ac 100644 --- a/src/renderer/redux/reducers/cost_info.js +++ b/src/renderer/redux/reducers/cost_info.js @@ -1,9 +1,9 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[types.FETCH_COST_INFO_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_COST_INFO_STARTED] = function(state, action) { const { uri } = action.data; const newFetching = Object.assign({}, state.fetching); newFetching[uri] = true; @@ -13,7 +13,7 @@ reducers[types.FETCH_COST_INFO_STARTED] = function(state, action) { }); }; -reducers[types.FETCH_COST_INFO_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_COST_INFO_COMPLETED] = function(state, action) { const { uri, costInfo } = action.data; const newByUri = Object.assign({}, state.byUri); const newFetching = Object.assign({}, state.fetching); diff --git a/src/renderer/redux/reducers/file_info.js b/src/renderer/redux/reducers/file_info.js index d900a860f..25ae15546 100644 --- a/src/renderer/redux/reducers/file_info.js +++ b/src/renderer/redux/reducers/file_info.js @@ -1,16 +1,15 @@ -import * as types from "constants/action_types"; -import lbryuri from "lbryuri"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[types.FILE_LIST_STARTED] = function(state, action) { +reducers[ACTIONS.FILE_LIST_STARTED] = function(state) { return Object.assign({}, state, { isFetchingFileList: true, }); }; -reducers[types.FILE_LIST_SUCCEEDED] = function(state, action) { +reducers[ACTIONS.FILE_LIST_SUCCEEDED] = function(state, action) { const { fileInfos } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint); @@ -28,7 +27,7 @@ reducers[types.FILE_LIST_SUCCEEDED] = function(state, action) { }); }; -reducers[types.FETCH_FILE_INFO_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_FILE_INFO_STARTED] = function(state, action) { const { outpoint } = action.data; const newFetching = Object.assign({}, state.fetching); @@ -39,7 +38,7 @@ reducers[types.FETCH_FILE_INFO_STARTED] = function(state, action) { }); }; -reducers[types.FETCH_FILE_INFO_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = function(state, action) { const { fileInfo, outpoint } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -54,7 +53,7 @@ reducers[types.FETCH_FILE_INFO_COMPLETED] = function(state, action) { }); }; -reducers[types.DOWNLOADING_STARTED] = function(state, action) { +reducers[ACTIONS.DOWNLOADING_STARTED] = function(state, action) { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -72,8 +71,8 @@ reducers[types.DOWNLOADING_STARTED] = function(state, action) { }); }; -reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) { - const { uri, outpoint, fileInfo } = action.data; +reducers[ACTIONS.DOWNLOADING_PROGRESSED] = function(state, action) { + const { outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint); @@ -87,8 +86,8 @@ reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) { }); }; -reducers[types.DOWNLOADING_COMPLETED] = function(state, action) { - const { uri, outpoint, fileInfo } = action.data; +reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state, action) { + const { outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint); @@ -102,7 +101,7 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) { }); }; -reducers[types.FILE_DELETE] = function(state, action) { +reducers[ACTIONS.FILE_DELETE] = function(state, action) { const { outpoint } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -117,7 +116,7 @@ reducers[types.FILE_DELETE] = function(state, action) { }); }; -reducers[types.LOADING_VIDEO_STARTED] = function(state, action) { +reducers[ACTIONS.LOADING_VIDEO_STARTED] = function(state, action) { const { uri } = action.data; const newLoading = Object.assign({}, state.urisLoading); @@ -129,7 +128,7 @@ reducers[types.LOADING_VIDEO_STARTED] = function(state, action) { }); }; -reducers[types.LOADING_VIDEO_FAILED] = function(state, action) { +reducers[ACTIONS.LOADING_VIDEO_FAILED] = function(state, action) { const { uri } = action.data; const newLoading = Object.assign({}, state.urisLoading); @@ -141,13 +140,14 @@ reducers[types.LOADING_VIDEO_FAILED] = function(state, action) { }); }; -reducers[types.FETCH_DATE] = function(state, action) { +reducers[ACTIONS.FETCH_DATE] = function(state, action) { const { time } = action.data; if (time) { return Object.assign({}, state, { publishedDate: time, }); } + return null; }; export default function reducer(state = defaultState, action) { diff --git a/src/renderer/redux/reducers/navigation.js b/src/renderer/redux/reducers/navigation.js index 990657df7..581fd52d2 100644 --- a/src/renderer/redux/reducers/navigation.js +++ b/src/renderer/redux/reducers/navigation.js @@ -1,38 +1,36 @@ -import * as types from "constants/action_types"; -import { parseQueryParams } from "util/query_params"; +import * as ACTIONS from 'constants/action_types'; -const currentPath = () => { - const hash = document.location.hash; - if (hash !== "") return hash.replace(/^#/, ""); - return "/discover"; +const getCurrentPath = () => { + const { hash } = document.location; + if (hash !== '') return hash.replace(/^#/, ''); + return '/discover'; }; const reducers = {}; const defaultState = { - currentPath: currentPath(), - pathAfterAuth: "/discover", + currentPath: getCurrentPath(), + pathAfterAuth: '/discover', index: 0, stack: [], }; -reducers[types.DAEMON_READY] = function(state, action) { +reducers[ACTIONS.DAEMON_READY] = function(state) { const { currentPath } = state; - const params = parseQueryParams(currentPath.split("?")[1] || ""); return Object.assign({}, state, { stack: [{ path: currentPath, scrollY: 0 }], }); }; -reducers[types.CHANGE_AFTER_AUTH_PATH] = function(state, action) { +reducers[ACTIONS.CHANGE_AFTER_AUTH_PATH] = function(state, action) { return Object.assign({}, state, { pathAfterAuth: action.data.path, }); }; -reducers[types.HISTORY_NAVIGATE] = (state, action) => { +reducers[ACTIONS.HISTORY_NAVIGATE] = (state, action) => { const { stack, index } = state; - const { url: path, index: newIndex, scrollY } = action.data; + const { url: path, index: newIndex } = action.data; const newState = { currentPath: path, @@ -46,12 +44,11 @@ reducers[types.HISTORY_NAVIGATE] = (state, action) => { newState.index = newState.stack.length - 1; } - history.replaceState(null, null, `#${path}`); // this allows currentPath() to retain the URL on reload return Object.assign({}, state, newState); }; -reducers[types.WINDOW_SCROLLED] = (state, action) => { - const { stack, index } = state; +reducers[ACTIONS.WINDOW_SCROLLED] = (state, action) => { + const { index } = state; const { scrollY } = action.data; return Object.assign({}, state, { diff --git a/src/renderer/redux/reducers/rewards.js b/src/renderer/redux/reducers/rewards.js index 77d20064e..f9a108f12 100644 --- a/src/renderer/redux/reducers/rewards.js +++ b/src/renderer/redux/reducers/rewards.js @@ -1,4 +1,4 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = { @@ -9,17 +9,17 @@ const defaultState = { claimErrorsByType: {}, }; -reducers[types.FETCH_REWARDS_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_REWARDS_STARTED] = function(state) { return Object.assign({}, state, { fetching: true, }); }; -reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = function(state, action) { const { userRewards } = action.data; - let unclaimedRewards = {}, - claimedRewards = {}; + const unclaimedRewards = {}; + const claimedRewards = {}; userRewards.forEach(reward => { if (reward.transaction_id) { claimedRewards[reward.id] = reward; @@ -35,7 +35,7 @@ reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) { }); }; -function setClaimRewardState(state, reward, isClaiming, errorMessage = "") { +function setClaimRewardState(state, reward, isClaiming, errorMessage = '') { const newClaimPendingByType = Object.assign({}, state.claimPendingByType); const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType); if (isClaiming) { @@ -55,21 +55,17 @@ function setClaimRewardState(state, reward, isClaiming, errorMessage = "") { }); } -reducers[types.CLAIM_REWARD_STARTED] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_STARTED] = function(state, action) { const { reward } = action.data; - return setClaimRewardState(state, reward, true, ""); + return setClaimRewardState(state, reward, true, ''); }; -reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = function(state, action) { const { reward } = action.data; - const unclaimedRewardsByType = Object.assign( - {}, - state.unclaimedRewardsByType - ); + const unclaimedRewardsByType = Object.assign({}, state.unclaimedRewardsByType); const existingReward = unclaimedRewardsByType[reward.reward_type]; - delete state.unclaimedRewardsByType[reward.reward_type]; const newReward = Object.assign({}, reward, { reward_title: existingReward.reward_title, @@ -84,24 +80,19 @@ reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) { claimedRewardsById, }); - return setClaimRewardState(newState, newReward, false, ""); + return setClaimRewardState(newState, newReward, false, ''); }; -reducers[types.CLAIM_REWARD_FAILURE] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_FAILURE] = function(state, action) { const { reward, error } = action.data; - return setClaimRewardState(state, reward, false, error ? error.message : ""); + return setClaimRewardState(state, reward, false, error ? error.message : ''); }; -reducers[types.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) { const { reward } = action.data; - return setClaimRewardState( - state, - reward, - state.claimPendingByType[reward.reward_type], - "" - ); + return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], ''); }; export default function reducer(state = defaultState, action) { diff --git a/src/renderer/redux/reducers/search.js b/src/renderer/redux/reducers/search.js index c44c78cd2..00764c2b7 100644 --- a/src/renderer/redux/reducers/search.js +++ b/src/renderer/redux/reducers/search.js @@ -1,4 +1,4 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = { @@ -6,15 +6,13 @@ const defaultState = { searching: false, }; -reducers[types.SEARCH_STARTED] = function(state, action) { - const { query } = action.data; - +reducers[ACTIONS.SEARCH_STARTED] = function(state) { return Object.assign({}, state, { searching: true, }); }; -reducers[types.SEARCH_COMPLETED] = function(state, action) { +reducers[ACTIONS.SEARCH_COMPLETED] = function(state, action) { const { query, uris } = action.data; return Object.assign({}, state, { @@ -23,7 +21,7 @@ reducers[types.SEARCH_COMPLETED] = function(state, action) { }); }; -reducers[types.SEARCH_CANCELLED] = function(state, action) { +reducers[ACTIONS.SEARCH_CANCELLED] = function(state) { return Object.assign({}, state, { searching: false, }); diff --git a/src/renderer/redux/reducers/settings.js b/src/renderer/redux/reducers/settings.js index 28413c504..b3cf5794a 100644 --- a/src/renderer/redux/reducers/settings.js +++ b/src/renderer/redux/reducers/settings.js @@ -1,6 +1,6 @@ -import * as types from "constants/action_types"; -import * as settings from "constants/settings"; -import LANGUAGES from "constants/languages"; +import * as ACTIONS from 'constants/action_types'; +import * as SETTINGS from 'constants/settings'; +import LANGUAGES from 'constants/languages'; function getLocalStorageSetting(setting, fallback) { const localStorageVal = localStorage.getItem(`setting_${setting}`); @@ -10,38 +10,30 @@ function getLocalStorageSetting(setting, fallback) { const reducers = {}; const defaultState = { clientSettings: { - instantPurchaseEnabled: getLocalStorageSetting( - settings.INSTANT_PURCHASE_ENABLED, - false - ), - instantPurchaseMax: getLocalStorageSetting(settings.INSTANT_PURCHASE_MAX, { - currency: "LBC", + instantPurchaseEnabled: getLocalStorageSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, false), + instantPurchaseMax: getLocalStorageSetting(SETTINGS.INSTANT_PURCHASE_MAX, { + currency: 'LBC', amount: 0.1, }), - showNsfw: getLocalStorageSetting(settings.SHOW_NSFW, false), - showUnavailable: getLocalStorageSetting(settings.SHOW_UNAVAILABLE, true), - welcome_acknowledged: getLocalStorageSetting( - settings.NEW_USER_ACKNOWLEDGED, - false - ), - email_collection_acknowledged: getLocalStorageSetting( - settings.EMAIL_COLLECTION_ACKNOWLEDGED - ), + showNsfw: getLocalStorageSetting(SETTINGS.SHOW_NSFW, false), + showUnavailable: getLocalStorageSetting(SETTINGS.SHOW_UNAVAILABLE, true), + welcome_acknowledged: getLocalStorageSetting(SETTINGS.NEW_USER_ACKNOWLEDGED, false), + email_collection_acknowledged: getLocalStorageSetting(SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED), credit_required_acknowledged: false, // this needs to be re-acknowledged every run - language: getLocalStorageSetting(settings.LANGUAGE, "en"), - theme: getLocalStorageSetting(settings.THEME, "light"), - themes: getLocalStorageSetting(settings.THEMES, []), + language: getLocalStorageSetting(SETTINGS.LANGUAGE, 'en'), + theme: getLocalStorageSetting(SETTINGS.THEME, 'light'), + themes: getLocalStorageSetting(SETTINGS.THEMES, []), }, languages: {}, }; -reducers[types.DAEMON_SETTINGS_RECEIVED] = function(state, action) { +reducers[ACTIONS.DAEMON_SETTINGS_RECEIVED] = function(state, action) { return Object.assign({}, state, { daemonSettings: action.data.settings, }); }; -reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) { +reducers[ACTIONS.CLIENT_SETTING_CHANGED] = function(state, action) { const { key, value } = action.data; const clientSettings = Object.assign({}, state.clientSettings); @@ -55,16 +47,14 @@ reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) { }); }; -reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) { +reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) { const languages = Object.assign({}, state.languages); - const language = action.data.language; + const { language } = action.data; const langCode = language.substring(0, 2); if (LANGUAGES[langCode]) { - languages[language] = `${LANGUAGES[langCode][0]} (${ - LANGUAGES[langCode][1] - })`; + languages[language] = `${LANGUAGES[langCode][0]} (${LANGUAGES[langCode][1]})`; } else { languages[langCode] = langCode; } @@ -72,7 +62,7 @@ reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) { return Object.assign({}, state, { languages }); }; -reducers[types.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) { +reducers[ACTIONS.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) { const languages = Object.assign({}, state.languages); delete languages[action.data.language]; return Object.assign({}, state, { languages }); diff --git a/src/renderer/redux/reducers/shape_shift.js b/src/renderer/redux/reducers/shape_shift.js index 71b59addd..81b78fe34 100644 --- a/src/renderer/redux/reducers/shape_shift.js +++ b/src/renderer/redux/reducers/shape_shift.js @@ -1,7 +1,7 @@ // @flow -import { handleActions } from "util/redux-utils"; -import * as actions from "constants/action_types"; -import * as statuses from "constants/shape_shift"; +import handleActions from 'util/redux-utils'; +import * as ACTIONS from 'constants/action_types'; +import * as STATUSES from 'constants/shape_shift'; export type ShapeShiftState = { loading: boolean, @@ -24,40 +24,6 @@ export type ShapeShiftState = { shapeShiftRate: ?number, }; -// All ShapeShift actions that will have some payload -export type GetSupportedCoinsSuccess = { - type: actions.GET_SUPPORTED_COINS_SUCCESS, - data: Array, -}; -export type GetCoinStatsStart = { - type: actions.GET_SUPPORTED_COINS_SUCCESS, - data: string, -}; -export type GetCoinStatsSuccess = { - type: actions.GET_COIN_STATS_SUCCESS, - data: ShapeShiftMarketInfo, -}; -export type GetCoinStatsFail = { - type: actions.GET_COIN_STATS_FAIL, - data: string, -}; -export type PrepareShapeShiftSuccess = { - type: actions.PREPARE_SHAPE_SHIFT_SUCCESS, - data: ActiveShiftInfo, -}; -export type PrepareShapeShiftFail = { - type: actions.PREPARE_SHAPE_SHIFT_FAIL, - data: ShapeShiftErrorResponse, -}; -export type GetActiveShiftSuccess = { - type: actions.GET_ACTIVE_SHIFT_SUCCESS, - data: string, -}; -export type GetActiveShiftFail = { - type: actions.GET_ACTIVE_SHIFT_FAIL, - data: ShapeShiftErrorResponse, -}; - // ShapeShift sub-types // Defined for actions that contain an object in the payload type ShapeShiftMarketInfo = { @@ -78,6 +44,40 @@ type ShapeShiftErrorResponse = { message: string, }; +// All ShapeShift actions that will have some payload +export type GetSupportedCoinsSuccess = { + type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS, + data: Array, +}; +export type GetCoinStatsStart = { + type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS, + data: string, +}; +export type GetCoinStatsSuccess = { + type: ACTIONS.GET_COIN_STATS_SUCCESS, + data: ShapeShiftMarketInfo, +}; +export type GetCoinStatsFail = { + type: ACTIONS.GET_COIN_STATS_FAIL, + data: string, +}; +export type PrepareShapeShiftSuccess = { + type: ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS, + data: ActiveShiftInfo, +}; +export type PrepareShapeShiftFail = { + type: ACTIONS.PREPARE_SHAPE_SHIFT_FAIL, + data: ShapeShiftErrorResponse, +}; +export type GetActiveShiftSuccess = { + type: ACTIONS.GET_ACTIVE_SHIFT_SUCCESS, + data: string, +}; +export type GetActiveShiftFail = { + type: ACTIONS.GET_ACTIVE_SHIFT_FAIL, + data: ShapeShiftErrorResponse, +}; + const defaultState: ShapeShiftState = { loading: true, updating: false, @@ -98,14 +98,12 @@ const defaultState: ShapeShiftState = { export default handleActions( { - [actions.GET_SUPPORTED_COINS_START]: ( - state: ShapeShiftState - ): ShapeShiftState => ({ + [ACTIONS.GET_SUPPORTED_COINS_START]: (state: ShapeShiftState): ShapeShiftState => ({ ...state, loading: true, error: undefined, }), - [actions.GET_SUPPORTED_COINS_SUCCESS]: ( + [ACTIONS.GET_SUPPORTED_COINS_SUCCESS]: ( state: ShapeShiftState, action: GetSupportedCoinsSuccess ): ShapeShiftState => { @@ -116,15 +114,13 @@ export default handleActions( shiftSupportedCoins, }; }, - [actions.GET_SUPPORTED_COINS_FAIL]: ( - state: ShapeShiftState - ): ShapeShiftState => ({ + [ACTIONS.GET_SUPPORTED_COINS_FAIL]: (state: ShapeShiftState): ShapeShiftState => ({ ...state, loading: false, - error: "Error getting available coins", + error: 'Error getting available coins', }), - [actions.GET_COIN_STATS_START]: ( + [ACTIONS.GET_COIN_STATS_START]: ( state: ShapeShiftState, action: GetCoinStatsStart ): ShapeShiftState => { @@ -135,7 +131,7 @@ export default handleActions( originCoin: coin, }; }, - [actions.GET_COIN_STATS_SUCCESS]: ( + [ACTIONS.GET_COIN_STATS_SUCCESS]: ( state: ShapeShiftState, action: GetCoinStatsSuccess ): ShapeShiftState => { @@ -148,14 +144,12 @@ export default handleActions( originCoinDepositMax: marketInfo.limit, // this will come in scientific notation // toFixed shows the real number, then regex to remove trailing zeros - originCoinDepositMin: marketInfo.minimum - .toFixed(10) - .replace(/\.?0+$/, ""), + originCoinDepositMin: marketInfo.minimum.toFixed(10).replace(/\.?0+$/, ''), originCoinDepositFee: marketInfo.minerFee, shapeShiftRate: marketInfo.rate, }; }, - [actions.GET_COIN_STATS_FAIL]: ( + [ACTIONS.GET_COIN_STATS_FAIL]: ( state: ShapeShiftState, action: GetCoinStatsFail ): ShapeShiftState => { @@ -167,13 +161,11 @@ export default handleActions( }; }, - [actions.PREPARE_SHAPE_SHIFT_START]: ( - state: ShapeShiftState - ): ShapeShiftState => ({ + [ACTIONS.PREPARE_SHAPE_SHIFT_START]: (state: ShapeShiftState): ShapeShiftState => ({ ...state, error: undefined, }), - [actions.PREPARE_SHAPE_SHIFT_SUCCESS]: ( + [ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS]: ( state: ShapeShiftState, action: PrepareShapeShiftSuccess ) => { @@ -185,13 +177,10 @@ export default handleActions( shiftCoinType: activeShiftInfo.depositType, shiftReturnAddress: activeShiftInfo.returnAddress, shiftOrderId: activeShiftInfo.orderId, - shiftState: statuses.NO_DEPOSITS, + shiftState: STATUSES.NO_DEPOSITS, }; }, - [actions.PREPARE_SHAPE_SHIFT_FAIL]: ( - state: ShapeShiftState, - action: PrepareShapeShiftFail - ) => { + [ACTIONS.PREPARE_SHAPE_SHIFT_FAIL]: (state: ShapeShiftState, action: PrepareShapeShiftFail) => { const error: ShapeShiftErrorResponse = action.data; return { ...state, @@ -199,7 +188,7 @@ export default handleActions( }; }, - [actions.CLEAR_SHAPE_SHIFT]: (state: ShapeShiftState): ShapeShiftState => ({ + [ACTIONS.CLEAR_SHAPE_SHIFT]: (state: ShapeShiftState): ShapeShiftState => ({ ...state, loading: false, updating: false, @@ -211,14 +200,12 @@ export default handleActions( originCoin: state.shiftSupportedCoins[0], }), - [actions.GET_ACTIVE_SHIFT_START]: ( - state: ShapeShiftState - ): ShapeShiftState => ({ + [ACTIONS.GET_ACTIVE_SHIFT_START]: (state: ShapeShiftState): ShapeShiftState => ({ ...state, error: undefined, updating: true, }), - [actions.GET_ACTIVE_SHIFT_SUCCESS]: ( + [ACTIONS.GET_ACTIVE_SHIFT_SUCCESS]: ( state: ShapeShiftState, action: GetActiveShiftSuccess ): ShapeShiftState => { @@ -229,7 +216,7 @@ export default handleActions( shiftState: status, }; }, - [actions.GET_ACTIVE_SHIFT_FAIL]: ( + [ACTIONS.GET_ACTIVE_SHIFT_FAIL]: ( state: ShapeShiftState, action: GetActiveShiftFail ): ShapeShiftState => { diff --git a/src/renderer/redux/reducers/subscriptions.js b/src/renderer/redux/reducers/subscriptions.js index f0de6819c..2e93f8dc6 100644 --- a/src/renderer/redux/reducers/subscriptions.js +++ b/src/renderer/redux/reducers/subscriptions.js @@ -1,6 +1,11 @@ // @flow -import * as actions from "constants/action_types"; -import { handleActions } from "util/redux-utils"; +import * as ACTIONS from 'constants/action_types'; +import handleActions from 'util/redux-utils'; + +export type Subscription = { + channelName: string, + uri: string, +}; // Subscription redux types export type SubscriptionState = { @@ -8,30 +13,22 @@ export type SubscriptionState = { hasFetchedSubscriptions: boolean, }; -export type Subscription = { - channelName: string, - uri: string, -}; - // Subscription action types type doChannelSubscribe = { - type: actions.CHANNEL_SUBSCRIBE, + type: ACTIONS.CHANNEL_SUBSCRIBE, data: Subscription, }; type doChannelUnsubscribe = { - type: actions.CHANNEL_UNSUBSCRIBE, + type: ACTIONS.CHANNEL_UNSUBSCRIBE, data: Subscription, }; type HasFetchedSubscriptions = { - type: actions.HAS_FETCHED_SUBSCRIPTIONS, + type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS, }; -export type Action = - | doChannelSubscribe - | doChannelUnsubscribe - | HasFetchedSubscriptions; +export type Action = doChannelSubscribe | doChannelUnsubscribe | HasFetchedSubscriptions; export type Dispatch = (action: Action) => any; const defaultState = { @@ -41,7 +38,7 @@ const defaultState = { export default handleActions( { - [actions.CHANNEL_SUBSCRIBE]: ( + [ACTIONS.CHANNEL_SUBSCRIBE]: ( state: SubscriptionState, action: doChannelSubscribe ): SubscriptionState => { @@ -54,7 +51,7 @@ export default handleActions( subscriptions: newSubscriptions, }; }, - [actions.CHANNEL_UNSUBSCRIBE]: ( + [ACTIONS.CHANNEL_UNSUBSCRIBE]: ( state: SubscriptionState, action: doChannelUnsubscribe ): SubscriptionState => { @@ -62,20 +59,14 @@ export default handleActions( const newSubscriptions = state.subscriptions .slice() - .filter( - subscription => - subscription.channelName !== subscriptionToRemove.channelName - ); + .filter(subscription => subscription.channelName !== subscriptionToRemove.channelName); return { ...state, subscriptions: newSubscriptions, }; }, - [actions.HAS_FETCHED_SUBSCRIPTIONS]: ( - state: SubscriptionState, - action: HasFetchedSubscriptions - ): SubscriptionState => ({ + [ACTIONS.HAS_FETCHED_SUBSCRIPTIONS]: (state: SubscriptionState): SubscriptionState => ({ ...state, hasFetchedSubscriptions: true, }), diff --git a/src/renderer/redux/reducers/user.js b/src/renderer/redux/reducers/user.js index ef4bd6f87..be8c5f1c7 100644 --- a/src/renderer/redux/reducers/user.js +++ b/src/renderer/redux/reducers/user.js @@ -1,4 +1,4 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; @@ -6,9 +6,9 @@ const defaultState = { authenticationIsPending: false, userIsPending: false, emailNewIsPending: false, - emailNewErrorMessage: "", - emailToVerify: "", - inviteNewErrorMessage: "", + emailNewErrorMessage: '', + emailToVerify: '', + inviteNewErrorMessage: '', inviteNewIsPending: false, inviteStatusIsPending: false, invitesRemaining: undefined, @@ -16,7 +16,7 @@ const defaultState = { user: undefined, }; -reducers[types.AUTHENTICATION_STARTED] = function(state, action) { +reducers[ACTIONS.AUTHENTICATION_STARTED] = function(state) { return Object.assign({}, state, { authenticationIsPending: true, userIsPending: true, @@ -24,7 +24,7 @@ reducers[types.AUTHENTICATION_STARTED] = function(state, action) { }); }; -reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) { +reducers[ACTIONS.AUTHENTICATION_SUCCESS] = function(state, action) { return Object.assign({}, state, { authenticationIsPending: false, userIsPending: false, @@ -32,7 +32,7 @@ reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) { }); }; -reducers[types.AUTHENTICATION_FAILURE] = function(state, action) { +reducers[ACTIONS.AUTHENTICATION_FAILURE] = function(state) { return Object.assign({}, state, { authenticationIsPending: false, userIsPending: false, @@ -40,35 +40,35 @@ reducers[types.AUTHENTICATION_FAILURE] = function(state, action) { }); }; -reducers[types.USER_FETCH_STARTED] = function(state, action) { +reducers[ACTIONS.USER_FETCH_STARTED] = function(state) { return Object.assign({}, state, { userIsPending: true, user: defaultState.user, }); }; -reducers[types.USER_FETCH_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_FETCH_SUCCESS] = function(state, action) { return Object.assign({}, state, { userIsPending: false, user: action.data.user, }); }; -reducers[types.USER_FETCH_FAILURE] = function(state, action) { +reducers[ACTIONS.USER_FETCH_FAILURE] = function(state) { return Object.assign({}, state, { userIsPending: true, user: null, }); }; -reducers[types.USER_EMAIL_NEW_STARTED] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_NEW_STARTED] = function(state) { return Object.assign({}, state, { emailNewIsPending: true, - emailNewErrorMessage: "", + emailNewErrorMessage: '', }); }; -reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = function(state, action) { const user = Object.assign({}, state.user); user.primary_email = action.data.email; return Object.assign({}, state, { @@ -78,68 +78,67 @@ reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) { }); }; -reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) { - const user = Object.assign({}, state.user); +reducers[ACTIONS.USER_EMAIL_NEW_EXISTS] = function(state, action) { return Object.assign({}, state, { emailToVerify: action.data.email, emailNewIsPending: false, }); }; -reducers[types.USER_EMAIL_NEW_FAILURE] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_NEW_FAILURE] = function(state, action) { return Object.assign({}, state, { emailNewIsPending: false, emailNewErrorMessage: action.data.error, }); }; -reducers[types.USER_EMAIL_VERIFY_STARTED] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_VERIFY_STARTED] = function(state) { return Object.assign({}, state, { emailVerifyIsPending: true, - emailVerifyErrorMessage: "", + emailVerifyErrorMessage: '', }); }; -reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { const user = Object.assign({}, state.user); user.primary_email = action.data.email; return Object.assign({}, state, { - emailToVerify: "", + emailToVerify: '', emailVerifyIsPending: false, user, }); }; -reducers[types.USER_EMAIL_VERIFY_FAILURE] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_VERIFY_FAILURE] = function(state, action) { return Object.assign({}, state, { emailVerifyIsPending: false, emailVerifyErrorMessage: action.data.error, }); }; -reducers[types.USER_IDENTITY_VERIFY_STARTED] = function(state, action) { +reducers[ACTIONS.USER_IDENTITY_VERIFY_STARTED] = function(state) { return Object.assign({}, state, { identityVerifyIsPending: true, - identityVerifyErrorMessage: "", + identityVerifyErrorMessage: '', }); }; -reducers[types.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) { return Object.assign({}, state, { identityVerifyIsPending: false, - identityVerifyErrorMessage: "", + identityVerifyErrorMessage: '', user: action.data.user, }); }; -reducers[types.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) { +reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) { return Object.assign({}, state, { identityVerifyIsPending: false, identityVerifyErrorMessage: action.data.error, }); }; -reducers[types.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) { +reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) { const { token } = action.data; return Object.assign({}, state, { @@ -147,13 +146,13 @@ reducers[types.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) { }); }; -reducers[types.USER_INVITE_STATUS_FETCH_STARTED] = function(state, action) { +reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = function(state) { return Object.assign({}, state, { inviteStatusIsPending: true, }); }; -reducers[types.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) { return Object.assign({}, state, { inviteStatusIsPending: false, invitesRemaining: action.data.invitesRemaining, @@ -161,28 +160,28 @@ reducers[types.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) { }); }; -reducers[types.USER_INVITE_NEW_STARTED] = function(state, action) { +reducers[ACTIONS.USER_INVITE_NEW_STARTED] = function(state) { return Object.assign({}, state, { inviteNewIsPending: true, - inviteNewErrorMessage: "", + inviteNewErrorMessage: '', }); }; -reducers[types.USER_INVITE_NEW_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_INVITE_NEW_SUCCESS] = function(state) { return Object.assign({}, state, { inviteNewIsPending: false, - inviteNewErrorMessage: "", + inviteNewErrorMessage: '', }); }; -reducers[types.USER_INVITE_NEW_FAILURE] = function(state, action) { +reducers[ACTIONS.USER_INVITE_NEW_FAILURE] = function(state, action) { return Object.assign({}, state, { inviteNewIsPending: false, inviteNewErrorMessage: action.data.error.message, }); }; -reducers[types.USER_INVITE_STATUS_FETCH_FAILURE] = function(state, action) { +reducers[ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE] = function(state) { return Object.assign({}, state, { inviteStatusIsPending: false, invitesRemaining: null, diff --git a/src/renderer/redux/reducers/wallet.js b/src/renderer/redux/reducers/wallet.js index 233bcea25..403c57486 100644 --- a/src/renderer/redux/reducers/wallet.js +++ b/src/renderer/redux/reducers/wallet.js @@ -1,7 +1,7 @@ -import * as types from "constants/action_types"; +import * as ACTIONS from 'constants/action_types'; const reducers = {}; -const address = localStorage.getItem("receiveAddress"); +const receiveAddress = localStorage.getItem('receiveAddress'); const buildDraftTransaction = () => ({ amount: undefined, address: undefined, @@ -12,19 +12,19 @@ const defaultState = { blocks: {}, transactions: {}, fetchingTransactions: false, - receiveAddress: address, + receiveAddress, gettingNewAddress: false, draftTransaction: buildDraftTransaction(), sendingSupport: false, }; -reducers[types.FETCH_TRANSACTIONS_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_TRANSACTIONS_STARTED] = function(state) { return Object.assign({}, state, { fetchingTransactions: true, }); }; -reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { const byId = Object.assign({}, state.transactions); const { transactions } = action.data; @@ -39,41 +39,41 @@ reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { }); }; -reducers[types.GET_NEW_ADDRESS_STARTED] = function(state, action) { +reducers[ACTIONS.GET_NEW_ADDRESS_STARTED] = function(state) { return Object.assign({}, state, { gettingNewAddress: true, }); }; -reducers[types.GET_NEW_ADDRESS_COMPLETED] = function(state, action) { +reducers[ACTIONS.GET_NEW_ADDRESS_COMPLETED] = function(state, action) { const { address } = action.data; - localStorage.setItem("receiveAddress", address); + localStorage.setItem('receiveAddress', address); return Object.assign({}, state, { gettingNewAddress: false, receiveAddress: address, }); }; -reducers[types.UPDATE_BALANCE] = function(state, action) { +reducers[ACTIONS.UPDATE_BALANCE] = function(state, action) { return Object.assign({}, state, { balance: action.data.balance, }); }; -reducers[types.CHECK_ADDRESS_IS_MINE_STARTED] = function(state, action) { +reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED] = function(state) { return Object.assign({}, state, { checkingAddressOwnership: true, }); }; -reducers[types.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state, action) { +reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state) { return Object.assign({}, state, { checkingAddressOwnership: false, }); }; -reducers[types.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) { +reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) { const oldDraft = state.draftTransaction; const newDraft = Object.assign({}, oldDraft, { amount: parseFloat(action.data.amount), @@ -84,7 +84,7 @@ reducers[types.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) { }); }; -reducers[types.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) { +reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) { const oldDraft = state.draftTransaction; const newDraft = Object.assign({}, oldDraft, { address: action.data.address, @@ -95,7 +95,7 @@ reducers[types.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) { }); }; -reducers[types.SEND_TRANSACTION_STARTED] = function(state, action) { +reducers[ACTIONS.SEND_TRANSACTION_STARTED] = function(state) { const newDraftTransaction = Object.assign({}, state.draftTransaction, { sending: true, }); @@ -105,13 +105,13 @@ reducers[types.SEND_TRANSACTION_STARTED] = function(state, action) { }); }; -reducers[types.SEND_TRANSACTION_COMPLETED] = function(state, action) { +reducers[ACTIONS.SEND_TRANSACTION_COMPLETED] = function(state) { return Object.assign({}, state, { draftTransaction: buildDraftTransaction(), }); }; -reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) { +reducers[ACTIONS.SEND_TRANSACTION_FAILED] = function(state, action) { const newDraftTransaction = Object.assign({}, state.draftTransaction, { sending: false, error: action.data.error, @@ -122,28 +122,28 @@ reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) { }); }; -reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { +reducers[ACTIONS.SUPPORT_TRANSACTION_STARTED] = function(state) { return Object.assign({}, state, { sendingSupport: true, }); }; -reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { +reducers[ACTIONS.SUPPORT_TRANSACTION_COMPLETED] = function(state) { return Object.assign({}, state, { sendingSupport: false, }); }; -reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { +reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = function(state, action) { return Object.assign({}, state, { error: action.data.error, sendingSupport: false, }); }; -reducers[types.FETCH_BLOCK_SUCCESS] = (state, action) => { - const { block, block: { height } } = action.data, - blocks = Object.assign({}, state.blocks); +reducers[ACTIONS.FETCH_BLOCK_SUCCESS] = (state, action) => { + const { block, block: { height } } = action.data; + const blocks = Object.assign({}, state.blocks); blocks[height] = block; diff --git a/src/renderer/redux/selectors/app.js b/src/renderer/redux/selectors/app.js index 24c2f2b95..7a43f7fb3 100644 --- a/src/renderer/redux/selectors/app.js +++ b/src/renderer/redux/selectors/app.js @@ -1,32 +1,26 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; -export const _selectState = state => state.app || {}; +export const selectState = state => state.app || {}; -export const selectPlatform = createSelector( - _selectState, - state => state.platform -); +export const selectPlatform = createSelector(selectState, state => state.platform); export const selectUpdateUrl = createSelector(selectPlatform, platform => { switch (platform) { - case "darwin": - return "https://lbry.io/get/lbry.dmg"; - case "linux": - return "https://lbry.io/get/lbry.deb"; - case "win32": - return "https://lbry.io/get/lbry.exe"; + case 'darwin': + return 'https://lbry.io/get/lbry.dmg'; + case 'linux': + return 'https://lbry.io/get/lbry.deb'; + case 'win32': + return 'https://lbry.io/get/lbry.exe'; default: - throw "Unknown platform"; + throw Error('Unknown platform'); } }); -export const selectRemoteVersion = createSelector( - _selectState, - state => state.remoteVersion -); +export const selectRemoteVersion = createSelector(selectState, state => state.remoteVersion); export const selectIsUpgradeAvailable = createSelector( - _selectState, + selectState, state => state.isUpgradeAvailable ); @@ -35,81 +29,54 @@ export const selectUpgradeFilename = createSelector( selectRemoteVersion, (platform, version) => { switch (platform) { - case "darwin": + case 'darwin': return `LBRY_${version}.dmg`; - case "linux": + case 'linux': return `LBRY_${version}_amd64.deb`; - case "win32": + case 'win32': return `LBRY_${version}.exe`; default: - throw "Unknown platform"; + throw Error('Unknown platform'); } } ); -export const selectCurrentModal = createSelector( - _selectState, - state => state.modal -); +export const selectCurrentModal = createSelector(selectState, state => state.modal); -export const selectDownloadProgress = createSelector( - _selectState, - state => state.downloadProgress -); +export const selectDownloadProgress = createSelector(selectState, state => state.downloadProgress); export const selectDownloadComplete = createSelector( - _selectState, + selectState, state => state.upgradeDownloadCompleted ); -export const selectIsUpgradeSkipped = createSelector( - _selectState, - state => state.isUpgradeSkipped -); +export const selectIsUpgradeSkipped = createSelector(selectState, state => state.isUpgradeSkipped); -export const selectUpgradeDownloadPath = createSelector( - _selectState, - state => state.downloadPath -); +export const selectUpgradeDownloadPath = createSelector(selectState, state => state.downloadPath); -export const selectUpgradeDownloadItem = createSelector( - _selectState, - state => state.downloadItem -); +export const selectUpgradeDownloadItem = createSelector(selectState, state => state.downloadItem); -export const selectModalProps = createSelector( - _selectState, - state => state.modalProps -); +export const selectModalProps = createSelector(selectState, state => state.modalProps); -export const selectDaemonReady = createSelector( - _selectState, - state => state.daemonReady -); +export const selectDaemonReady = createSelector(selectState, state => state.daemonReady); export const selectDaemonVersionMatched = createSelector( - _selectState, + selectState, state => state.daemonVersionMatched ); -export const selectSnackBar = createSelector( - _selectState, - state => state.snackBar || {} -); +export const selectSnackBar = createSelector(selectState, state => state.snackBar || {}); export const selectSnackBarSnacks = createSelector( selectSnackBar, snackBar => snackBar.snacks || [] ); -export const selectBadgeNumber = createSelector( - _selectState, - state => state.badgeNumber -); +export const selectBadgeNumber = createSelector(selectState, state => state.badgeNumber); export const selectCurrentLanguage = createSelector( - _selectState, - () => app.i18n.getLocale() || "en" + selectState, + () => app.i18n.getLocale() || 'en' ); -export const selectVolume = createSelector(_selectState, state => state.volume); +export const selectVolume = createSelector(selectState, state => state.volume); diff --git a/src/renderer/redux/selectors/availability.js b/src/renderer/redux/selectors/availability.js index 679f25ca0..afa7ac7f6 100644 --- a/src/renderer/redux/selectors/availability.js +++ b/src/renderer/redux/selectors/availability.js @@ -1,22 +1,7 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; -const _selectState = state => state.availability; +const selectState = state => state.availability; -export const selectAvailabilityByUri = createSelector( - _selectState, - state => state.byUri || {} -); +const selectFetchingAvailability = createSelector(selectState, state => state.fetching || {}); -export const makeSelectIsAvailableForUri = uri => - createSelector( - selectAvailabilityByUri, - byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0) - ); - -export const selectFetchingAvailability = createSelector( - _selectState, - state => state.fetching || {} -); - -export const makeSelectFetchingAvailabilityForUri = uri => - createSelector(selectFetchingAvailability, byUri => byUri && byUri[uri]); +export { selectFetchingAvailability as default }; diff --git a/src/renderer/redux/selectors/claims.js b/src/renderer/redux/selectors/claims.js index 3fc571aa0..b0a62174a 100644 --- a/src/renderer/redux/selectors/claims.js +++ b/src/renderer/redux/selectors/claims.js @@ -1,77 +1,79 @@ -import { createSelector } from "reselect"; -import lbryuri from "lbryuri"; -import { makeSelectCurrentParam } from "./navigation"; +import { createSelector } from 'reselect'; +import Lbryuri from 'lbryuri'; +import { makeSelectCurrentParam } from 'redux/selectors/navigation'; -const _selectState = state => state.claims || {}; +const selectState = state => state.claims || {}; -export const selectClaimsById = createSelector( - _selectState, - state => state.byId || {} -); +export const selectClaimsById = createSelector(selectState, state => state.byId || {}); -export const selectClaimsByUri = createSelector( - _selectState, - selectClaimsById, - (state, byId) => { - const byUri = state.claimsByUri || {}; - const claims = {}; +export const selectClaimsByUri = createSelector(selectState, selectClaimsById, (state, byId) => { + const byUri = state.claimsByUri || {}; + const claims = {}; - Object.keys(byUri).forEach(uri => { - const claimId = byUri[uri]; + Object.keys(byUri).forEach(uri => { + const claimId = byUri[uri]; - // NOTE returning a null claim allows us to differentiate between an - // undefined (never fetched claim) and one which just doesn't exist. Not - // the cleanest solution but couldn't think of anything better right now - if (claimId === null) { - claims[uri] = null; - } else { - const claim = byId[claimId]; + // NOTE returning a null claim allows us to differentiate between an + // undefined (never fetched claim) and one which just doesn't exist. Not + // the cleanest solution but couldn't think of anything better right now + if (claimId === null) { + claims[uri] = null; + } else { + const claim = byId[claimId]; - claims[uri] = claim; - } - }); + claims[uri] = claim; + } + }); - return claims; - } -); + return claims; +}); export const selectAllClaimsByChannel = createSelector( - _selectState, + selectState, state => state.claimsByChannel || {} ); export const makeSelectClaimForUri = uri => - createSelector( - selectClaimsByUri, - claims => claims && claims[lbryuri.normalize(uri)] - ); + createSelector(selectClaimsByUri, claims => claims && claims[Lbryuri.normalize(uri)]); + +export const selectMyClaimsRaw = createSelector(selectState, state => state.myClaims); + +export const selectAbandoningIds = createSelector(selectState, state => + Object.keys(state.abandoningById || {}) +); + +export const selectMyActiveClaims = createSelector( + selectMyClaimsRaw, + selectAbandoningIds, + (claims, abandoningIds) => + new Set( + claims && + claims + .map(claim => claim.claim_id) + .filter(claimId => Object.keys(abandoningIds).indexOf(claimId) === -1) + ) +); export const makeSelectClaimIsMine = rawUri => { - const uri = lbryuri.normalize(rawUri); + const uri = Lbryuri.normalize(rawUri); return createSelector( selectClaimsByUri, selectMyActiveClaims, (claims, myClaims) => - claims && - claims[uri] && - claims[uri].claim_id && - myClaims.has(claims[uri].claim_id) + claims && claims[uri] && claims[uri].claim_id && myClaims.has(claims[uri].claim_id) ); }; export const selectAllFetchingChannelClaims = createSelector( - _selectState, + selectState, state => state.fetchingChannelClaims || {} ); export const makeSelectFetchingChannelClaims = uri => - createSelector( - selectAllFetchingChannelClaims, - fetching => fetching && fetching[uri] - ); + createSelector(selectAllFetchingChannelClaims, fetching => fetching && fetching[uri]); export const makeSelectClaimsInChannelForCurrentPage = uri => { - const pageSelector = makeSelectCurrentParam("page"); + const pageSelector = makeSelectCurrentParam('page'); return createSelector( selectClaimsById, @@ -90,53 +92,27 @@ export const makeSelectClaimsInChannelForCurrentPage = uri => { export const makeSelectMetadataForUri = uri => createSelector(makeSelectClaimForUri(uri), claim => { - const metadata = - claim && claim.value && claim.value.stream && claim.value.stream.metadata; + const metadata = claim && claim.value && claim.value.stream && claim.value.stream.metadata; const value = metadata || (claim === undefined ? undefined : null); return value; }); export const makeSelectTitleForUri = uri => - createSelector( - makeSelectMetadataForUri(uri), - metadata => metadata && metadata.title - ); + createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title); export const makeSelectContentTypeForUri = uri => createSelector(makeSelectClaimForUri(uri), claim => { - const source = - claim && claim.value && claim.value.stream && claim.value.stream.source; + const source = claim && claim.value && claim.value.stream && claim.value.stream.source; return source ? source.contentType : undefined; }); export const selectIsFetchingClaimListMine = createSelector( - _selectState, + selectState, state => !!state.isFetchingClaimListMine ); -export const selectMyClaimsRaw = createSelector( - _selectState, - state => state.myClaims -); - -export const selectAbandoningIds = createSelector(_selectState, state => - Object.keys(state.abandoningById || {}) -); - -export const selectMyActiveClaims = createSelector( - selectMyClaimsRaw, - selectAbandoningIds, - (claims, abandoningIds) => - new Set( - claims && - claims - .map(claim => claim.claim_id) - .filter(claimId => Object.keys(abandoningIds).indexOf(claimId) === -1) - ) -); - -export const selectPendingClaims = createSelector(_selectState, state => +export const selectPendingClaims = createSelector(selectState, state => Object.values(state.pendingById || {}) ); @@ -151,46 +127,38 @@ export const selectMyClaims = createSelector( myClaimIds.forEach(id => { const claim = byId[id]; - if (claim && abandoningIds.indexOf(id) == -1) claims.push(claim); + if (claim && abandoningIds.indexOf(id) === -1) claims.push(claim); }); return [...claims, ...pendingClaims]; } ); -export const selectMyClaimsWithoutChannels = createSelector( - selectMyClaims, - myClaims => myClaims.filter(claim => !claim.name.match(/^@/)) +export const selectMyClaimsWithoutChannels = createSelector(selectMyClaims, myClaims => + myClaims.filter(claim => !claim.name.match(/^@/)) ); export const selectAllMyClaimsByOutpoint = createSelector( selectMyClaimsRaw, claims => - new Set( - claims && claims.length - ? claims.map(claim => `${claim.txid}:${claim.nout}`) - : null - ) + new Set(claims && claims.length ? claims.map(claim => `${claim.txid}:${claim.nout}`) : null) ); -export const selectMyClaimsOutpoints = createSelector( - selectMyClaims, - myClaims => { - const outpoints = []; +export const selectMyClaimsOutpoints = createSelector(selectMyClaims, myClaims => { + const outpoints = []; - myClaims.forEach(claim => outpoints.push(`${claim.txid}:${claim.nout}`)); + myClaims.forEach(claim => outpoints.push(`${claim.txid}:${claim.nout}`)); - return outpoints; - } -); + return outpoints; +}); export const selectFetchingMyChannels = createSelector( - _selectState, + selectState, state => !!state.fetchingMyChannels ); export const selectMyChannelClaims = createSelector( - _selectState, + selectState, selectClaimsById, (state, byId) => { const ids = state.myChannelClaims || []; diff --git a/src/renderer/redux/selectors/content.js b/src/renderer/redux/selectors/content.js index 7d7f01ef9..31e415dbe 100644 --- a/src/renderer/redux/selectors/content.js +++ b/src/renderer/redux/selectors/content.js @@ -1,35 +1,26 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; -export const _selectState = state => state.content || {}; +export const selectState = state => state.content || {}; -export const selectFeaturedUris = createSelector( - _selectState, - state => state.featuredUris -); +export const selectFeaturedUris = createSelector(selectState, state => state.featuredUris); export const selectFetchingFeaturedUris = createSelector( - _selectState, + selectState, state => !!state.fetchingFeaturedContent ); -export const selectResolvingUris = createSelector( - _selectState, - state => state.resolvingUris || [] -); +export const selectResolvingUris = createSelector(selectState, state => state.resolvingUris || []); -export const selectPlayingUri = createSelector( - _selectState, - state => state.playingUri -); +export const selectPlayingUri = createSelector(selectState, state => state.playingUri); export const makeSelectIsUriResolving = uri => createSelector( selectResolvingUris, - resolvingUris => resolvingUris && resolvingUris.indexOf(uri) != -1 + resolvingUris => resolvingUris && resolvingUris.indexOf(uri) !== -1 ); export const selectChannelClaimCounts = createSelector( - _selectState, + selectState, state => state.channelClaimCounts || {} ); @@ -43,6 +34,6 @@ export const makeSelectTotalPagesForChannel = uri => ); export const selectRewardContentClaimIds = createSelector( - _selectState, + selectState, state => state.rewardedContentClaimIds ); diff --git a/src/renderer/redux/selectors/cost_info.js b/src/renderer/redux/selectors/cost_info.js index 20eae1a69..04d5b09e5 100644 --- a/src/renderer/redux/selectors/cost_info.js +++ b/src/renderer/redux/selectors/cost_info.js @@ -1,33 +1,20 @@ -import { createSelector } from "reselect"; -import { selectCurrentParams } from "redux/selectors/navigation"; +import { createSelector } from 'reselect'; +import { selectCurrentParams } from 'redux/selectors/navigation'; -export const _selectState = state => state.costInfo || {}; +export const selectState = state => state.costInfo || {}; -export const selectAllCostInfoByUri = createSelector( - _selectState, - state => state.byUri || {} -); +export const selectAllCostInfoByUri = createSelector(selectState, state => state.byUri || {}); export const makeSelectCostInfoForUri = uri => - createSelector( - selectAllCostInfoByUri, - costInfos => costInfos && costInfos[uri] - ); + createSelector(selectAllCostInfoByUri, costInfos => costInfos && costInfos[uri]); export const selectCostForCurrentPageUri = createSelector( selectAllCostInfoByUri, selectCurrentParams, - (costInfo, params) => - params.uri && costInfo[params.uri] ? costInfo[params.uri].cost : undefined + (costInfo, params) => (params.uri && costInfo[params.uri] ? costInfo[params.uri].cost : undefined) ); -export const selectFetchingCostInfo = createSelector( - _selectState, - state => state.fetching || {} -); +export const selectFetchingCostInfo = createSelector(selectState, state => state.fetching || {}); export const makeSelectFetchingCostInfoForUri = uri => - createSelector( - selectFetchingCostInfo, - fetchingByUri => fetchingByUri && fetchingByUri[uri] - ); + createSelector(selectFetchingCostInfo, fetchingByUri => fetchingByUri && fetchingByUri[uri]); diff --git a/src/renderer/redux/selectors/file_info.js b/src/renderer/redux/selectors/file_info.js index 74482abf0..9e2409911 100644 --- a/src/renderer/redux/selectors/file_info.js +++ b/src/renderer/redux/selectors/file_info.js @@ -1,45 +1,39 @@ -import lbry from "lbry"; -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; import { selectClaimsByUri, selectIsFetchingClaimListMine, selectMyClaims, selectMyClaimsOutpoints, -} from "redux/selectors/claims"; +} from 'redux/selectors/claims'; -export const _selectState = state => state.fileInfo || {}; +export const selectState = state => state.fileInfo || {}; export const selectFileInfosByOutpoint = createSelector( - _selectState, + selectState, state => state.byOutpoint || {} ); export const selectIsFetchingFileList = createSelector( - _selectState, - state => !!state.isFetchingFileList + selectState, + state => state.isFetchingFileList ); export const selectIsFetchingFileListDownloadedOrPublished = createSelector( selectIsFetchingFileList, selectIsFetchingClaimListMine, - (isFetchingFileList, isFetchingClaimListMine) => - isFetchingFileList || isFetchingClaimListMine + (isFetchingFileList, isFetchingClaimListMine) => isFetchingFileList || isFetchingClaimListMine ); export const makeSelectFileInfoForUri = uri => - createSelector( - selectClaimsByUri, - selectFileInfosByOutpoint, - (claims, byOutpoint) => { - const claim = claims[uri], - outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined; + createSelector(selectClaimsByUri, selectFileInfosByOutpoint, (claims, byOutpoint) => { + const claim = claims[uri]; + const outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined; - return outpoint ? byOutpoint[outpoint] : undefined; - } - ); + return outpoint ? byOutpoint[outpoint] : undefined; + }); export const selectDownloadingByOutpoint = createSelector( - _selectState, + selectState, state => state.downloadingByOutpoint || {} ); @@ -53,17 +47,13 @@ export const makeSelectDownloadingForUri = uri => } ); -export const selectUrisLoading = createSelector( - _selectState, - state => state.urisLoading || {} -); +export const selectUrisLoading = createSelector(selectState, state => state.urisLoading || {}); export const makeSelectLoadingForUri = uri => createSelector(selectUrisLoading, byUri => byUri && byUri[uri]); -export const selectFileInfosPendingPublish = createSelector( - _selectState, - state => Object.values(state.pendingByOutpoint || {}) +export const selectFileInfosPendingPublish = createSelector(selectState, state => + Object.values(state.pendingByOutpoint || {}) ); export const selectFileInfosDownloaded = createSelector( @@ -141,18 +131,15 @@ export const selectDownloadingFileInfos = createSelector( } ); -export const selectTotalDownloadProgress = createSelector( - selectDownloadingFileInfos, - fileInfos => { - const progress = []; +export const selectTotalDownloadProgress = createSelector(selectDownloadingFileInfos, fileInfos => { + const progress = []; - fileInfos.forEach(fileInfo => { - progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100); - }); + fileInfos.forEach(fileInfo => { + progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100); + }); - const totalProgress = progress.reduce((a, b) => a + b, 0); + const totalProgress = progress.reduce((a, b) => a + b, 0); - if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0; - return -1; - } -); + if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0; + return -1; +}); diff --git a/src/renderer/redux/selectors/navigation.js b/src/renderer/redux/selectors/navigation.js index 7d401127a..dc0b507a1 100644 --- a/src/renderer/redux/selectors/navigation.js +++ b/src/renderer/redux/selectors/navigation.js @@ -1,17 +1,12 @@ -import { createSelector } from "reselect"; -import { parseQueryParams, toQueryString } from "util/query_params"; -import * as settings from "constants/settings.js"; -import lbryuri from "lbryuri"; +import { createSelector } from 'reselect'; +import { parseQueryParams, toQueryString } from 'util/query_params'; +import Lbryuri from 'lbryuri'; -export const _selectState = state => state.navigation || {}; +export const selectState = state => state.navigation || {}; -export const selectCurrentPath = createSelector( - _selectState, - state => state.currentPath -); +export const selectCurrentPath = createSelector(selectState, state => state.currentPath); -export const computePageFromPath = path => - path.replace(/^\//, "").split("?")[0]; +export const computePageFromPath = path => path.replace(/^\//, '').split('?')[0]; export const selectCurrentPage = createSelector(selectCurrentPath, path => computePageFromPath(path) @@ -21,50 +16,47 @@ export const selectCurrentParams = createSelector(selectCurrentPath, path => { if (path === undefined) return {}; if (!path.match(/\?/)) return {}; - return parseQueryParams(path.split("?")[1]); + return parseQueryParams(path.split('?')[1]); }); export const makeSelectCurrentParam = param => - createSelector( - selectCurrentParams, - params => (params ? params[param] : undefined) - ); + createSelector(selectCurrentParams, params => (params ? params[param] : undefined)); export const selectHeaderLinks = createSelector(selectCurrentPage, page => { // This contains intentional fall throughs switch (page) { - case "wallet": - case "history": - case "send": - case "getcredits": - case "invite": - case "rewards": - case "backup": + case 'wallet': + case 'history': + case 'send': + case 'getcredits': + case 'invite': + case 'rewards': + case 'backup': return { - wallet: __("Overview"), - getcredits: __("Get Credits"), - send: __("Send / Receive"), - rewards: __("Rewards"), - invite: __("Invites"), - history: __("History"), + wallet: __('Overview'), + getcredits: __('Get Credits'), + send: __('Send / Receive'), + rewards: __('Rewards'), + invite: __('Invites'), + history: __('History'), }; - case "downloaded": - case "published": + case 'downloaded': + case 'published': return { - downloaded: __("Downloaded"), - published: __("Published"), + downloaded: __('Downloaded'), + published: __('Published'), }; - case "settings": - case "help": + case 'settings': + case 'help': return { - settings: __("Settings"), - help: __("Help"), + settings: __('Settings'), + help: __('Help'), }; - case "discover": - case "subscriptions": + case 'discover': + case 'subscriptions': return { - discover: __("Discover"), - subscriptions: __("Subscriptions"), + discover: __('Discover'), + subscriptions: __('Subscriptions'), }; default: return null; @@ -76,86 +68,72 @@ export const selectPageTitle = createSelector( selectCurrentParams, (page, params) => { switch (page) { - case "settings": - return __("Settings"); - case "report": - return __("Report"); - case "wallet": - return __("Wallet"); - case "send": - return __("Send or Receive LBRY Credits"); - case "getcredits": - return __("Get LBRY Credits"); - case "backup": - return __("Backup Your Wallet"); - case "rewards": - return __("Rewards"); - case "invite": - return __("Invites"); - case "start": - return __("Start"); - case "publish": - return params.id ? __("Edit") : __("Publish"); - case "help": - return __("Help"); - case "developer": - return __("Developer"); - case "show": { - const parts = [lbryuri.normalize(params.uri)]; + case 'settings': + return __('Settings'); + case 'report': + return __('Report'); + case 'wallet': + return __('Wallet'); + case 'send': + return __('Send or Receive LBRY Credits'); + case 'getcredits': + return __('Get LBRY Credits'); + case 'backup': + return __('Backup Your Wallet'); + case 'rewards': + return __('Rewards'); + case 'invite': + return __('Invites'); + case 'start': + return __('Start'); + case 'publish': + return params.id ? __('Edit') : __('Publish'); + case 'help': + return __('Help'); + case 'developer': + return __('Developer'); + case 'show': { + const parts = [Lbryuri.normalize(params.uri)]; // If the params has any keys other than "uri" if (Object.keys(params).length > 1) { parts.push(toQueryString(Object.assign({}, params, { uri: null }))); } - return parts.join("?"); + return parts.join('?'); } - case "downloaded": - return __("Downloads & Purchases"); - case "published": - return __("Publishes"); - case "search": - return params.query - ? __("Search results for %s", params.query) - : __("Search"); - case "subscriptions": - return __("Your Subscriptions"); - case "discover": + case 'downloaded': + return __('Downloads & Purchases'); + case 'published': + return __('Publications'); + case 'search': + return params.query ? __('Search results for %s', params.query) : __('Search'); + case 'subscriptions': + return __('Your Subscriptions'); + case 'discover': case false: case null: - case "": - return ""; + case '': + return ''; default: - return page[0].toUpperCase() + (page.length > 0 ? page.substr(1) : ""); + return page[0].toUpperCase() + (page.length > 0 ? page.substr(1) : ''); } } ); -export const selectPathAfterAuth = createSelector( - _selectState, - state => state.pathAfterAuth -); +export const selectPathAfterAuth = createSelector(selectState, state => state.pathAfterAuth); -export const selectIsBackDisabled = createSelector( - _selectState, - state => state.index === 0 -); +export const selectIsBackDisabled = createSelector(selectState, state => state.index === 0); export const selectIsForwardDisabled = createSelector( - _selectState, + selectState, state => state.index === state.stack.length - 1 ); -export const selectHistoryIndex = createSelector( - _selectState, - state => state.index -); +export const selectHistoryIndex = createSelector(selectState, state => state.index); -export const selectHistoryStack = createSelector( - _selectState, - state => state.stack -); +export const selectHistoryStack = createSelector(selectState, state => state.stack); // returns current page attributes (scrollY, path) export const selectActiveHistoryEntry = createSelector( - _selectState, + selectState, state => state.stack[state.index] ); diff --git a/src/renderer/redux/selectors/rewards.js b/src/renderer/redux/selectors/rewards.js index ed6ef4605..cb0c83f52 100644 --- a/src/renderer/redux/selectors/rewards.js +++ b/src/renderer/redux/selectors/rewards.js @@ -1,16 +1,15 @@ -import { createSelector } from "reselect"; -import { selectUser } from "redux/selectors/user"; -import rewards from "rewards"; +import { createSelector } from 'reselect'; +import REWARDS from 'rewards'; -const _selectState = state => state.rewards || {}; +const selectState = state => state.rewards || {}; export const selectUnclaimedRewardsByType = createSelector( - _selectState, + selectState, state => state.unclaimedRewardsByType ); export const selectClaimedRewardsById = createSelector( - _selectState, + selectState, state => state.claimedRewardsById ); @@ -19,13 +18,12 @@ export const selectClaimedRewards = createSelector( byId => Object.values(byId) || [] ); -export const selectClaimedRewardsByTransactionId = createSelector( - selectClaimedRewards, - rewards => - rewards.reduce((map, reward) => { - map[reward.transaction_id] = reward; - return map; - }, {}) +export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedRewards, rewards => + rewards.reduce((mapParam, reward) => { + const map = mapParam; + map[reward.transaction_id] = reward; + return map; + }, {}) ); export const selectUnclaimedRewards = createSelector( @@ -33,38 +31,20 @@ export const selectUnclaimedRewards = createSelector( byType => Object.values(byType).sort( (a, b) => - rewards.SORT_ORDER.indexOf(a.reward_type) < - rewards.SORT_ORDER.indexOf(b.reward_type) + REWARDS.SORT_ORDER.indexOf(a.reward_type) < REWARDS.SORT_ORDER.indexOf(b.reward_type) ? -1 : 1 ) || [] ); -export const selectIsRewardEligible = createSelector( - selectUser, - user => user.can_claim_rewards +export const selectFetchingRewards = createSelector(selectState, state => !!state.fetching); + +export const selectUnclaimedRewardValue = createSelector(selectUnclaimedRewards, rewards => + rewards.reduce((sum, reward) => sum + reward.reward_amount, 0) ); -export const selectFetchingRewards = createSelector( - _selectState, - state => !!state.fetching -); - -export const selectUnclaimedRewardValue = createSelector( - selectUnclaimedRewards, - rewards => rewards.reduce((sum, reward) => sum + reward.reward_amount, 0) -); - -export const selectHasClaimedReward = (state, props) => { - const reward = selectRewardsByType(state)[props.reward_type]; - return reward && reward.transaction_id !== ""; -}; - -export const makeSelectHasClaimedReward = () => - createSelector(selectHasClaimedReward, claimed => claimed); - export const selectClaimsPendingByType = createSelector( - _selectState, + selectState, state => state.claimPendingByType ); @@ -75,7 +55,7 @@ export const makeSelectIsRewardClaimPending = () => createSelector(selectIsClaimRewardPending, isClaiming => isClaiming); export const selectClaimErrorsByType = createSelector( - _selectState, + selectState, state => state.claimErrorsByType ); @@ -85,14 +65,9 @@ const selectClaimRewardError = (state, props) => export const makeSelectClaimRewardError = () => createSelector(selectClaimRewardError, errorMessage => errorMessage); -const selectRewardByType = (state, props) => - selectUnclaimedRewardsByType(state)[props.reward_type]; +const selectRewardByType = (state, props) => selectUnclaimedRewardsByType(state)[props.reward_type]; -export const makeSelectRewardByType = () => - createSelector(selectRewardByType, reward => reward); +export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward); export const makeSelectRewardAmountByType = () => - createSelector( - selectRewardByType, - reward => (reward ? reward.reward_amount : 0) - ); + createSelector(selectRewardByType, reward => (reward ? reward.reward_amount : 0)); diff --git a/src/renderer/redux/selectors/search.js b/src/renderer/redux/selectors/search.js index 8faf0a307..b34a5742f 100644 --- a/src/renderer/redux/selectors/search.js +++ b/src/renderer/redux/selectors/search.js @@ -1,40 +1,34 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; import { selectPageTitle, selectCurrentPage, selectCurrentParams, -} from "redux/selectors/navigation"; +} from 'redux/selectors/navigation'; -export const _selectState = state => state.search || {}; +export const selectState = state => state.search || {}; export const selectSearchQuery = createSelector( selectCurrentPage, selectCurrentParams, - (page, params) => (page === "search" ? params && params.query : null) + (page, params) => (page === 'search' ? params && params.query : null) ); -export const selectIsSearching = createSelector( - _selectState, - state => !!state.searching -); +export const selectIsSearching = createSelector(selectState, state => !!state.searching); -export const selectSearchUrisByQuery = createSelector( - _selectState, - state => state.urisByQuery -); +export const selectSearchUrisByQuery = createSelector(selectState, state => state.urisByQuery); export const makeSelectSearchUris = query => // replace statement below is kind of ugly, and repeated in doSearch action createSelector( selectSearchUrisByQuery, - byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, "") : query] + byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '') : query] ); export const selectWunderBarAddress = createSelector( selectCurrentPage, selectPageTitle, selectSearchQuery, - (page, title, query) => (page != "search" ? title : query || title) + (page, title, query) => (page !== 'search' ? title : query || title) ); export const selectWunderBarIcon = createSelector( @@ -42,44 +36,44 @@ export const selectWunderBarIcon = createSelector( selectCurrentParams, (page, params) => { switch (page) { - case "auth": - return "icon-user"; - case "settings": - return "icon-gear"; - case "help": - return "icon-question"; - case "report": - return "icon-file"; - case "downloaded": - return "icon-folder"; - case "published": - return "icon-folder"; - case "history": - return "icon-history"; - case "send": - return "icon-send"; - case "rewards": - return "icon-rocket"; - case "invite": - return "icon-envelope-open"; - case "getcredits": - return "icon-shopping-cart"; - case "wallet": - case "backup": - return "icon-bank"; - case "show": - return "icon-file"; - case "publish": - return params.id ? __("icon-pencil") : __("icon-upload"); - case "developer": - return "icon-code"; - case "discover": - case "search": - return "icon-search"; - case "subscriptions": - return "icon-th-list"; + case 'auth': + return 'icon-user'; + case 'settings': + return 'icon-gear'; + case 'help': + return 'icon-question'; + case 'report': + return 'icon-file'; + case 'downloaded': + return 'icon-folder'; + case 'published': + return 'icon-folder'; + case 'history': + return 'icon-history'; + case 'send': + return 'icon-send'; + case 'rewards': + return 'icon-rocket'; + case 'invite': + return 'icon-envelope-open'; + case 'getcredits': + return 'icon-shopping-cart'; + case 'wallet': + case 'backup': + return 'icon-bank'; + case 'show': + return 'icon-file'; + case 'publish': + return params.id ? __('icon-pencil') : __('icon-upload'); + case 'developer': + return 'icon-code'; + case 'discover': + case 'search': + return 'icon-search'; + case 'subscriptions': + return 'icon-th-list'; default: - return "icon-file"; + return 'icon-file'; } } ); diff --git a/src/renderer/redux/selectors/settings.js b/src/renderer/redux/selectors/settings.js index b0a7325dd..ba246f0cb 100644 --- a/src/renderer/redux/selectors/settings.js +++ b/src/renderer/redux/selectors/settings.js @@ -1,24 +1,17 @@ -import * as settings from "constants/settings"; -import { createSelector } from "reselect"; -import path from "path"; +import * as SETTINGS from 'constants/settings'; +import { createSelector } from 'reselect'; -const _selectState = state => state.settings || {}; +const selectState = state => state.settings || {}; -export const selectDaemonSettings = createSelector( - _selectState, - state => state.daemonSettings -); +export const selectDaemonSettings = createSelector(selectState, state => state.daemonSettings); export const selectClientSettings = createSelector( - _selectState, + selectState, state => state.clientSettings || {} ); export const makeSelectClientSetting = setting => - createSelector( - selectClientSettings, - settings => (settings ? settings[setting] : undefined) - ); + createSelector(selectClientSettings, settings => (settings ? settings[setting] : undefined)); export const selectSettingsIsGenerous = createSelector( selectDaemonSettings, @@ -26,14 +19,11 @@ export const selectSettingsIsGenerous = createSelector( ); // refactor me -export const selectShowNsfw = makeSelectClientSetting(settings.SHOW_NSFW); +export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW); -export const selectLanguages = createSelector( - _selectState, - state => state.languages || {} -); +export const selectLanguages = createSelector(selectState, state => state.languages || {}); export const selectThemePath = createSelector( - makeSelectClientSetting(settings.THEME), - theme => `${staticResourcesPath}/themes/${theme || "light"}.css` + makeSelectClientSetting(SETTINGS.THEME), + theme => `${staticResourcesPath}/themes/${theme || 'light'}.css` ); diff --git a/src/renderer/redux/selectors/shape_shift.js b/src/renderer/redux/selectors/shape_shift.js index e60af9fb4..090006d73 100644 --- a/src/renderer/redux/selectors/shape_shift.js +++ b/src/renderer/redux/selectors/shape_shift.js @@ -1,7 +1,9 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; -const _selectState = state => state.shapeShift; +const selectState = state => state.shapeShift; -export const selectShapeShift = createSelector(_selectState, state => ({ +export const selectShapeShift = createSelector(selectState, state => ({ ...state, })); + +export { selectShapeShift as default }; diff --git a/src/renderer/redux/selectors/subscriptions.js b/src/renderer/redux/selectors/subscriptions.js index f3eb78a6e..50bedf3ef 100644 --- a/src/renderer/redux/selectors/subscriptions.js +++ b/src/renderer/redux/selectors/subscriptions.js @@ -1,15 +1,11 @@ -import * as settings from "constants/settings"; -import { createSelector } from "reselect"; -import { selectAllClaimsByChannel, selectClaimsById } from "./claims"; +import { createSelector } from 'reselect'; +import { selectAllClaimsByChannel, selectClaimsById } from './claims'; // get the entire subscriptions state -const _selectState = state => state.subscriptions || {}; +const selectState = state => state.subscriptions || {}; // list of saved channel names and uris -export const selectSubscriptions = createSelector( - _selectState, - state => state.subscriptions -); +export const selectSubscriptions = createSelector(selectState, state => state.subscriptions); export const selectSubscriptionsFromClaims = createSelector( selectAllClaimsByChannel, @@ -29,7 +25,7 @@ export const selectSubscriptionsFromClaims = createSelector( // if subscribed channel has content if (channelIds[subscription.uri]) { // This will need to be more robust, we will want to be able to load more than the first page - const pageOneChannelIds = channelIds[subscription.uri]["1"]; + const pageOneChannelIds = channelIds[subscription.uri]['1']; // we have the channel ids and the corresponding claims // loop over the list of ids and grab the claim @@ -40,9 +36,7 @@ export const selectSubscriptionsFromClaims = createSelector( } // all we really need is a uri for each claim - channelClaims = channelClaims.map( - claim => `${claim.name}#${claim.claim_id}` - ); + channelClaims = channelClaims.map(claim => `${claim.name}#${claim.claim_id}`); fetchedSubscriptions.push({ claims: channelClaims, diff --git a/src/renderer/redux/selectors/user.js b/src/renderer/redux/selectors/user.js index 8cc59bab0..de2c6c447 100644 --- a/src/renderer/redux/selectors/user.js +++ b/src/renderer/redux/selectors/user.js @@ -1,18 +1,15 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; -export const _selectState = state => state.user || {}; +export const selectState = state => state.user || {}; export const selectAuthenticationIsPending = createSelector( - _selectState, + selectState, state => state.authenticationIsPending ); -export const selectUserIsPending = createSelector( - _selectState, - state => state.userIsPending -); +export const selectUserIsPending = createSelector(selectState, state => state.userIsPending); -export const selectUser = createSelector(_selectState, state => state.user); +export const selectUser = createSelector(selectState, state => state.user); export const selectUserEmail = createSelector( selectUser, @@ -20,7 +17,7 @@ export const selectUserEmail = createSelector( ); export const selectEmailToVerify = createSelector( - _selectState, + selectState, selectUserEmail, (state, userEmail) => state.emailToVerify || userEmail ); @@ -31,32 +28,32 @@ export const selectUserIsRewardApproved = createSelector( ); export const selectEmailNewIsPending = createSelector( - _selectState, + selectState, state => state.emailNewIsPending ); export const selectEmailNewErrorMessage = createSelector( - _selectState, + selectState, state => state.emailNewErrorMessage ); export const selectEmailVerifyIsPending = createSelector( - _selectState, + selectState, state => state.emailVerifyIsPending ); export const selectEmailVerifyErrorMessage = createSelector( - _selectState, + selectState, state => state.emailVerifyErrorMessage ); export const selectIdentityVerifyIsPending = createSelector( - _selectState, + selectState, state => state.identityVerifyIsPending ); export const selectIdentityVerifyErrorMessage = createSelector( - _selectState, + selectState, state => state.identityVerifyErrorMessage ); @@ -65,37 +62,31 @@ export const selectUserIsVerificationCandidate = createSelector( user => user && (!user.has_verified_email || !user.is_identity_verified) ); -export const selectAccessToken = createSelector( - _selectState, - state => state.accessToken -); +export const selectAccessToken = createSelector(selectState, state => state.accessToken); export const selectUserInviteStatusIsPending = createSelector( - _selectState, + selectState, state => state.inviteStatusIsPending ); export const selectUserInvitesRemaining = createSelector( - _selectState, + selectState, state => state.invitesRemaining ); -export const selectUserInvitees = createSelector( - _selectState, - state => state.invitees -); +export const selectUserInvitees = createSelector(selectState, state => state.invitees); export const selectUserInviteStatusFailed = createSelector( selectUserInvitesRemaining, - inviteStatus => selectUserInvitesRemaining === null + () => selectUserInvitesRemaining === null ); export const selectUserInviteNewIsPending = createSelector( - _selectState, + selectState, state => state.inviteNewIsPending ); export const selectUserInviteNewErrorMessage = createSelector( - _selectState, + selectState, state => state.inviteNewErrorMessage ); diff --git a/src/renderer/redux/selectors/wallet.js b/src/renderer/redux/selectors/wallet.js index dca790e5b..bddedb8f4 100644 --- a/src/renderer/redux/selectors/wallet.js +++ b/src/renderer/redux/selectors/wallet.js @@ -1,99 +1,81 @@ -import { createSelector } from "reselect"; +import { createSelector } from 'reselect'; -export const _selectState = state => state.wallet || {}; +export const selectState = state => state.wallet || {}; -export const selectBalance = createSelector( - _selectState, - state => state.balance -); +export const selectBalance = createSelector(selectState, state => state.balance); -export const selectTransactionsById = createSelector( - _selectState, - state => state.transactions -); +export const selectTransactionsById = createSelector(selectState, state => state.transactions); -export const selectTransactionItems = createSelector( - selectTransactionsById, - byId => { - const items = []; +export const selectTransactionItems = createSelector(selectTransactionsById, byId => { + const items = []; - Object.keys(byId).forEach(txid => { - const tx = byId[txid]; + Object.keys(byId).forEach(txid => { + const tx = byId[txid]; - // ignore dust/fees - // it is fee only txn if all infos are also empty - if ( - Math.abs(tx.value) === Math.abs(tx.fee) && - tx.claim_info.length == 0 && - tx.support_info.length == 0 && - tx.update_info.length == 0 - ) { - return; - } + // ignore dust/fees + // it is fee only txn if all infos are also empty + if ( + Math.abs(tx.value) === Math.abs(tx.fee) && + tx.claim_info.length === 0 && + tx.support_info.length === 0 && + tx.update_info.length === 0 + ) { + return; + } - const append = []; + const append = []; + append.push( + ...tx.claim_info.map(item => + Object.assign({}, tx, item, { + type: item.claim_name[0] === '@' ? 'channel' : 'publish', + }) + ) + ); + append.push( + ...tx.support_info.map(item => + Object.assign({}, tx, item, { + type: !item.is_tip ? 'support' : 'tip', + }) + ) + ); + append.push(...tx.update_info.map(item => Object.assign({}, tx, item, { type: 'update' }))); + + if (!append.length) { append.push( - ...tx.claim_info.map(item => - Object.assign({}, tx, item, { - type: item.claim_name[0] === "@" ? "channel" : "publish", - }) - ) - ); - append.push( - ...tx.support_info.map(item => - Object.assign({}, tx, item, { - type: !item.is_tip ? "support" : "tip", - }) - ) - ); - append.push( - ...tx.update_info.map(item => - Object.assign({}, tx, item, { type: "update" }) - ) - ); - - if (!append.length) { - append.push( - Object.assign({}, tx, { - type: tx.value < 0 ? "spend" : "receive", - }) - ); - } - - items.push( - ...append.map(item => { - // value on transaction, amount on outpoint - // amount is always positive, but should match sign of value - const amount = parseFloat( - item.balance_delta ? item.balance_delta : item.value - ); - - return { - txid, - date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, - amount, - fee: amount < 0 ? -1 * tx.fee / append.length : 0, - claim_id: item.claim_id, - claim_name: item.claim_name, - type: item.type || "send", - nout: item.nout, - }; + Object.assign({}, tx, { + type: tx.value < 0 ? 'spend' : 'receive', }) ); - }); - return items.reverse(); - } -); + } -export const selectRecentTransactions = createSelector( - selectTransactionItems, - transactions => { - const threshold = new Date(); - threshold.setDate(threshold.getDate() - 7); - return transactions.filter(transaction => transaction.date > threshold); - } -); + items.push( + ...append.map(item => { + // value on transaction, amount on outpoint + // amount is always positive, but should match sign of value + const amount = parseFloat(item.balance_delta ? item.balance_delta : item.value); + + return { + txid, + date: tx.timestamp ? new Date(Number(tx.timestamp) * 1000) : null, + amount, + fee: amount < 0 ? -1 * tx.fee / append.length : 0, + claim_id: item.claim_id, + claim_name: item.claim_name, + type: item.type || 'send', + nout: item.nout, + }; + }) + ); + }); + return items.reverse(); +}); + +export const selectRecentTransactions = createSelector(selectTransactionItems, transactions => { + const threshold = new Date(); + threshold.setDate(threshold.getDate() - 7); + return transactions.filter(transaction => transaction.date > threshold); +}); export const selectHasTransactions = createSelector( selectTransactionItems, @@ -101,27 +83,21 @@ export const selectHasTransactions = createSelector( ); export const selectIsFetchingTransactions = createSelector( - _selectState, + selectState, state => state.fetchingTransactions ); -export const selectIsSendingSupport = createSelector( - _selectState, - state => state.sendingSupport -); +export const selectIsSendingSupport = createSelector(selectState, state => state.sendingSupport); -export const selectReceiveAddress = createSelector( - _selectState, - state => state.receiveAddress -); +export const selectReceiveAddress = createSelector(selectState, state => state.receiveAddress); export const selectGettingNewAddress = createSelector( - _selectState, + selectState, state => state.gettingNewAddress ); export const selectDraftTransaction = createSelector( - _selectState, + selectState, state => state.draftTransaction || {} ); @@ -140,11 +116,10 @@ export const selectDraftTransactionError = createSelector( draft => draft.error ); -export const selectBlocks = createSelector(_selectState, state => state.blocks); +export const selectBlocks = createSelector(selectState, state => state.blocks); export const makeSelectBlockDate = block => createSelector( selectBlocks, - blocks => - blocks && blocks[block] ? new Date(blocks[block].time * 1000) : undefined + blocks => (blocks && blocks[block] ? new Date(blocks[block].time * 1000) : undefined) ); diff --git a/src/renderer/rewards.js b/src/renderer/rewards.js index 72ca1fb44..de552230f 100644 --- a/src/renderer/rewards.js +++ b/src/renderer/rewards.js @@ -1,53 +1,32 @@ -import lbry from "lbry"; -import lbryio from "lbryio"; -import { doShowSnackBar } from "redux/actions/app"; +import Lbry from 'lbry'; +import Lbryio from 'lbryio'; +import { doShowSnackBar } from 'redux/actions/app'; function rewardMessage(type, amount) { return { - new_developer: __( - "You earned %s for registering as a new developer.", - amount - ), - new_user: __("You earned %s LBC new user reward.", amount), - confirm_email: __( - "You earned %s LBC for verifying your email address.", - amount - ), - new_channel: __( - "You earned %s LBC for creating a publisher identity.", - amount - ), - first_stream: __( - "You earned %s LBC for streaming your first video.", - amount - ), - many_downloads: __( - "You earned %s LBC for downloading a bunch of things.", - amount - ), - first_publish: __( - "You earned %s LBC for making your first publication.", - amount - ), - featured_download: __( - "You earned %s LBC for watching a featured download.", - amount - ), - referral: __("You earned %s LBC for referring someone.", amount), + new_developer: __('You earned %s for registering as a new developer.', amount), + new_user: __('You earned %s LBC new user reward.', amount), + confirm_email: __('You earned %s LBC for verifying your email address.', amount), + new_channel: __('You earned %s LBC for creating a publisher identity.', amount), + first_stream: __('You earned %s LBC for streaming your first video.', amount), + many_downloads: __('You earned %s LBC for downloading a bunch of things.', amount), + first_publish: __('You earned %s LBC for making your first publication.', amount), + featured_download: __('You earned %s LBC for watching a featured download.', amount), + referral: __('You earned %s LBC for referring someone.', amount), }[type]; } const rewards = {}; -rewards.TYPE_NEW_DEVELOPER = "new_developer"; -rewards.TYPE_NEW_USER = "new_user"; -rewards.TYPE_CONFIRM_EMAIL = "verified_email"; -rewards.TYPE_FIRST_CHANNEL = "new_channel"; -rewards.TYPE_FIRST_STREAM = "first_stream"; -rewards.TYPE_MANY_DOWNLOADS = "many_downloads"; -rewards.TYPE_FIRST_PUBLISH = "first_publish"; -rewards.TYPE_FEATURED_DOWNLOAD = "featured_download"; -rewards.TYPE_REFERRAL = "referral"; +rewards.TYPE_NEW_DEVELOPER = 'new_developer'; +rewards.TYPE_NEW_USER = 'new_user'; +rewards.TYPE_CONFIRM_EMAIL = 'verified_email'; +rewards.TYPE_FIRST_CHANNEL = 'new_channel'; +rewards.TYPE_FIRST_STREAM = 'first_stream'; +rewards.TYPE_MANY_DOWNLOADS = 'many_downloads'; +rewards.TYPE_FIRST_PUBLISH = 'first_publish'; +rewards.TYPE_FEATURED_DOWNLOAD = 'featured_download'; +rewards.TYPE_REFERRAL = 'referral'; rewards.SORT_ORDER = [ rewards.TYPE_NEW_USER, rewards.TYPE_CONFIRM_EMAIL, @@ -62,18 +41,18 @@ rewards.SORT_ORDER = [ rewards.claimReward = function(type) { function requestReward(resolve, reject, params) { - if (!lbryio.enabled) { - reject(new Error(__("Rewards are not enabled."))); + if (!Lbryio.enabled) { + reject(new Error(__('Rewards are not enabled.'))); return; } - lbryio.call("reward", "new", params, "post").then(reward => { + Lbryio.call('reward', 'new', params, 'post').then(reward => { const message = rewardMessage(type, reward.reward_amount); // Display global notice const action = doShowSnackBar({ message, - linkText: __("Show All"), - linkTarget: "/rewards", + linkText: __('Show All'), + linkTarget: '/rewards', isError: false, }); window.app.store.dispatch(action); @@ -85,7 +64,7 @@ rewards.claimReward = function(type) { } return new Promise((resolve, reject) => { - lbry.wallet_unused_address().then(address => { + Lbry.wallet_unused_address().then(address => { const params = { reward_type: type, wallet_address: address, @@ -93,42 +72,38 @@ rewards.claimReward = function(type) { switch (type) { case rewards.TYPE_FIRST_CHANNEL: - lbry - .claim_list_mine() + Lbry.claim_list_mine() .then(claims => { const claim = claims .reverse() .find( - claim => - claim.name.length && - claim.name[0] == "@" && - claim.txid.length && - claim.category == "claim" + foundClaim => + foundClaim.name.length && + foundClaim.name[0] === '@' && + foundClaim.txid.length && + foundClaim.category === 'claim' ); if (claim) { params.transaction_id = claim.txid; requestReward(resolve, reject, params); } else { - reject( - new Error(__("Please create a channel identity first.")) - ); + reject(new Error(__('Please create a channel identity first.'))); } }) .catch(reject); break; case rewards.TYPE_FIRST_PUBLISH: - lbry - .claim_list_mine() + Lbry.claim_list_mine() .then(claims => { const claim = claims .reverse() .find( - claim => - claim.name.length && - claim.name[0] != "@" && - claim.txid.length && - claim.category == "claim" + foundClaim => + foundClaim.name.length && + foundClaim.name[0] !== '@' && + foundClaim.txid.length && + foundClaim.category === 'claim' ); if (claim) { params.transaction_id = claim.txid; @@ -138,12 +113,10 @@ rewards.claimReward = function(type) { claims.length ? new Error( __( - "Please publish something and wait for confirmation by the network to claim this reward." + 'Please publish something and wait for confirmation by the network to claim this reward.' ) ) - : new Error( - __("Please publish something to claim this reward.") - ) + : new Error(__('Please publish something to claim this reward.')) ); } }) diff --git a/src/renderer/scss/_gui.scss b/src/renderer/scss/_gui.scss index fa188a37f..da3f5334c 100644 --- a/src/renderer/scss/_gui.scss +++ b/src/renderer/scss/_gui.scss @@ -1,13 +1,11 @@ @import url(https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700); -html -{ +html { height: 100%; font-size: var(--font-size); } -body -{ +body { color: var(--text-color); font-family: 'Roboto', sans-serif; line-height: var(--font-line-height); @@ -19,30 +17,25 @@ body color: var(--text-selection-color); } -#window -{ +#window { min-height: 100vh; background: var(--window-bg); } -.credit-amount--indicator -{ +.credit-amount--indicator { font-weight: 500; color: var(--color-money); } -.credit-amount--fee -{ +.credit-amount--fee { font-size: 0.9em; color: var(--color-meta-light); } -.credit-amount--bold -{ +.credit-amount--bold { font-weight: 700; } -#main-content -{ +#main-content { margin: auto; display: flex; flex-direction: column; @@ -58,8 +51,7 @@ body margin-right: auto; max-width: 100%; } - main.main--single-column - { + main.main--single-column { width: $width-page-constrained; } @@ -76,7 +68,7 @@ body background: url('../../../static/img/busy.gif') no-repeat center center; width: $width; height: $spacing-vertical; - content: ""; + content: ''; left: 50%; margin-left: -1 / 2 * $width; display: inline-block; @@ -93,30 +85,37 @@ h2 { font-size: 1.75em; } -h3 { font-size: 1.4em; } +h3 { + font-size: 1.4em; +} h4 { font-size: 1.2em; } -h5 { font-size: 1.1em; } -sup, sub { - vertical-align: baseline; - position: relative; +h5 { + font-size: 1.1em; +} +sup, +sub { + vertical-align: baseline; + position: relative; +} +sup { + top: -0.4em; +} +sub { + top: 0.4em; } -sup { top: -0.4em; } -sub { top: 0.4em; } code { font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace; background-color: var(--color-bg-alt); } -p -{ +p { margin-bottom: 0.8em; - &:last-child - { + &:last-child { margin-bottom: 0; } } @@ -137,8 +136,7 @@ p -webkit-box-orient: vertical; } -.busy-indicator -{ +.busy-indicator { background: url('../../../static/img/busy.gif') no-repeat center center; display: inline-block; margin: -1em 0; @@ -146,30 +144,26 @@ p min-height: 8px; vertical-align: middle; padding: 0 30px; - &:last-child - { + &:last-child { padding-right: 2px; } - &:first-child - { + &:first-child { padding-left: 2px; } } .help { - font-size: .85em; + font-size: 0.85em; color: var(--color-help); } -.meta -{ +.meta { font-size: 0.9em; color: var(--color-meta-light); } -.empty -{ - color:var(--color-meta-light); +.empty { + color: var(--color-meta-light); font-style: italic; } @@ -185,7 +179,6 @@ p display: block; margin-bottom: $spacing-vertical * 2/3; - text-align: right; line-height: 1; font-size: 0.85em; @@ -196,7 +189,6 @@ section.section-spaced { margin-bottom: $spacing-vertical; } -.text-center -{ +.text-center { text-align: center; } diff --git a/src/renderer/scss/_icons.scss b/src/renderer/scss/_icons.scss index 49e894145..c589a1ac5 100644 --- a/src/renderer/scss/_icons.scss +++ b/src/renderer/scss/_icons.scss @@ -1,16 +1,20 @@ @font-face { font-family: 'FontAwesome'; src: url('../../../static/font/fontawesome-webfont.eot?v=4.7.0'); - src: url('../../../static/font/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../../../static/font/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../../../static/font/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../../../static/font/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../../../static/font/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + src: url('../../../static/font/fontawesome-webfont.eot?#iefix&v=4.7.0') + format('embedded-opentype'), + url('../../../static/font/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), + url('../../../static/font/fontawesome-webfont.woff?v=4.7.0') format('woff'), + url('../../../static/font/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), + url('../../../static/font/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } -[class*="icon-"] -{ +[class*='icon-'] { display: inline-block; text-align: center; - font-family: "FontAwesome"; + font-family: 'FontAwesome'; font-style: normal; font-weight: normal; font-variant: normal; @@ -23,7 +27,6 @@ transform: translate(0, 0); } - /* Adjustments for icon size and alignment */ .icon-rocket { color: orangered; @@ -37,1639 +40,1639 @@ /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen readers do not read off random characters that represent icons */ .icon-glass:before { - content: "\f000"; + content: '\f000'; } .icon-music:before { - content: "\f001"; + content: '\f001'; } .icon-search:before { - content: "\f002"; + content: '\f002'; } .icon-envelope-o:before { - content: "\f003"; + content: '\f003'; } .icon-heart:before { - content: "\f004"; + content: '\f004'; } .icon-star:before { - content: "\f005"; + content: '\f005'; } .icon-star-o:before { - content: "\f006"; + content: '\f006'; } .icon-user:before { - content: "\f007"; + content: '\f007'; } .icon-film:before { - content: "\f008"; + content: '\f008'; } .icon-th-large:before { - content: "\f009"; + content: '\f009'; } .icon-th:before { - content: "\f00a"; + content: '\f00a'; } .icon-th-list:before { - content: "\f00b"; + content: '\f00b'; } .icon-check:before { - content: "\f00c"; + content: '\f00c'; } .icon-remove:before, .icon-close:before, .icon-times:before { - content: "\f00d"; + content: '\f00d'; } .icon-search-plus:before { - content: "\f00e"; + content: '\f00e'; } .icon-search-minus:before { - content: "\f010"; + content: '\f010'; } .icon-power-off:before { - content: "\f011"; + content: '\f011'; } .icon-signal:before { - content: "\f012"; + content: '\f012'; } .icon-gear:before, .icon-cog:before { - content: "\f013"; + content: '\f013'; } .icon-trash-o:before { - content: "\f014"; + content: '\f014'; } .icon-home:before { - content: "\f015"; + content: '\f015'; } .icon-file-o:before { - content: "\f016"; + content: '\f016'; } .icon-clock-o:before { - content: "\f017"; + content: '\f017'; } .icon-road:before { - content: "\f018"; + content: '\f018'; } .icon-download:before { - content: "\f019"; + content: '\f019'; } .icon-arrow-circle-o-down:before { - content: "\f01a"; + content: '\f01a'; } .icon-arrow-circle-o-up:before { - content: "\f01b"; + content: '\f01b'; } .icon-inbox:before { - content: "\f01c"; + content: '\f01c'; } .icon-play-circle-o:before { - content: "\f01d"; + content: '\f01d'; } .icon-rotate-right:before, .icon-repeat:before { - content: "\f01e"; + content: '\f01e'; } .icon-refresh:before { - content: "\f021"; + content: '\f021'; } .icon-list-alt:before { - content: "\f022"; + content: '\f022'; } .icon-lock:before { - content: "\f023"; + content: '\f023'; } .icon-flag:before { - content: "\f024"; + content: '\f024'; } .icon-headphones:before { - content: "\f025"; + content: '\f025'; } .icon-volume-off:before { - content: "\f026"; + content: '\f026'; } .icon-volume-down:before { - content: "\f027"; + content: '\f027'; } .icon-volume-up:before { - content: "\f028"; + content: '\f028'; } .icon-qrcode:before { - content: "\f029"; + content: '\f029'; } .icon-barcode:before { - content: "\f02a"; + content: '\f02a'; } .icon-tag:before { - content: "\f02b"; + content: '\f02b'; } .icon-tags:before { - content: "\f02c"; + content: '\f02c'; } .icon-book:before { - content: "\f02d"; + content: '\f02d'; } .icon-bookmark:before { - content: "\f02e"; + content: '\f02e'; } .icon-print:before { - content: "\f02f"; + content: '\f02f'; } .icon-camera:before { - content: "\f030"; + content: '\f030'; } .icon-font:before { - content: "\f031"; + content: '\f031'; } .icon-bold:before { - content: "\f032"; + content: '\f032'; } .icon-italic:before { - content: "\f033"; + content: '\f033'; } .icon-text-height:before { - content: "\f034"; + content: '\f034'; } .icon-text-width:before { - content: "\f035"; + content: '\f035'; } .icon-align-left:before { - content: "\f036"; + content: '\f036'; } .icon-align-center:before { - content: "\f037"; + content: '\f037'; } .icon-align-right:before { - content: "\f038"; + content: '\f038'; } .icon-align-justify:before { - content: "\f039"; + content: '\f039'; } .icon-list:before { - content: "\f03a"; + content: '\f03a'; } .icon-dedent:before, .icon-outdent:before { - content: "\f03b"; + content: '\f03b'; } .icon-indent:before { - content: "\f03c"; + content: '\f03c'; } .icon-video-camera:before { - content: "\f03d"; + content: '\f03d'; } .icon-photo:before, .icon-image:before, .icon-picture-o:before { - content: "\f03e"; + content: '\f03e'; } .icon-pencil:before { - content: "\f040"; + content: '\f040'; } .icon-map-marker:before { - content: "\f041"; + content: '\f041'; } .icon-adjust:before { - content: "\f042"; + content: '\f042'; } .icon-tint:before { - content: "\f043"; + content: '\f043'; } .icon-edit:before, .icon-pencil-square-o:before { - content: "\f044"; + content: '\f044'; } .icon-share-square-o:before { - content: "\f045"; + content: '\f045'; } .icon-check-square-o:before { - content: "\f046"; + content: '\f046'; } .icon-arrows:before { - content: "\f047"; + content: '\f047'; } .icon-step-backward:before { - content: "\f048"; + content: '\f048'; } .icon-fast-backward:before { - content: "\f049"; + content: '\f049'; } .icon-backward:before { - content: "\f04a"; + content: '\f04a'; } .icon-play:before { - content: "\f04b"; + content: '\f04b'; } .icon-pause:before { - content: "\f04c"; + content: '\f04c'; } .icon-stop:before { - content: "\f04d"; + content: '\f04d'; } .icon-forward:before { - content: "\f04e"; + content: '\f04e'; } .icon-fast-forward:before { - content: "\f050"; + content: '\f050'; } .icon-step-forward:before { - content: "\f051"; + content: '\f051'; } .icon-eject:before { - content: "\f052"; + content: '\f052'; } .icon-chevron-left:before { - content: "\f053"; + content: '\f053'; } .icon-chevron-right:before { - content: "\f054"; + content: '\f054'; } .icon-plus-circle:before { - content: "\f055"; + content: '\f055'; } .icon-minus-circle:before { - content: "\f056"; + content: '\f056'; } .icon-times-circle:before { - content: "\f057"; + content: '\f057'; } .icon-check-circle:before { - content: "\f058"; + content: '\f058'; } .icon-question-circle:before { - content: "\f059"; + content: '\f059'; } .icon-info-circle:before { - content: "\f05a"; + content: '\f05a'; } .icon-crosshairs:before { - content: "\f05b"; + content: '\f05b'; } .icon-times-circle-o:before { - content: "\f05c"; + content: '\f05c'; } .icon-check-circle-o:before { - content: "\f05d"; + content: '\f05d'; } .icon-ban:before { - content: "\f05e"; + content: '\f05e'; } .icon-arrow-left:before { - content: "\f060"; + content: '\f060'; } .icon-arrow-right:before { - content: "\f061"; + content: '\f061'; } .icon-arrow-up:before { - content: "\f062"; + content: '\f062'; } .icon-arrow-down:before { - content: "\f063"; + content: '\f063'; } .icon-mail-forward:before, .icon-share:before { - content: "\f064"; + content: '\f064'; } .icon-expand:before { - content: "\f065"; + content: '\f065'; } .icon-compress:before { - content: "\f066"; + content: '\f066'; } .icon-plus:before { - content: "\f067"; + content: '\f067'; } .icon-minus:before { - content: "\f068"; + content: '\f068'; } .icon-asterisk:before { - content: "\f069"; + content: '\f069'; } .icon-exclamation-circle:before { - content: "\f06a"; + content: '\f06a'; } .icon-gift:before { - content: "\f06b"; + content: '\f06b'; } .icon-leaf:before { - content: "\f06c"; + content: '\f06c'; } .icon-fire:before { - content: "\f06d"; + content: '\f06d'; } .icon-eye:before { - content: "\f06e"; + content: '\f06e'; } .icon-eye-slash:before { - content: "\f070"; + content: '\f070'; } .icon-warning:before, .icon-exclamation-triangle:before { - content: "\f071"; + content: '\f071'; } .icon-plane:before { - content: "\f072"; + content: '\f072'; } .icon-calendar:before { - content: "\f073"; + content: '\f073'; } .icon-random:before { - content: "\f074"; + content: '\f074'; } .icon-comment:before { - content: "\f075"; + content: '\f075'; } .icon-magnet:before { - content: "\f076"; + content: '\f076'; } .icon-chevron-up:before { - content: "\f077"; + content: '\f077'; } .icon-chevron-down:before { - content: "\f078"; + content: '\f078'; } .icon-retweet:before { - content: "\f079"; + content: '\f079'; } .icon-shopping-cart:before { - content: "\f07a"; + content: '\f07a'; } .icon-folder:before { - content: "\f07b"; + content: '\f07b'; } .icon-folder-open:before { - content: "\f07c"; + content: '\f07c'; } .icon-arrows-v:before { - content: "\f07d"; + content: '\f07d'; } .icon-arrows-h:before { - content: "\f07e"; + content: '\f07e'; } .icon-bar-chart-o:before, .icon-bar-chart:before { - content: "\f080"; + content: '\f080'; } .icon-twitter-square:before { - content: "\f081"; + content: '\f081'; } .icon-facebook-square:before { - content: "\f082"; + content: '\f082'; } .icon-camera-retro:before { - content: "\f083"; + content: '\f083'; } .icon-key:before { - content: "\f084"; + content: '\f084'; } .icon-gears:before, .icon-cogs:before { - content: "\f085"; + content: '\f085'; } .icon-comments:before { - content: "\f086"; + content: '\f086'; } .icon-thumbs-o-up:before { - content: "\f087"; + content: '\f087'; } .icon-thumbs-o-down:before { - content: "\f088"; + content: '\f088'; } .icon-star-half:before { - content: "\f089"; + content: '\f089'; } .icon-heart-o:before { - content: "\f08a"; + content: '\f08a'; } .icon-sign-out:before { - content: "\f08b"; + content: '\f08b'; } .icon-linkedin-square:before { - content: "\f08c"; + content: '\f08c'; } .icon-thumb-tack:before { - content: "\f08d"; + content: '\f08d'; } .icon-external-link:before { - content: "\f08e"; + content: '\f08e'; } .icon-sign-in:before { - content: "\f090"; + content: '\f090'; } .icon-trophy:before { - content: "\f091"; + content: '\f091'; } .icon-github-square:before { - content: "\f092"; + content: '\f092'; } .icon-upload:before { - content: "\f093"; + content: '\f093'; } .icon-lemon-o:before { - content: "\f094"; + content: '\f094'; } .icon-phone:before { - content: "\f095"; + content: '\f095'; } .icon-square-o:before { - content: "\f096"; + content: '\f096'; } .icon-bookmark-o:before { - content: "\f097"; + content: '\f097'; } .icon-phone-square:before { - content: "\f098"; + content: '\f098'; } .icon-twitter:before { - content: "\f099"; + content: '\f099'; } .icon-facebook-f:before, .icon-facebook:before { - content: "\f09a"; + content: '\f09a'; } .icon-github:before { - content: "\f09b"; + content: '\f09b'; } .icon-unlock:before { - content: "\f09c"; + content: '\f09c'; } .icon-credit-card:before { - content: "\f09d"; + content: '\f09d'; } .icon-rss:before { - content: "\f09e"; + content: '\f09e'; } .icon-hdd-o:before { - content: "\f0a0"; + content: '\f0a0'; } .icon-bullhorn:before { - content: "\f0a1"; + content: '\f0a1'; } .icon-bell:before { - content: "\f0f3"; + content: '\f0f3'; } .icon-certificate:before { - content: "\f0a3"; + content: '\f0a3'; } .icon-hand-o-right:before { - content: "\f0a4"; + content: '\f0a4'; } .icon-hand-o-left:before { - content: "\f0a5"; + content: '\f0a5'; } .icon-hand-o-up:before { - content: "\f0a6"; + content: '\f0a6'; } .icon-hand-o-down:before { - content: "\f0a7"; + content: '\f0a7'; } .icon-arrow-circle-left:before { - content: "\f0a8"; + content: '\f0a8'; } .icon-arrow-circle-right:before { - content: "\f0a9"; + content: '\f0a9'; } .icon-arrow-circle-up:before { - content: "\f0aa"; + content: '\f0aa'; } .icon-arrow-circle-down:before { - content: "\f0ab"; + content: '\f0ab'; } .icon-globe:before { - content: "\f0ac"; + content: '\f0ac'; } .icon-wrench:before { - content: "\f0ad"; + content: '\f0ad'; } .icon-tasks:before { - content: "\f0ae"; + content: '\f0ae'; } .icon-filter:before { - content: "\f0b0"; + content: '\f0b0'; } .icon-briefcase:before { - content: "\f0b1"; + content: '\f0b1'; } .icon-arrows-alt:before { - content: "\f0b2"; + content: '\f0b2'; } .icon-group:before, .icon-users:before { - content: "\f0c0"; + content: '\f0c0'; } .icon-chain:before, .icon-link:before { - content: "\f0c1"; + content: '\f0c1'; } .icon-cloud:before { - content: "\f0c2"; + content: '\f0c2'; } .icon-flask:before { - content: "\f0c3"; + content: '\f0c3'; } .icon-cut:before, .icon-scissors:before { - content: "\f0c4"; + content: '\f0c4'; } .icon-copy:before, .icon-files-o:before { - content: "\f0c5"; + content: '\f0c5'; } .icon-paperclip:before { - content: "\f0c6"; + content: '\f0c6'; } .icon-save:before, .icon-floppy-o:before { - content: "\f0c7"; + content: '\f0c7'; } .icon-square:before { - content: "\f0c8"; + content: '\f0c8'; } .icon-navicon:before, .icon-reorder:before, .icon-bars:before { - content: "\f0c9"; + content: '\f0c9'; } .icon-list-ul:before { - content: "\f0ca"; + content: '\f0ca'; } .icon-list-ol:before { - content: "\f0cb"; + content: '\f0cb'; } .icon-strikethrough:before { - content: "\f0cc"; + content: '\f0cc'; } .icon-underline:before { - content: "\f0cd"; + content: '\f0cd'; } .icon-table:before { - content: "\f0ce"; + content: '\f0ce'; } .icon-magic:before { - content: "\f0d0"; + content: '\f0d0'; } .icon-truck:before { - content: "\f0d1"; + content: '\f0d1'; } .icon-pinterest:before { - content: "\f0d2"; + content: '\f0d2'; } .icon-pinterest-square:before { - content: "\f0d3"; + content: '\f0d3'; } .icon-google-plus-square:before { - content: "\f0d4"; + content: '\f0d4'; } .icon-google-plus:before { - content: "\f0d5"; + content: '\f0d5'; } .icon-money:before { - content: "\f0d6"; + content: '\f0d6'; } .icon-caret-down:before { - content: "\f0d7"; + content: '\f0d7'; } .icon-caret-up:before { - content: "\f0d8"; + content: '\f0d8'; } .icon-caret-left:before { - content: "\f0d9"; + content: '\f0d9'; } .icon-caret-right:before { - content: "\f0da"; + content: '\f0da'; } .icon-columns:before { - content: "\f0db"; + content: '\f0db'; } .icon-unsorted:before, .icon-sort:before { - content: "\f0dc"; + content: '\f0dc'; } .icon-sort-down:before, .icon-sort-desc:before { - content: "\f0dd"; + content: '\f0dd'; } .icon-sort-up:before, .icon-sort-asc:before { - content: "\f0de"; + content: '\f0de'; } .icon-envelope:before { - content: "\f0e0"; + content: '\f0e0'; } .icon-linkedin:before { - content: "\f0e1"; + content: '\f0e1'; } .icon-rotate-left:before, .icon-undo:before { - content: "\f0e2"; + content: '\f0e2'; } .icon-legal:before, .icon-gavel:before { - content: "\f0e3"; + content: '\f0e3'; } .icon-dashboard:before, .icon-tachometer:before { - content: "\f0e4"; + content: '\f0e4'; } .icon-comment-o:before { - content: "\f0e5"; + content: '\f0e5'; } .icon-comments-o:before { - content: "\f0e6"; + content: '\f0e6'; } .icon-flash:before, .icon-bolt:before { - content: "\f0e7"; + content: '\f0e7'; } .icon-sitemap:before { - content: "\f0e8"; + content: '\f0e8'; } .icon-umbrella:before { - content: "\f0e9"; + content: '\f0e9'; } .icon-paste:before, .icon-clipboard:before { - content: "\f0ea"; + content: '\f0ea'; } .icon-lightbulb-o:before { - content: "\f0eb"; + content: '\f0eb'; } .icon-exchange:before { - content: "\f0ec"; + content: '\f0ec'; } .icon-cloud-download:before { - content: "\f0ed"; + content: '\f0ed'; } .icon-cloud-upload:before { - content: "\f0ee"; + content: '\f0ee'; } .icon-user-md:before { - content: "\f0f0"; + content: '\f0f0'; } .icon-stethoscope:before { - content: "\f0f1"; + content: '\f0f1'; } .icon-suitcase:before { - content: "\f0f2"; + content: '\f0f2'; } .icon-bell-o:before { - content: "\f0a2"; + content: '\f0a2'; } .icon-coffee:before { - content: "\f0f4"; + content: '\f0f4'; } .icon-cutlery:before { - content: "\f0f5"; + content: '\f0f5'; } .icon-file-text-o:before { - content: "\f0f6"; + content: '\f0f6'; } .icon-building-o:before { - content: "\f0f7"; + content: '\f0f7'; } .icon-hospital-o:before { - content: "\f0f8"; + content: '\f0f8'; } .icon-ambulance:before { - content: "\f0f9"; + content: '\f0f9'; } .icon-medkit:before { - content: "\f0fa"; + content: '\f0fa'; } .icon-fighter-jet:before { - content: "\f0fb"; + content: '\f0fb'; } .icon-beer:before { - content: "\f0fc"; + content: '\f0fc'; } .icon-h-square:before { - content: "\f0fd"; + content: '\f0fd'; } .icon-plus-square:before { - content: "\f0fe"; + content: '\f0fe'; } .icon-angle-double-left:before { - content: "\f100"; + content: '\f100'; } .icon-angle-double-right:before { - content: "\f101"; + content: '\f101'; } .icon-angle-double-up:before { - content: "\f102"; + content: '\f102'; } .icon-angle-double-down:before { - content: "\f103"; + content: '\f103'; } .icon-angle-left:before { - content: "\f104"; + content: '\f104'; } .icon-angle-right:before { - content: "\f105"; + content: '\f105'; } .icon-angle-up:before { - content: "\f106"; + content: '\f106'; } .icon-angle-down:before { - content: "\f107"; + content: '\f107'; } .icon-desktop:before { - content: "\f108"; + content: '\f108'; } .icon-laptop:before { - content: "\f109"; + content: '\f109'; } .icon-tablet:before { - content: "\f10a"; + content: '\f10a'; } .icon-mobile-phone:before, .icon-mobile:before { - content: "\f10b"; + content: '\f10b'; } .icon-circle-o:before { - content: "\f10c"; + content: '\f10c'; } .icon-quote-left:before { - content: "\f10d"; + content: '\f10d'; } .icon-quote-right:before { - content: "\f10e"; + content: '\f10e'; } .icon-spinner:before { - content: "\f110"; + content: '\f110'; } .icon-circle:before { - content: "\f111"; + content: '\f111'; } .icon-mail-reply:before, .icon-reply:before { - content: "\f112"; + content: '\f112'; } .icon-github-alt:before { - content: "\f113"; + content: '\f113'; } .icon-folder-o:before { - content: "\f114"; + content: '\f114'; } .icon-folder-open-o:before { - content: "\f115"; + content: '\f115'; } .icon-smile-o:before { - content: "\f118"; + content: '\f118'; } .icon-frown-o:before { - content: "\f119"; + content: '\f119'; } .icon-meh-o:before { - content: "\f11a"; + content: '\f11a'; } .icon-gamepad:before { - content: "\f11b"; + content: '\f11b'; } .icon-keyboard-o:before { - content: "\f11c"; + content: '\f11c'; } .icon-flag-o:before { - content: "\f11d"; + content: '\f11d'; } .icon-flag-checkered:before { - content: "\f11e"; + content: '\f11e'; } .icon-terminal:before { - content: "\f120"; + content: '\f120'; } .icon-code:before { - content: "\f121"; + content: '\f121'; } .icon-mail-reply-all:before, .icon-reply-all:before { - content: "\f122"; + content: '\f122'; } .icon-star-half-empty:before, .icon-star-half-full:before, .icon-star-half-o:before { - content: "\f123"; + content: '\f123'; } .icon-location-arrow:before { - content: "\f124"; + content: '\f124'; } .icon-crop:before { - content: "\f125"; + content: '\f125'; } .icon-code-fork:before { - content: "\f126"; + content: '\f126'; } .icon-unlink:before, .icon-chain-broken:before { - content: "\f127"; + content: '\f127'; } .icon-question:before { - content: "\f128"; + content: '\f128'; } .icon-info:before { - content: "\f129"; + content: '\f129'; } .icon-exclamation:before { - content: "\f12a"; + content: '\f12a'; } .icon-superscript:before { - content: "\f12b"; + content: '\f12b'; } .icon-subscript:before { - content: "\f12c"; + content: '\f12c'; } .icon-eraser:before { - content: "\f12d"; + content: '\f12d'; } .icon-puzzle-piece:before { - content: "\f12e"; + content: '\f12e'; } .icon-microphone:before { - content: "\f130"; + content: '\f130'; } .icon-microphone-slash:before { - content: "\f131"; + content: '\f131'; } .icon-shield:before { - content: "\f132"; + content: '\f132'; } .icon-calendar-o:before { - content: "\f133"; + content: '\f133'; } .icon-fire-extinguisher:before { - content: "\f134"; + content: '\f134'; } .icon-rocket:before { - content: "\f135"; + content: '\f135'; } .icon-maxcdn:before { - content: "\f136"; + content: '\f136'; } .icon-chevron-circle-left:before { - content: "\f137"; + content: '\f137'; } .icon-chevron-circle-right:before { - content: "\f138"; + content: '\f138'; } .icon-chevron-circle-up:before { - content: "\f139"; + content: '\f139'; } .icon-chevron-circle-down:before { - content: "\f13a"; + content: '\f13a'; } .icon-html5:before { - content: "\f13b"; + content: '\f13b'; } .icon-css3:before { - content: "\f13c"; + content: '\f13c'; } .icon-anchor:before { - content: "\f13d"; + content: '\f13d'; } .icon-unlock-alt:before { - content: "\f13e"; + content: '\f13e'; } .icon-bullseye:before { - content: "\f140"; + content: '\f140'; } .icon-ellipsis-h:before { - content: "\f141"; + content: '\f141'; } .icon-ellipsis-v:before { - content: "\f142"; + content: '\f142'; } .icon-rss-square:before { - content: "\f143"; + content: '\f143'; } .icon-play-circle:before { - content: "\f144"; + content: '\f144'; } .icon-ticket:before { - content: "\f145"; + content: '\f145'; } .icon-minus-square:before { - content: "\f146"; + content: '\f146'; } .icon-minus-square-o:before { - content: "\f147"; + content: '\f147'; } .icon-level-up:before { - content: "\f148"; + content: '\f148'; } .icon-level-down:before { - content: "\f149"; + content: '\f149'; } .icon-check-square:before { - content: "\f14a"; + content: '\f14a'; } .icon-pencil-square:before { - content: "\f14b"; + content: '\f14b'; } .icon-external-link-square:before { - content: "\f14c"; + content: '\f14c'; } .icon-share-square:before { - content: "\f14d"; + content: '\f14d'; } .icon-compass:before { - content: "\f14e"; + content: '\f14e'; } .icon-toggle-down:before, .icon-caret-square-o-down:before { - content: "\f150"; + content: '\f150'; } .icon-toggle-up:before, .icon-caret-square-o-up:before { - content: "\f151"; + content: '\f151'; } .icon-toggle-right:before, .icon-caret-square-o-right:before { - content: "\f152"; + content: '\f152'; } .icon-euro:before, .icon-eur:before { - content: "\f153"; + content: '\f153'; } .icon-gbp:before { - content: "\f154"; + content: '\f154'; } .icon-dollar:before, .icon-usd:before { - content: "\f155"; + content: '\f155'; } .icon-rupee:before, .icon-inr:before { - content: "\f156"; + content: '\f156'; } .icon-cny:before, .icon-rmb:before, .icon-yen:before, .icon-jpy:before { - content: "\f157"; + content: '\f157'; } .icon-ruble:before, .icon-rouble:before, .icon-rub:before { - content: "\f158"; + content: '\f158'; } .icon-won:before, .icon-krw:before { - content: "\f159"; + content: '\f159'; } .icon-bitcoin:before, .icon-btc:before { - content: "\f15a"; + content: '\f15a'; } .icon-file:before { - content: "\f15b"; + content: '\f15b'; } .icon-file-text:before { - content: "\f15c"; + content: '\f15c'; } .icon-sort-alpha-asc:before { - content: "\f15d"; + content: '\f15d'; } .icon-sort-alpha-desc:before { - content: "\f15e"; + content: '\f15e'; } .icon-sort-amount-asc:before { - content: "\f160"; + content: '\f160'; } .icon-sort-amount-desc:before { - content: "\f161"; + content: '\f161'; } .icon-sort-numeric-asc:before { - content: "\f162"; + content: '\f162'; } .icon-sort-numeric-desc:before { - content: "\f163"; + content: '\f163'; } .icon-thumbs-up:before { - content: "\f164"; + content: '\f164'; } .icon-thumbs-down:before { - content: "\f165"; + content: '\f165'; } .icon-youtube-square:before { - content: "\f166"; + content: '\f166'; } .icon-youtube:before { - content: "\f167"; + content: '\f167'; } .icon-xing:before { - content: "\f168"; + content: '\f168'; } .icon-xing-square:before { - content: "\f169"; + content: '\f169'; } .icon-youtube-play:before { - content: "\f16a"; + content: '\f16a'; } .icon-dropbox:before { - content: "\f16b"; + content: '\f16b'; } .icon-stack-overflow:before { - content: "\f16c"; + content: '\f16c'; } .icon-instagram:before { - content: "\f16d"; + content: '\f16d'; } .icon-flickr:before { - content: "\f16e"; + content: '\f16e'; } .icon-adn:before { - content: "\f170"; + content: '\f170'; } .icon-bitbucket:before { - content: "\f171"; + content: '\f171'; } .icon-bitbucket-square:before { - content: "\f172"; + content: '\f172'; } .icon-tumblr:before { - content: "\f173"; + content: '\f173'; } .icon-tumblr-square:before { - content: "\f174"; + content: '\f174'; } .icon-long-arrow-down:before { - content: "\f175"; + content: '\f175'; } .icon-long-arrow-up:before { - content: "\f176"; + content: '\f176'; } .icon-long-arrow-left:before { - content: "\f177"; + content: '\f177'; } .icon-long-arrow-right:before { - content: "\f178"; + content: '\f178'; } .icon-apple:before { - content: "\f179"; + content: '\f179'; } .icon-windows:before { - content: "\f17a"; + content: '\f17a'; } .icon-android:before { - content: "\f17b"; + content: '\f17b'; } .icon-linux:before { - content: "\f17c"; + content: '\f17c'; } .icon-dribbble:before { - content: "\f17d"; + content: '\f17d'; } .icon-skype:before { - content: "\f17e"; + content: '\f17e'; } .icon-foursquare:before { - content: "\f180"; + content: '\f180'; } .icon-trello:before { - content: "\f181"; + content: '\f181'; } .icon-female:before { - content: "\f182"; + content: '\f182'; } .icon-male:before { - content: "\f183"; + content: '\f183'; } .icon-gittip:before, .icon-gratipay:before { - content: "\f184"; + content: '\f184'; } .icon-sun-o:before { - content: "\f185"; + content: '\f185'; } .icon-moon-o:before { - content: "\f186"; + content: '\f186'; } .icon-archive:before { - content: "\f187"; + content: '\f187'; } .icon-bug:before { - content: "\f188"; + content: '\f188'; } .icon-vk:before { - content: "\f189"; + content: '\f189'; } .icon-weibo:before { - content: "\f18a"; + content: '\f18a'; } .icon-renren:before { - content: "\f18b"; + content: '\f18b'; } .icon-pagelines:before { - content: "\f18c"; + content: '\f18c'; } .icon-stack-exchange:before { - content: "\f18d"; + content: '\f18d'; } .icon-arrow-circle-o-right:before { - content: "\f18e"; + content: '\f18e'; } .icon-arrow-circle-o-left:before { - content: "\f190"; + content: '\f190'; } .icon-toggle-left:before, .icon-caret-square-o-left:before { - content: "\f191"; + content: '\f191'; } .icon-dot-circle-o:before { - content: "\f192"; + content: '\f192'; } .icon-wheelchair:before { - content: "\f193"; + content: '\f193'; } .icon-vimeo-square:before { - content: "\f194"; + content: '\f194'; } .icon-turkish-lira:before, .icon-try:before { - content: "\f195"; + content: '\f195'; } .icon-plus-square-o:before { - content: "\f196"; + content: '\f196'; } .icon-space-shuttle:before { - content: "\f197"; + content: '\f197'; } .icon-slack:before { - content: "\f198"; + content: '\f198'; } .icon-envelope-square:before { - content: "\f199"; + content: '\f199'; } .icon-wordpress:before { - content: "\f19a"; + content: '\f19a'; } .icon-openid:before { - content: "\f19b"; + content: '\f19b'; } .icon-institution:before, .icon-bank:before, .icon-university:before { - content: "\f19c"; + content: '\f19c'; } .icon-mortar-board:before, .icon-graduation-cap:before { - content: "\f19d"; + content: '\f19d'; } .icon-yahoo:before { - content: "\f19e"; + content: '\f19e'; } .icon-google:before { - content: "\f1a0"; + content: '\f1a0'; } .icon-reddit:before { - content: "\f1a1"; + content: '\f1a1'; } .icon-reddit-square:before { - content: "\f1a2"; + content: '\f1a2'; } .icon-stumbleupon-circle:before { - content: "\f1a3"; + content: '\f1a3'; } .icon-stumbleupon:before { - content: "\f1a4"; + content: '\f1a4'; } .icon-delicious:before { - content: "\f1a5"; + content: '\f1a5'; } .icon-digg:before { - content: "\f1a6"; + content: '\f1a6'; } .icon-pied-piper:before { - content: "\f1a7"; + content: '\f1a7'; } .icon-pied-piper-alt:before { - content: "\f1a8"; + content: '\f1a8'; } .icon-drupal:before { - content: "\f1a9"; + content: '\f1a9'; } .icon-joomla:before { - content: "\f1aa"; + content: '\f1aa'; } .icon-language:before { - content: "\f1ab"; + content: '\f1ab'; } .icon-fax:before { - content: "\f1ac"; + content: '\f1ac'; } .icon-building:before { - content: "\f1ad"; + content: '\f1ad'; } .icon-child:before { - content: "\f1ae"; + content: '\f1ae'; } .icon-paw:before { - content: "\f1b0"; + content: '\f1b0'; } .icon-spoon:before { - content: "\f1b1"; + content: '\f1b1'; } .icon-cube:before { - content: "\f1b2"; + content: '\f1b2'; } .icon-cubes:before { - content: "\f1b3"; + content: '\f1b3'; } .icon-behance:before { - content: "\f1b4"; + content: '\f1b4'; } .icon-behance-square:before { - content: "\f1b5"; + content: '\f1b5'; } .icon-steam:before { - content: "\f1b6"; + content: '\f1b6'; } .icon-steam-square:before { - content: "\f1b7"; + content: '\f1b7'; } .icon-recycle:before { - content: "\f1b8"; + content: '\f1b8'; } .icon-automobile:before, .icon-car:before { - content: "\f1b9"; + content: '\f1b9'; } .icon-cab:before, .icon-taxi:before { - content: "\f1ba"; + content: '\f1ba'; } .icon-tree:before { - content: "\f1bb"; + content: '\f1bb'; } .icon-spotify:before { - content: "\f1bc"; + content: '\f1bc'; } .icon-deviantart:before { - content: "\f1bd"; + content: '\f1bd'; } .icon-soundcloud:before { - content: "\f1be"; + content: '\f1be'; } .icon-database:before { - content: "\f1c0"; + content: '\f1c0'; } .icon-file-pdf-o:before { - content: "\f1c1"; + content: '\f1c1'; } .icon-file-word-o:before { - content: "\f1c2"; + content: '\f1c2'; } .icon-file-excel-o:before { - content: "\f1c3"; + content: '\f1c3'; } .icon-file-powerpoint-o:before { - content: "\f1c4"; + content: '\f1c4'; } .icon-file-photo-o:before, .icon-file-picture-o:before, .icon-file-image-o:before { - content: "\f1c5"; + content: '\f1c5'; } .icon-file-zip-o:before, .icon-file-archive-o:before { - content: "\f1c6"; + content: '\f1c6'; } .icon-file-sound-o:before, .icon-file-audio-o:before { - content: "\f1c7"; + content: '\f1c7'; } .icon-file-movie-o:before, .icon-file-video-o:before { - content: "\f1c8"; + content: '\f1c8'; } .icon-file-code-o:before { - content: "\f1c9"; + content: '\f1c9'; } .icon-vine:before { - content: "\f1ca"; + content: '\f1ca'; } .icon-codepen:before { - content: "\f1cb"; + content: '\f1cb'; } .icon-jsfiddle:before { - content: "\f1cc"; + content: '\f1cc'; } .icon-life-bouy:before, .icon-life-buoy:before, .icon-life-saver:before, .icon-support:before, .icon-life-ring:before { - content: "\f1cd"; + content: '\f1cd'; } .icon-circle-o-notch:before { - content: "\f1ce"; + content: '\f1ce'; } .icon-ra:before, .icon-rebel:before { - content: "\f1d0"; + content: '\f1d0'; } .icon-ge:before, .icon-empire:before { - content: "\f1d1"; + content: '\f1d1'; } .icon-git-square:before { - content: "\f1d2"; + content: '\f1d2'; } .icon-git:before { - content: "\f1d3"; + content: '\f1d3'; } .icon-hacker-news:before { - content: "\f1d4"; + content: '\f1d4'; } .icon-tencent-weibo:before { - content: "\f1d5"; + content: '\f1d5'; } .icon-qq:before { - content: "\f1d6"; + content: '\f1d6'; } .icon-wechat:before, .icon-weixin:before { - content: "\f1d7"; + content: '\f1d7'; } .icon-send:before, .icon-paper-plane:before { - content: "\f1d8"; + content: '\f1d8'; } .icon-send-o:before, .icon-paper-plane-o:before { - content: "\f1d9"; + content: '\f1d9'; } .icon-history:before { - content: "\f1da"; + content: '\f1da'; } .icon-genderless:before, .icon-circle-thin:before { - content: "\f1db"; + content: '\f1db'; } .icon-header:before { - content: "\f1dc"; + content: '\f1dc'; } .icon-paragraph:before { - content: "\f1dd"; + content: '\f1dd'; } .icon-sliders:before { - content: "\f1de"; + content: '\f1de'; } .icon-share-alt:before { - content: "\f1e0"; + content: '\f1e0'; } .icon-share-alt-square:before { - content: "\f1e1"; + content: '\f1e1'; } .icon-bomb:before { - content: "\f1e2"; + content: '\f1e2'; } .icon-soccer-ball-o:before, .icon-futbol-o:before { - content: "\f1e3"; + content: '\f1e3'; } .icon-tty:before { - content: "\f1e4"; + content: '\f1e4'; } .icon-binoculars:before { - content: "\f1e5"; + content: '\f1e5'; } .icon-plug:before { - content: "\f1e6"; + content: '\f1e6'; } .icon-slideshare:before { - content: "\f1e7"; + content: '\f1e7'; } .icon-twitch:before { - content: "\f1e8"; + content: '\f1e8'; } .icon-yelp:before { - content: "\f1e9"; + content: '\f1e9'; } .icon-newspaper-o:before { - content: "\f1ea"; + content: '\f1ea'; } .icon-wifi:before { - content: "\f1eb"; + content: '\f1eb'; } .icon-calculator:before { - content: "\f1ec"; + content: '\f1ec'; } .icon-paypal:before { - content: "\f1ed"; + content: '\f1ed'; } .icon-google-wallet:before { - content: "\f1ee"; + content: '\f1ee'; } .icon-cc-visa:before { - content: "\f1f0"; + content: '\f1f0'; } .icon-cc-mastercard:before { - content: "\f1f1"; + content: '\f1f1'; } .icon-cc-discover:before { - content: "\f1f2"; + content: '\f1f2'; } .icon-cc-amex:before { - content: "\f1f3"; + content: '\f1f3'; } .icon-cc-paypal:before { - content: "\f1f4"; + content: '\f1f4'; } .icon-cc-stripe:before { - content: "\f1f5"; + content: '\f1f5'; } .icon-bell-slash:before { - content: "\f1f6"; + content: '\f1f6'; } .icon-bell-slash-o:before { - content: "\f1f7"; + content: '\f1f7'; } .icon-trash:before { - content: "\f1f8"; + content: '\f1f8'; } .icon-copyright:before { - content: "\f1f9"; + content: '\f1f9'; } .icon-at:before { - content: "\f1fa"; + content: '\f1fa'; } .icon-eyedropper:before { - content: "\f1fb"; + content: '\f1fb'; } .icon-paint-brush:before { - content: "\f1fc"; + content: '\f1fc'; } .icon-birthday-cake:before { - content: "\f1fd"; + content: '\f1fd'; } .icon-area-chart:before { - content: "\f1fe"; + content: '\f1fe'; } .icon-pie-chart:before { - content: "\f200"; + content: '\f200'; } .icon-line-chart:before { - content: "\f201"; + content: '\f201'; } .icon-lastfm:before { - content: "\f202"; + content: '\f202'; } .icon-lastfm-square:before { - content: "\f203"; + content: '\f203'; } .icon-toggle-off:before { - content: "\f204"; + content: '\f204'; } .icon-toggle-on:before { - content: "\f205"; + content: '\f205'; } .icon-bicycle:before { - content: "\f206"; + content: '\f206'; } .icon-bus:before { - content: "\f207"; + content: '\f207'; } .icon-ioxhost:before { - content: "\f208"; + content: '\f208'; } .icon-angellist:before { - content: "\f209"; + content: '\f209'; } .icon-cc:before { - content: "\f20a"; + content: '\f20a'; } .icon-shekel:before, .icon-sheqel:before, .icon-ils:before { - content: "\f20b"; + content: '\f20b'; } .icon-meanpath:before { - content: "\f20c"; + content: '\f20c'; } .icon-buysellads:before { - content: "\f20d"; + content: '\f20d'; } .icon-connectdevelop:before { - content: "\f20e"; + content: '\f20e'; } .icon-dashcube:before { - content: "\f210"; + content: '\f210'; } .icon-forumbee:before { - content: "\f211"; + content: '\f211'; } .icon-leanpub:before { - content: "\f212"; + content: '\f212'; } .icon-sellsy:before { - content: "\f213"; + content: '\f213'; } .icon-shirtsinbulk:before { - content: "\f214"; + content: '\f214'; } .icon-simplybuilt:before { - content: "\f215"; + content: '\f215'; } .icon-skyatlas:before { - content: "\f216"; + content: '\f216'; } .icon-cart-plus:before { - content: "\f217"; + content: '\f217'; } .icon-cart-arrow-down:before { - content: "\f218"; + content: '\f218'; } .icon-diamond:before { - content: "\f219"; + content: '\f219'; } .icon-ship:before { - content: "\f21a"; + content: '\f21a'; } .icon-user-secret:before { - content: "\f21b"; + content: '\f21b'; } .icon-motorcycle:before { - content: "\f21c"; + content: '\f21c'; } .icon-street-view:before { - content: "\f21d"; + content: '\f21d'; } .icon-heartbeat:before { - content: "\f21e"; + content: '\f21e'; } .icon-venus:before { - content: "\f221"; + content: '\f221'; } .icon-mars:before { - content: "\f222"; + content: '\f222'; } .icon-mercury:before { - content: "\f223"; + content: '\f223'; } .icon-transgender:before { - content: "\f224"; + content: '\f224'; } .icon-transgender-alt:before { - content: "\f225"; + content: '\f225'; } .icon-venus-double:before { - content: "\f226"; + content: '\f226'; } .icon-mars-double:before { - content: "\f227"; + content: '\f227'; } .icon-venus-mars:before { - content: "\f228"; + content: '\f228'; } .icon-mars-stroke:before { - content: "\f229"; + content: '\f229'; } .icon-mars-stroke-v:before { - content: "\f22a"; + content: '\f22a'; } .icon-mars-stroke-h:before { - content: "\f22b"; + content: '\f22b'; } .icon-neuter:before { - content: "\f22c"; + content: '\f22c'; } .icon-facebook-official:before { - content: "\f230"; + content: '\f230'; } .icon-pinterest-p:before { - content: "\f231"; + content: '\f231'; } .icon-whatsapp:before { - content: "\f232"; + content: '\f232'; } .icon-server:before { - content: "\f233"; + content: '\f233'; } .icon-user-plus:before { - content: "\f234"; + content: '\f234'; } .icon-user-times:before { - content: "\f235"; + content: '\f235'; } .icon-hotel:before, .icon-bed:before { - content: "\f236"; + content: '\f236'; } .icon-viacoin:before { - content: "\f237"; + content: '\f237'; } .icon-train:before { - content: "\f238"; + content: '\f238'; } .icon-subway:before { - content: "\f239"; + content: '\f239'; } .icon-medium:before { - content: "\f23a"; + content: '\f23a'; } .icon-address-book:before { - content: "\f2b9"; + content: '\f2b9'; } .icon-envelope-open:before { - content: "\f2b6"; + content: '\f2b6'; } diff --git a/src/renderer/scss/_reset.scss b/src/renderer/scss/_reset.scss index e951875a8..b93394c96 100644 --- a/src/renderer/scss/_reset.scss +++ b/src/renderer/scss/_reset.scss @@ -1,39 +1,70 @@ -body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, select, textarea, p, blockquote, th, td, iframe -{ - margin:0; - padding:0; +body, +div, +dl, +dt, +dd, +ul, +ol, +li, +h1, +h2, +h3, +h4, +h5, +h6, +pre, +code, +form, +fieldset, +legend, +input, +select, +textarea, +p, +blockquote, +th, +td, +iframe { + margin: 0; + padding: 0; } -:focus -{ +:focus { outline: 0; } input::-webkit-search-cancel-button { /* Remove default */ -webkit-appearance: none; } -table -{ +table { border-collapse: collapse; - border-spacing:0; + border-spacing: 0; } -fieldset, img, iframe -{ - border: 0; +fieldset, +img, +iframe { + border: 0; } -h1, h2, h3, h4, h5, h6 -{ - font-weight:normal; +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: normal; } -ol, ul -{ +ol, +ul { + list-style-position: inside; + > li { list-style-position: inside; - > li { list-style-position: inside; } + } } -input, textarea, select -{ - font-family:inherit; - font-size:inherit; - font-weight:inherit; +input, +textarea, +select { + font-family: inherit; + font-size: inherit; + font-weight: inherit; border: 0 none; } img { @@ -42,8 +73,7 @@ img { vertical-align: middle; -ms-interpolation-mode: bicubic; } -a -{ - color: inherit; - text-decoration: none; -} \ No newline at end of file +a { + color: inherit; + text-decoration: none; +} diff --git a/src/renderer/scss/_vars.scss b/src/renderer/scss/_vars.scss index b9e0f49e8..15436a5b1 100644 --- a/src/renderer/scss/_vars.scss +++ b/src/renderer/scss/_vars.scss @@ -6,28 +6,27 @@ $width-page-constrained: 800px; $text-color: #000; :root { - /* Colors */ - --color-brand: #155B4A; - --color-primary: #155B4A; - --color-primary-light: saturate(lighten(#155B4A, 50%), 20%); - --color-light-alt: hsl(hue(#155B4A), 15, 85); - --color-dark-overlay: rgba(32,32,32,0.9); + --color-brand: #155b4a; + --color-primary: #155b4a; + --color-primary-light: saturate(lighten(#155b4a, 50%), 20%); + --color-light-alt: hsl(hue(#155b4a), 15, 85); + --color-dark-overlay: rgba(32, 32, 32, 0.9); --color-help: rgba(0, 0, 0, 0.54); --color-notice: #8a6d3b; --color-error: #a94442; --color-load-screen-text: #c3c3c3; --color-meta-light: #505050; - --color-money: #216C2A; + --color-money: #216c2a; --color-download: rgba(0, 0, 0, 0.75); --color-canvas: #f5f5f5; --color-bg: #ffffff; - --color-bg-alt: #D9D9D9; + --color-bg-alt: #d9d9d9; /* Misc */ --content-max-width: 1000px; --nsfw-blur-intensity: 20px; - --height-video-embedded: $width-page-constrained * 9 / 16 ; + --height-video-embedded: $width-page-constrained * 9 / 16; /* Font */ --font-size: 16px; @@ -35,20 +34,21 @@ $text-color: #000; --font-size-subtext-multiple: 0.82; /* Shadows */ - --box-shadow-layer: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); - --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); + --box-shadow-layer: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + --box-shadow-focus: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2), + 2px 3px 7px 0 rgba(0, 0, 0, 0.12); /* Transition */ - --transition-duration: .225s; + --transition-duration: 0.225s; --transition-type: ease; /* Text */ --text-color: $text-color; - --text-help-color: #EEE; + --text-help-color: #eee; --text-max-width: 660px; --text-link-padding: 4px; - --text-selection-bg: rgba(saturate(lighten(#155B4A, 20%), 20%), 1); // temp color - --text-selection-color: #FFF; + --text-selection-bg: rgba(saturate(lighten(#155b4a, 20%), 20%), 1); // temp color + --text-selection-color: #fff; /* Window */ --window-bg: var(--color-canvas); @@ -72,7 +72,7 @@ $text-color: #000; /* input:hover */ --input-hover-border-color: rgba(0, 0, 0, 0.87); - /* input:placeholder */ + /* input:placeholder */ --input-placeholder-color: rgba(0, 0, 0, 0.42); --input-placeholder-opacity: 1; @@ -82,9 +82,9 @@ $text-color: #000; /* Button */ --button-bg: var(--color-bg-alt); - --button-color: #FFF; + --button-color: #fff; --button-primary-bg: var(--color-primary); - --button-primary-color: #FFF; + --button-primary-color: #fff; --button-padding: $spacing-vertical * 2/3; --button-height: $spacing-vertical * 1.5; --button-intra-margin: $spacing-vertical; @@ -93,14 +93,14 @@ $text-color: #000; /* Header */ --header-bg: var(--color-bg); --header-color: #666; - --header-active-color: rgba(0,0,0, 0.85); + --header-active-color: rgba(0, 0, 0, 0.85); --header-height: $spacing-vertical * 2.5; --header-button-bg: transparent; //var(--button-bg); --header-button-hover-bg: rgba(100, 100, 100, 0.15); /* Header -> search */ --search-bg: rgba(255, 255, 255, 0.7); - --search-border:1px solid #ccc; + --search-border: 1px solid #ccc; --search-color: #666; --search-active-color: var(--header-active-color); --search-active-shadow: 0 0 3px 0px var(--text-selection-bg); @@ -130,7 +130,7 @@ $text-color: #000; /* Modal */ --modal-width: 440px; --modal-bg: var(--color-bg); - --modal-overlay-bg: rgba(#F5F5F5, 0.75); // --color-canvas: #F5F5F5 + --modal-overlay-bg: rgba(#f5f5f5, 0.75); // --color-canvas: #F5F5F5 --modal-border: 1px solid rgb(204, 204, 204); /* Menu */ @@ -146,7 +146,7 @@ $text-color: #000; /* Scrollbar */ --scrollbar-radius: 10px; - --scrollbar-thumb-bg: rgba(0, 0, 0, 0.20); + --scrollbar-thumb-bg: rgba(0, 0, 0, 0.2); --scrollbar-thumb-hover-bg: rgba(0, 0, 0, 0.35); --scrollbar-thumb-active-bg: var(--color-primary); --scrollbar-track-bg: transparent; @@ -156,6 +156,5 @@ $text-color: #000; /* Animation :) */ --animation-duration: 0.3s; - --animation-style: cubic-bezier(.55,0,.1,1); - + --animation-style: cubic-bezier(0.55, 0, 0.1, 1); } diff --git a/src/renderer/scss/all.scss b/src/renderer/scss/all.scss index 40c63b1f4..7d39cb43a 100644 --- a/src/renderer/scss/all.scss +++ b/src/renderer/scss/all.scss @@ -1,31 +1,31 @@ @charset "UTF-8"; -@import "_reset"; -@import "_vars"; -@import "_icons"; -@import "_gui"; -@import "component/_table"; -@import "component/_button.scss"; -@import "component/_card.scss"; -@import "component/_file-download.scss"; -@import "component/_file-selector.scss"; -@import "component/_file-tile.scss"; -@import "component/_form-field.scss"; -@import "component/_header.scss"; -@import "component/_menu.scss"; -@import "component/_tooltip.scss"; -@import "component/_load-screen.scss"; -@import "component/_channel-indicator.scss"; -@import "component/_notice.scss"; -@import "component/_modal.scss"; -@import "component/_snack-bar.scss"; -@import "component/_video.scss"; -@import "component/_pagination.scss"; -@import "component/_markdown-editor.scss"; -@import "component/_scrollbar.scss"; -@import "component/_tabs.scss"; -@import "component/_divider.scss"; -@import "component/_checkbox.scss"; -@import "component/_radio.scss"; -@import "component/_shapeshift.scss"; -@import "component/_spinner.scss"; -@import "page/_show.scss"; +@import '_reset'; +@import '_vars'; +@import '_icons'; +@import '_gui'; +@import 'component/_table'; +@import 'component/_button.scss'; +@import 'component/_card.scss'; +@import 'component/_file-download.scss'; +@import 'component/_file-selector.scss'; +@import 'component/_file-tile.scss'; +@import 'component/_form-field.scss'; +@import 'component/_header.scss'; +@import 'component/_menu.scss'; +@import 'component/_tooltip.scss'; +@import 'component/_load-screen.scss'; +@import 'component/_channel-indicator.scss'; +@import 'component/_notice.scss'; +@import 'component/_modal.scss'; +@import 'component/_snack-bar.scss'; +@import 'component/_video.scss'; +@import 'component/_pagination.scss'; +@import 'component/_markdown-editor.scss'; +@import 'component/_scrollbar.scss'; +@import 'component/_tabs.scss'; +@import 'component/_divider.scss'; +@import 'component/_checkbox.scss'; +@import 'component/_radio.scss'; +@import 'component/_shapeshift.scss'; +@import 'component/_spinner.scss'; +@import 'page/_show.scss'; diff --git a/src/renderer/scss/component/_button.scss b/src/renderer/scss/component/_button.scss index e3dad6330..576ca4c33 100644 --- a/src/renderer/scss/component/_button.scss +++ b/src/renderer/scss/component/_button.scss @@ -1,4 +1,4 @@ -@import "../mixin/link.scss"; +@import '../mixin/link.scss'; $button-focus-shift: 12%; @@ -6,14 +6,13 @@ $button-focus-shift: 12%; position: relative; display: inline-block; - + .button-set-item - { + + .button-set-item { margin-left: var(--button-intra-margin); } } -.button-block, .faux-button-block -{ +.button-block, +.faux-button-block { display: inline-block; height: var(--button-height); line-height: var(--button-height); @@ -22,26 +21,21 @@ $button-focus-shift: 12%; text-align: center; border-radius: var(--button-radius); text-transform: uppercase; - .icon - { + .icon { top: 0em; } - .icon:first-child - { + .icon:first-child { padding-right: 5px; } - .icon:last-child - { + .icon:last-child { padding-left: 5px; } - .icon:only-child - { + .icon:only-child { padding-left: 0; padding-right: 0; } } -.button-block -{ +.button-block { cursor: pointer; font-weight: 500; font-size: 14px; @@ -57,9 +51,7 @@ $button-focus-shift: 12%; } } -.button-primary -{ - +.button-primary { color: var(--button-primary-color); background-color: var(--button-primary-bg); box-shadow: var(--box-shadow-layer); @@ -70,14 +62,12 @@ $button-focus-shift: 12%; //box-shadow: $box-shadow-focus; } } -.button-alt -{ +.button-alt { background-color: var(--button-bg); box-shadow: var(--box-shadow-layer); } -.button-text -{ +.button-text { @include text-link(); display: inline-block; @@ -85,17 +75,15 @@ $button-focus-shift: 12%; margin: 0 var(--text-link-padding); } } -.button-text-help -{ +.button-text-help { @include text-link(var(--text-help-color)); font-size: 0.8em; } -.button--flat -{ +.button--flat { box-shadow: none !important; } .button--submit { - font-family: inherit; - line-height: 0; -} \ No newline at end of file + font-family: inherit; + line-height: 0; +} diff --git a/src/renderer/scss/component/_card.scss b/src/renderer/scss/component/_card.scss index 5d0b5e76a..cef50a1fb 100644 --- a/src/renderer/scss/component/_card.scss +++ b/src/renderer/scss/component/_card.scss @@ -12,12 +12,11 @@ //below added to prevent scrollbar on long titles when show page loads, would prefer a cleaner CSS solution overflow-x: hidden; } -.card--obscured -{ +.card--obscured { position: relative; } .card--obscured .card__inner { - filter: blur( var(--nsfw-blur-intensity) ); + filter: blur(var(--nsfw-blur-intensity)); } .card__title-primary, .card__title-identity, @@ -52,7 +51,6 @@ margin-top: var(--card-margin); margin-bottom: var(--card-margin); user-select: none; - } .card__actions--bottom { margin-top: $spacing-vertical * 1/3; @@ -88,7 +86,7 @@ $font-size-subtext-multiple: 0.82; .card__subtext { color: var(--color-meta-light); - font-size: calc( var(--font-size-subtext-multiple) * 1.0em ); + font-size: calc(var(--font-size-subtext-multiple) * 1em); margin-top: $spacing-vertical * 1/3; margin-bottom: $spacing-vertical * 1/3; } @@ -96,7 +94,9 @@ $font-size-subtext-multiple: 0.82; white-space: pre-wrap; } .card__subtext--two-lines { - height: calc( var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2); /*this is so one line text still has the proper height*/ + height: calc( + var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2 + ); /*this is so one line text still has the proper height*/ } .card-overlay { position: absolute; @@ -117,7 +117,7 @@ $font-size-subtext-multiple: 0.82; cursor: pointer; } .card--link { - transition: transform 0.2s var(--animation-style); + transition: transform 0.2s var(--animation-style); } .card--link:hover { position: relative; @@ -126,7 +126,7 @@ $font-size-subtext-multiple: 0.82; transform: scale(var(--card-link-scaling)) translateX(var(--card-hover-translate)); transform-origin: 50% 50%; overflow-x: visible; - overflow-y: visible + overflow-y: visible; } .card--link:hover ~ .card--link { transform: translateX(calc(var(--card-hover-translate) * 2)); @@ -139,49 +139,49 @@ $font-size-subtext-multiple: 0.82; } .card__media--autothumb { - position: relative + position: relative; } .card__media--autothumb.purple { - background-color: #9c27b0 + background-color: #9c27b0; } .card__media--autothumb.red { - background-color: #e53935 + background-color: #e53935; } .card__media--autothumb.pink { - background-color: #e91e63 + background-color: #e91e63; } .card__media--autothumb.indigo { - background-color: #3f51b5 + background-color: #3f51b5; } .card__media--autothumb.blue { - background-color: #2196f3 + background-color: #2196f3; } .card__media--autothumb.light-blue { - background-color: #039be5 + background-color: #039be5; } .card__media--autothumb.cyan { - background-color: #00acc1 + background-color: #00acc1; } .card__media--autothumb.teal { - background-color: #009688 + background-color: #009688; } .card__media--autothumb.green { - background-color: #43a047 + background-color: #43a047; } .card__media--autothumb.yellow { - background-color: #ffeb3b + background-color: #ffeb3b; } .card__media--autothumb.orange { - background-color: #ffa726 + background-color: #ffa726; } .card__media--autothumb .card__autothumb__text { - font-size: 2.0em; + font-size: 2em; width: 100%; color: #ffffff; text-align: center; position: absolute; - top: 36% + top: 36%; } .card__indicators { @@ -194,17 +194,17 @@ $font-size-subtext-multiple: 0.82; white-space: normal; } .card--small .card__media { - height: calc( var(--card-small-width) * 9 / 16); + height: calc(var(--card-small-width) * 9 / 16); } .card--form { - width: calc( var(--input-width) + var(--card-padding) * 2); + width: calc(var(--input-width) + var(--card-padding) * 2); } .card__subtitle { color: var(--color-help); font-size: 0.85em; - line-height: calc( var(--font-line-height) * 1 / 0.85); + line-height: calc(var(--font-line-height) * 1 / 0.85); } .card--file-subtitle { @@ -219,8 +219,7 @@ $font-size-subtext-multiple: 0.82; padding-left: 20px; } -.card-series-submit -{ +.card-series-submit { margin-left: auto; margin-right: auto; max-width: var(--card-max-width); @@ -279,7 +278,7 @@ $padding-right-card-hover-hack: 30px; position: absolute; padding: 0 var(--card-margin); height: 100%; - top: calc( $padding-top-card-hover-hack - var(--card-margin) ); + top: calc($padding-top-card-hover-hack - var(--card-margin)); } .card-row__nav .card-row__scroll-button { background: var(--card-bg); @@ -295,8 +294,8 @@ $padding-right-card-hover-hack: 30px; transition: transform 0.2s var(--animation-style); &:hover { - opacity: 1.0; - transform: scale(calc( var(--card-link-scaling) * 1.1)); + opacity: 1; + transform: scale(calc(var(--card-link-scaling) * 1.1)); } } .card-row__nav--left { @@ -311,11 +310,11 @@ if we keep doing things like this, we should add a real grid system, but I'm goi */ .card-grid { $margin-card-grid: $spacing-vertical * 2/3; - display:flex; + display: flex; flex-wrap: wrap; > .card { width: $width-page-constrained / 2 - $margin-card-grid / 2; - flex-grow:1; + flex-grow: 1; } > .card:nth-of-type(2n - 1):not(:last-child) { margin-right: $margin-card-grid; diff --git a/src/renderer/scss/component/_channel-indicator.scss b/src/renderer/scss/component/_channel-indicator.scss index 50b7648d0..7c437780c 100644 --- a/src/renderer/scss/component/_channel-indicator.scss +++ b/src/renderer/scss/component/_channel-indicator.scss @@ -1,4 +1,3 @@ - .channel-name { display: inline-flex; overflow: hidden; diff --git a/src/renderer/scss/component/_checkbox.scss b/src/renderer/scss/component/_checkbox.scss index 92b7599cb..b72f7c896 100644 --- a/src/renderer/scss/component/_checkbox.scss +++ b/src/renderer/scss/component/_checkbox.scss @@ -1,4 +1,6 @@ -*, *:before, *:after { +*, +*:before, +*:after { box-sizing: border-box; } @@ -7,17 +9,18 @@ $md-checkbox-border-color: var(--input-border-color); $md-checkbox-size: 20px; $md-checkbox-padding: 4px; $md-checkmark-width: 2px; -$md-checkmark-color: #FFF; +$md-checkmark-color: #fff; .form-field--checkbox { position: relative; label { cursor: pointer; - &:before, &:after { - content: ""; + &:before, + &:after { + content: ''; position: absolute; - left:0; + left: 0; top: 0; } @@ -29,7 +32,7 @@ $md-checkmark-color: #FFF; border: 2px solid $md-checkbox-border-color; border-radius: 2px; cursor: pointer; - transition: background .3s; + transition: background 0.3s; } &:after { @@ -37,19 +40,17 @@ $md-checkmark-color: #FFF; } } - input[type="checkbox"] { + input[type='checkbox'] { outline: 0; visibility: hidden; margin-right: 16px; &:checked { - - + label:before{ + + label:before { background: $md-checkbox-checked-color; - border:none; + border: none; } + label:after { - $md-checkmark-size: $md-checkbox-size - 2*$md-checkbox-padding; transform: rotate(-45deg); @@ -65,5 +66,4 @@ $md-checkmark-color: #FFF; } } } - } diff --git a/src/renderer/scss/component/_file-download.scss b/src/renderer/scss/component/_file-download.scss index dcde4b31b..04eb6fc90 100644 --- a/src/renderer/scss/component/_file-download.scss +++ b/src/renderer/scss/component/_file-download.scss @@ -1,16 +1,15 @@ -.file-download, .file-download__overlay { - .button__content { - margin: 0 var(--text-link-padding); - } +.file-download, +.file-download__overlay { + .button__content { + margin: 0 var(--text-link-padding); + } } -.file-download -{ +.file-download { position: relative; color: var(--color-download); } -.file-download__overlay -{ +.file-download__overlay { background: var(--color-download); color: var(--color-bg); position: absolute; diff --git a/src/renderer/scss/component/_file-tile.scss b/src/renderer/scss/component/_file-tile.scss index 3542ac2ea..eccb74446 100644 --- a/src/renderer/scss/component/_file-tile.scss +++ b/src/renderer/scss/component/_file-tile.scss @@ -19,5 +19,4 @@ $height-file-tile: $spacing-vertical * 6; .card__title-primary { margin-top: 0; } - } diff --git a/src/renderer/scss/component/_form-field.scss b/src/renderer/scss/component/_form-field.scss index 1d7398d7a..042565611 100644 --- a/src/renderer/scss/component/_form-field.scss +++ b/src/renderer/scss/component/_form-field.scss @@ -1,9 +1,7 @@ -.form-row-submit -{ +.form-row-submit { margin-top: $spacing-vertical; } -.form-row-submit--with-footer -{ +.form-row-submit--with-footer { margin-bottom: $spacing-vertical; } @@ -11,7 +9,7 @@ margin-top: $spacing-vertical * 5/6; margin-bottom: 0px; line-height: 1; - font-size:calc( 0.9 * var(--font-size)); + font-size: calc(0.9 * var(--font-size)); } .form-row__label-row--prefix { float: left; @@ -19,7 +17,8 @@ } .form-row--focus { - .form-field__label, .form-field__prefix { + .form-field__label, + .form-field__prefix { color: var(--color-primary) !important; } } @@ -37,26 +36,27 @@ background: var(--select-bg); color: var(--select-color); &:focus { - outline: var(--input-border-size) solid var(--color-primary); + outline: var(--input-border-size) solid var(--color-primary); } } - input[type="radio"], input[type="checkbox"], { - &:checked + .form-field__label, { + input[type='radio'], + input[type='checkbox'] { + &:checked + .form-field__label { color: var(--text-color); } } - input[type="text"].input-copyable { + input[type='text'].input-copyable { background: var(--input-bg); - color: var(--input-disabled-color); + color: var(--input-disabled-color); line-height: 1; padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; padding-left: 5px; padding-right: 5px; width: 100%; - font-family: "Consolas", "Lucida Console", "Adobe Source Code Pro", monospace; + font-family: 'Consolas', 'Lucida Console', 'Adobe Source Code Pro', monospace; &.input-copyable--with-copy-btn { width: 85%; @@ -64,44 +64,44 @@ } input[readonly] { - color: var(--input-disabled-color) !important; - border-bottom: 1px dashed var(--input-disabled-border-color) !important; + color: var(--input-disabled-color) !important; + border-bottom: 1px dashed var(--input-disabled-border-color) !important; } input[readonly]:focus { - background: var(--input-bg) !important; - border-bottom: 1px dashed var(--input-disabled-border-color) !important; + background: var(--input-bg) !important; + border-bottom: 1px dashed var(--input-disabled-border-color) !important; } textarea, - input[type="text"], - input[type="password"], - input[type="email"], - input[type="number"], - input[type="search"], - input[type="date"]{ + input[type='text'], + input[type='password'], + input[type='email'], + input[type='number'], + input[type='search'], + input[type='date'] { background: var(--input-bg); border-bottom: var(--input-border-size) solid var(--input-border-color); - caret-color: var(--color-primary); + caret-color: var(--color-primary); color: var(--input-color); cursor: pointer; line-height: 1; - padding:0 1px 8px 1px; + padding: 0 1px 8px 1px; box-sizing: border-box; -webkit-appearance: none; - transition: all var(--transition-duration) var(--transition-type); + transition: all var(--transition-duration) var(--transition-type); &::-webkit-input-placeholder { color: var(--input-placeholder-color); opacity: var(--input-placeholder-opacity) !important; - } + } &:focus { border-color: var(--color-primary); background: var(--input-active-bg); } - &:hover:not(:focus){ + &:hover:not(:focus) { border-color: var(--input-hover-border-color); } @@ -112,11 +112,10 @@ &.form-field__input--inline { padding-top: 0; padding-bottom: 0; - border-bottom-width: var(--input-border-size); + border-bottom-width: var(--input-border-size); margin-left: 8px; margin-right: 8px; } - } textarea { @@ -132,7 +131,8 @@ display: block; } -.form-field__label, .form-row__label { +.form-field__label, +.form-row__label { color: var(--form-label-color); &[for] { cursor: pointer; @@ -167,17 +167,18 @@ width: 100%; } -.form-field__error, .form-field__helper { +.form-field__error, +.form-field__helper { margin-top: $spacing-vertical * 1/3; font-size: 0.8em; - transition: opacity var(--transition-duration) var(--transition-type); + transition: opacity var(--transition-duration) var(--transition-type); } .form-field__error { color: var(--color-error); } .form-field__helper { - color:var(--color-help); + color: var(--color-help); } .form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll { diff --git a/src/renderer/scss/component/_header.scss b/src/renderer/scss/component/_header.scss index bdc72dcbd..a8967d0eb 100644 --- a/src/renderer/scss/component/_header.scss +++ b/src/renderer/scss/component/_header.scss @@ -1,6 +1,4 @@ - -#header -{ +#header { color: var(--header-color); background: var(--header-bg); display: flex; @@ -19,11 +17,11 @@ padding-left: $spacing-vertical / 4; padding-right: $spacing-vertical / 4; .button-alt { - background: var(--header-button-bg) !important; - font-size: 1em; + background: var(--header-button-bg) !important; + font-size: 1em; } .button-alt:hover { - background: var(--header-button-hover-bg) !important; + background: var(--header-button-hover-bg) !important; } } @@ -31,17 +29,18 @@ flex-grow: 1; } -.wunderbar -{ +.wunderbar { position: relative; .icon { position: absolute; left: 10px; - top: $spacing-vertical / 2 - 4px; //hacked + top: $spacing-vertical / 2 - 4px; //hacked } } -.wunderbar--active .icon-search { color: var(--color-primary); } +.wunderbar--active .icon-search { + color: var(--color-primary); +} // below styles should be inside the common input styling // will come back to this with the redesign - sean diff --git a/src/renderer/scss/component/_load-screen.scss b/src/renderer/scss/component/_load-screen.scss index cfd369c95..05cce635e 100644 --- a/src/renderer/scss/component/_load-screen.scss +++ b/src/renderer/scss/component/_load-screen.scss @@ -1,4 +1,3 @@ - .load-screen { color: white; background: var(--color-brand); diff --git a/src/renderer/scss/component/_markdown-editor.scss b/src/renderer/scss/component/_markdown-editor.scss index 5a1786b48..7211c0d08 100644 --- a/src/renderer/scss/component/_markdown-editor.scss +++ b/src/renderer/scss/component/_markdown-editor.scss @@ -1,17 +1,17 @@ .CodeMirror { - background: var(--color-canvas) !important; - border: 0px !important; - border-radius: 0px !important; - color: var(--text-color) !important; - box-shadow: var(--box-shadow-layer); + background: var(--color-canvas) !important; + border: 0px !important; + border-radius: 0px !important; + color: var(--text-color) !important; + box-shadow: var(--box-shadow-layer); } .editor-toolbar { - opacity: 1 !important; - border: 0 !important; - background: var(--color-bg-alt); - border-radius: 0 !important; - box-shadow: var(--box-shadow-layer); + opacity: 1 !important; + border: 0 !important; + background: var(--color-bg-alt); + border-radius: 0 !important; + box-shadow: var(--box-shadow-layer); } .editor-toolbar i.separator { @@ -20,85 +20,85 @@ } .editor-toolbar.fullscreen { - background: var(--color-bg) !important; + background: var(--color-bg) !important; } div.editor-toolbar a { - opacity: 0.64; - color: var(--text-color) !important; + opacity: 0.64; + color: var(--text-color) !important; } .editor-toolbar a.active, .editor-toolbar a:hover { - opacity: 1; - background: var(--button-bg) !important; - border-color: transparent !important; + opacity: 1; + background: var(--button-bg) !important; + border-color: transparent !important; } .editor-toolbar.disabled-for-preview a:not(.no-disable) { - background: var(--color-bg-alt) !important; - border-color: transparent !important; + background: var(--color-bg-alt) !important; + border-color: transparent !important; } .editor-statusbar { - color: var(--form-label-color) !important; + color: var(--form-label-color) !important; } .editor-preview { - background: var(--card-bg) !important; - border: 0 !important; + background: var(--card-bg) !important; + border: 0 !important; } .editor-preview-side { - background: var(--color-bg-alt) !important; - border: 1px solid var(--input-border-color) !important; + background: var(--color-bg-alt) !important; + border: 1px solid var(--input-border-color) !important; } .editor-preview pre, .editor-preview-side pre { - background: #eee; + background: #eee; } .editor-preview table td, .editor-preview table th, .editor-preview-side table td, .editor-preview-side table th { - border: 1px solid var(--input-border-color) !important; + border: 1px solid var(--input-border-color) !important; } .CodeMirror .CodeMirror-code .cm-tag { - color: #63a35c; + color: #63a35c; } .CodeMirror .CodeMirror-code .cm-attribute { - color: #795da3; + color: #795da3; } .CodeMirror .CodeMirror-code .cm-string { - color: #183691; + color: #183691; } .CodeMirror .CodeMirror-selected { - background: var(--text-selection-bg) !important; - color: var(--text-selection-color) !important; + background: var(--text-selection-bg) !important; + color: var(--text-selection-color) !important; } -.CodeMirror .CodeMirror-cursor{ - border-color: var(--color-primary) !important; +.CodeMirror .CodeMirror-cursor { + border-color: var(--color-primary) !important; } .CodeMirror .CodeMirror-code .cm-comment { - background: rgba(0, 0, 0, .05); + background: rgba(0, 0, 0, 0.05); } .CodeMirror .CodeMirror-code .cm-link { - color: #7f8c8d; + color: #7f8c8d; } .CodeMirror .CodeMirror-code .cm-url { - color: #aab2b3; + color: #aab2b3; } .CodeMirror .CodeMirror-placeholder { - opacity: .5; + opacity: 0.5; } diff --git a/src/renderer/scss/component/_menu.scss b/src/renderer/scss/component/_menu.scss index 19af2af66..c04f11610 100644 --- a/src/renderer/scss/component/_menu.scss +++ b/src/renderer/scss/component/_menu.scss @@ -1,4 +1,3 @@ - $border-radius-menu: 2px; .menu-container { diff --git a/src/renderer/scss/component/_modal.scss b/src/renderer/scss/component/_modal.scss index 26fa408df..d5a561334 100644 --- a/src/renderer/scss/component/_modal.scss +++ b/src/renderer/scss/component/_modal.scss @@ -1,5 +1,5 @@ - -.modal-overlay, .error-modal-overlay { +.modal-overlay, +.error-modal-overlay { position: fixed; display: flex; justify-content: center; @@ -72,11 +72,12 @@ max-width: none; width: var(--modal-width); } -.error-modal__error-list { /*shitty hack/temp fix for long errors making modal unusable*/ +.error-modal__error-list { + /*shitty hack/temp fix for long errors making modal unusable*/ border: 1px solid var(--input-border-color); padding: 8px; list-style: none; max-height: 400px; - max-width: var(--modal-width); + max-width: var(--modal-width); overflow-y: hidden; } diff --git a/src/renderer/scss/component/_notice.scss b/src/renderer/scss/component/_notice.scss index 112658987..277fe0615 100644 --- a/src/renderer/scss/component/_notice.scss +++ b/src/renderer/scss/component/_notice.scss @@ -1,17 +1,16 @@ - .notice { - padding: 10px 20px; - border: 1px solid #000; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - border-radius: 5px; + padding: 10px 20px; + border: 1px solid #000; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-radius: 5px; - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; } .notice--error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; } diff --git a/src/renderer/scss/component/_pagination.scss b/src/renderer/scss/component/_pagination.scss index 4851f366a..9c70d32f4 100644 --- a/src/renderer/scss/component/_pagination.scss +++ b/src/renderer/scss/component/_pagination.scss @@ -1,4 +1,3 @@ - .pagination { display: block; padding: 0; @@ -13,7 +12,9 @@ border-radius: 2px; &:not(.pagination__item--selected):hover { background: rgba(0, 0, 0, 0.2); - > a { cursor: hand } + > a { + cursor: hand; + } } > a { display: inline-block; @@ -21,12 +22,13 @@ } } -.pagination__item--previous, .pagination__item--next { +.pagination__item--previous, +.pagination__item--next { font-size: 1.2em; } .pagination__item--break { - padding: 0 $spacing-vertical * 2 / 3; + padding: 0 $spacing-vertical * 2 / 3; } .pagination__item--selected { diff --git a/src/renderer/scss/component/_radio.scss b/src/renderer/scss/component/_radio.scss index 3e54da009..4d511816f 100644 --- a/src/renderer/scss/component/_radio.scss +++ b/src/renderer/scss/component/_radio.scss @@ -5,50 +5,50 @@ $md-radio-checked-size: 10px; $md-radio-ripple-size: 15px; .form-field--radio { - position: relative; + position: relative; - label { + label { + cursor: pointer; + + &:before, + &:after { + content: ''; + position: absolute; + left: 0; + top: 0; + border-radius: 50%; + transition: all 0.3s ease; + transition-property: transform, border-color; + } + + &:before { + width: $md-radio-size; + height: $md-radio-size; + background: transparent; + border: 2px solid $md-radio-border-color; cursor: pointer; - - &:before, &:after { - content: ""; - position: absolute; - left:0; - top: 0; - border-radius: 50%; - transition: all .3s ease; - transition-property: transform, border-color; - } - - &:before { - width: $md-radio-size; - height: $md-radio-size; - background: transparent; - border: 2px solid $md-radio-border-color; - cursor: pointer; - } - - &:after { - top: $md-radio-size / 2 - $md-radio-checked-size / 2; - left: $md-radio-size / 2 - $md-radio-checked-size / 2; - width:$md-radio-checked-size; - height:$md-radio-checked-size; - transform: scale(0); - background:$md-radio-checked-color; - } - } - input[type="radio"] { - visibility: hidden; - margin-right: 16px; - - &:checked + label:before { - border-color: $md-radio-checked-color; - } - - &:checked + label:after { - transform: scale(1); - } + &:after { + top: $md-radio-size / 2 - $md-radio-checked-size / 2; + left: $md-radio-size / 2 - $md-radio-checked-size / 2; + width: $md-radio-checked-size; + height: $md-radio-checked-size; + transform: scale(0); + background: $md-radio-checked-color; } + } + + input[type='radio'] { + visibility: hidden; + margin-right: 16px; + + &:checked + label:before { + border-color: $md-radio-checked-color; + } + + &:checked + label:after { + transform: scale(1); + } + } } diff --git a/src/renderer/scss/component/_scrollbar.scss b/src/renderer/scss/component/_scrollbar.scss index 048428132..c501d0ddd 100644 --- a/src/renderer/scss/component/_scrollbar.scss +++ b/src/renderer/scss/component/_scrollbar.scss @@ -1,24 +1,24 @@ ::-webkit-scrollbar { - width: 8px; - overflow: auto; + width: 8px; + overflow: auto; } ::-webkit-scrollbar-track { - background: var(--scrollbar-track-bg); - border-radius: var(--scrollbar-radius); - margin: 4px; + background: var(--scrollbar-track-bg); + border-radius: var(--scrollbar-radius); + margin: 4px; } ::-webkit-scrollbar-thumb { - border-radius: var(--scrollbar-radius); - background-color: var(--scrollbar-thumb-bg); - transition: background-color 0.3s ease; + border-radius: var(--scrollbar-radius); + background-color: var(--scrollbar-thumb-bg); + transition: background-color 0.3s ease; } ::-webkit-scrollbar-thumb:hover { - background-color: var(--scrollbar-thumb-hover-bg); + background-color: var(--scrollbar-thumb-hover-bg); } ::-webkit-scrollbar-thumb:active { - background-color: var(--scrollbar-thumb-active-bg); + background-color: var(--scrollbar-thumb-active-bg); } diff --git a/src/renderer/scss/component/_shapeshift.scss b/src/renderer/scss/component/_shapeshift.scss index 6e12a0522..cbe040180 100644 --- a/src/renderer/scss/component/_shapeshift.scss +++ b/src/renderer/scss/component/_shapeshift.scss @@ -34,7 +34,6 @@ margin-left: 40px; } - .shapeshift__link { padding-left: 10px; } diff --git a/src/renderer/scss/component/_snack-bar.scss b/src/renderer/scss/component/_snack-bar.scss index 75d2e3491..ccc81e0b9 100644 --- a/src/renderer/scss/component/_snack-bar.scss +++ b/src/renderer/scss/component/_snack-bar.scss @@ -1,4 +1,3 @@ - $padding-snack-horizontal: $spacing-vertical; .snack-bar { @@ -24,7 +23,7 @@ $padding-snack-horizontal: $spacing-vertical; border-radius: 2px; - transition: all var(--transition-duration) var(--transition-type); + transition: all var(--transition-duration) var(--transition-type); z-index: 10000; /*hack to get it over react modal */ } diff --git a/src/renderer/scss/component/_spinner.scss b/src/renderer/scss/component/_spinner.scss index ec339e5a1..f3e0485f7 100644 --- a/src/renderer/scss/component/_spinner.scss +++ b/src/renderer/scss/component/_spinner.scss @@ -55,4 +55,4 @@ &:after { background: var(--color-bg); } -} \ No newline at end of file +} diff --git a/src/renderer/scss/component/_table.scss b/src/renderer/scss/component/_table.scss index 06f33aaf0..1c6b17369 100644 --- a/src/renderer/scss/component/_table.scss +++ b/src/renderer/scss/component/_table.scss @@ -1,9 +1,9 @@ - table.table-standard { word-wrap: break-word; max-width: 100%; - th, td { + th, + td { padding: $spacing-vertical/2 8px; } th { @@ -13,7 +13,8 @@ table.table-standard { td { vertical-align: top; } - thead th, > tr:first-child th { + thead th, + > tr:first-child th { vertical-align: bottom; font-weight: 500; font-size: 0.9em; @@ -32,7 +33,7 @@ table.table-standard { } tfoot td { padding: $spacing-vertical / 2 8px; - font-size: .85em; + font-size: 0.85em; } tbody { tr { @@ -62,9 +63,19 @@ table.table-stretch { } table.table-transactions { - td:nth-of-type(1) { width: 15%; } - td:nth-of-type(2) { width: 15%; } - td:nth-of-type(3) { width: 15%; } - td:nth-of-type(4) { width: 40%; } - td:nth-of-type(5) { width: 15%; } + td:nth-of-type(1) { + width: 15%; + } + td:nth-of-type(2) { + width: 15%; + } + td:nth-of-type(3) { + width: 15%; + } + td:nth-of-type(4) { + width: 40%; + } + td:nth-of-type(5) { + width: 15%; + } } diff --git a/src/renderer/scss/component/_tabs.scss b/src/renderer/scss/component/_tabs.scss index c990c8adf..69f6bc7a3 100644 --- a/src/renderer/scss/component/_tabs.scss +++ b/src/renderer/scss/component/_tabs.scss @@ -1,14 +1,12 @@ /* Tabs */ -nav.sub-header -{ +nav.sub-header { text-transform: uppercase; max-width: $width-page-constrained; margin-bottom: 40px; border-bottom: var(--divider); user-select: none; - > a - { + > a { height: 38px; line-height: 38px; text-align: center; @@ -21,16 +19,13 @@ nav.sub-header color: var(--tab-color); position: relative; - &:first-child - { + &:first-child { margin-left: 0; } - &:last-child - { + &:last-child { margin-right: 0; } - &.sub-header-selected - { + &.sub-header-selected { color: var(--tab-active-color); &:before { width: 100%; @@ -45,8 +40,7 @@ nav.sub-header animation-timing-function: var(--animation-style); } } - &:hover - { + &:hover { color: var(--tab-active-color); } } @@ -60,8 +54,11 @@ nav.sub-header } } - @keyframes activeTab { - from {width: 0;} - to {width: 100%;} + from { + width: 0; + } + to { + width: 100%; + } } diff --git a/src/renderer/scss/component/_tooltip.scss b/src/renderer/scss/component/_tooltip.scss index 58889f657..d017996c1 100644 --- a/src/renderer/scss/component/_tooltip.scss +++ b/src/renderer/scss/component/_tooltip.scss @@ -1,4 +1,4 @@ -@import "../mixin/link.scss"; +@import '../mixin/link.scss'; .tooltip { position: relative; @@ -27,7 +27,7 @@ .tooltip--header .tooltip__link { @include text-link(#aaa); - font-size: calc( var(--font-size) * 3/4 ); + font-size: calc(var(--font-size) * 3/4); margin-left: var(--button-padding); vertical-align: middle; } diff --git a/src/renderer/scss/component/_video.scss b/src/renderer/scss/component/_video.scss index d6021849e..aa449c48e 100644 --- a/src/renderer/scss/component/_video.scss +++ b/src/renderer/scss/component/_video.scss @@ -1,4 +1,3 @@ - $height-video-embedded: $width-page-constrained * 9 / 16; video { @@ -32,13 +31,11 @@ video { height: $height-video-embedded; } } -.video--obscured .video__cover -{ +.video--obscured .video__cover { position: relative; filter: blur(var(--nsfw-blur-intensity)); } - .video__loading-screen { height: 100%; display: flex; diff --git a/src/renderer/scss/mixin/link.scss b/src/renderer/scss/mixin/link.scss index ae6e752da..df55e49ba 100644 --- a/src/renderer/scss/mixin/link.scss +++ b/src/renderer/scss/mixin/link.scss @@ -1,6 +1,5 @@ -@mixin text-link($color: var(--color-primary), $hover-opacity: 0.70) { - .icon - { +@mixin text-link($color: var(--color-primary), $hover-opacity: 0.7) { + .icon { &:first-child { padding-right: 5px; } @@ -15,10 +14,9 @@ text-decoration: none; } } - &:hover - { + &:hover { opacity: $hover-opacity; - transition: opacity var(--transition-duration) var(--transition-type); + transition: opacity var(--transition-duration) var(--transition-type); text-decoration: underline; .icon { text-decoration: none; diff --git a/src/renderer/store.js b/src/renderer/store.js index 9e6176b0e..fc8e5e9f2 100644 --- a/src/renderer/store.js +++ b/src/renderer/store.js @@ -1,29 +1,27 @@ -import { createLogger } from "redux-logger"; -import appReducer from "redux/reducers/app"; -import availabilityReducer from "redux/reducers/availability"; -import claimsReducer from "redux/reducers/claims"; -import contentReducer from "redux/reducers/content"; -import costInfoReducer from "redux/reducers/cost_info"; -import fileInfoReducer from "redux/reducers/file_info"; -import navigationReducer from "redux/reducers/navigation"; -import rewardsReducer from "redux/reducers/rewards"; -import searchReducer from "redux/reducers/search"; -import settingsReducer from "redux/reducers/settings"; -import userReducer from "redux/reducers/user"; -import walletReducer from "redux/reducers/wallet"; -import shapeShiftReducer from "redux/reducers/shape_shift"; -import subscriptionsReducer from "redux/reducers/subscriptions"; -import { persistStore, autoRehydrate } from "redux-persist"; -import createCompressor from "redux-persist-transform-compress"; -import createFilter from "redux-persist-transform-filter"; -import localForage from "localforage"; -import { createStore, applyMiddleware, compose, combineReducers } from "redux"; -import thunk from "redux-thunk"; - -const env = process.env.NODE_ENV || "production" +import { createLogger } from 'redux-logger'; +import appReducer from 'redux/reducers/app'; +import availabilityReducer from 'redux/reducers/availability'; +import claimsReducer from 'redux/reducers/claims'; +import contentReducer from 'redux/reducers/content'; +import costInfoReducer from 'redux/reducers/cost_info'; +import fileInfoReducer from 'redux/reducers/file_info'; +import navigationReducer from 'redux/reducers/navigation'; +import rewardsReducer from 'redux/reducers/rewards'; +import searchReducer from 'redux/reducers/search'; +import settingsReducer from 'redux/reducers/settings'; +import userReducer from 'redux/reducers/user'; +import walletReducer from 'redux/reducers/wallet'; +import shapeShiftReducer from 'redux/reducers/shape_shift'; +import subscriptionsReducer from 'redux/reducers/subscriptions'; +import { persistStore, autoRehydrate } from 'redux-persist'; +import createCompressor from 'redux-persist-transform-compress'; +import createFilter from 'redux-persist-transform-filter'; +import localForage from 'localforage'; +import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; +import thunk from 'redux-thunk'; function isFunction(object) { - return typeof object === "function"; + return typeof object === 'function'; } function isNotFunction(object) { @@ -32,10 +30,8 @@ function isNotFunction(object) { function createBulkThunkMiddleware() { return ({ dispatch, getState }) => next => action => { - if (action.type === "BATCH_ACTIONS") { - action.actions - .filter(isFunction) - .map(actionFn => actionFn(dispatch, getState)); + if (action.type === 'BATCH_ACTIONS') { + action.actions.filter(isFunction).map(actionFn => actionFn(dispatch, getState)); } return next(action); }; @@ -44,10 +40,8 @@ function createBulkThunkMiddleware() { function enableBatching(reducer) { return function batchingReducer(state, action) { switch (action.type) { - case "BATCH_ACTIONS": - return action.actions - .filter(isNotFunction) - .reduce(batchingReducer, state); + case 'BATCH_ACTIONS': + return action.actions.filter(isNotFunction).reduce(batchingReducer, state); default: return reducer(state, action); } @@ -74,13 +68,14 @@ const reducers = combineReducers({ const bulkThunk = createBulkThunkMiddleware(); const middleware = [thunk, bulkThunk]; -if (env === "development") { +if (app.env === 'development') { const logger = createLogger({ collapsed: true, }); middleware.push(logger); } +// eslint-disable-next-line no-underscore-dangle const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( @@ -88,18 +83,18 @@ const store = createStore( {}, // initial state composeEnhancers( autoRehydrate({ - log: env === "development", + log: app.env === 'development', }), applyMiddleware(...middleware) ) ); const compressor = createCompressor(); -const saveClaimsFilter = createFilter("claims", ["byId", "claimsByUri"]); -const subscriptionsFilter = createFilter("subscriptions", ["subscriptions"]); +const saveClaimsFilter = createFilter('claims', ['byId', 'claimsByUri']); +const subscriptionsFilter = createFilter('subscriptions', ['subscriptions']); const persistOptions = { - whitelist: ["claims", "subscriptions"], + whitelist: ['claims', 'subscriptions'], // Order is important. Needs to be compressed last or other transforms can't // read the data transforms: [saveClaimsFilter, subscriptionsFilter, compressor], @@ -109,7 +104,7 @@ const persistOptions = { window.cacheStore = persistStore(store, persistOptions, err => { if (err) { - console.error("Unable to load saved settings"); + console.error('Unable to load saved SETTINGS'); } }); diff --git a/src/renderer/types/common.js b/src/renderer/types/common.js index ea8c0d815..5f3636de3 100644 --- a/src/renderer/types/common.js +++ b/src/renderer/types/common.js @@ -1,3 +1,5 @@ +// @flow + export type FormikActions = { setSubmitting: boolean => mixed, }; diff --git a/src/renderer/util/batchActions.js b/src/renderer/util/batchActions.js index d8cb486a5..4bc4eee7f 100644 --- a/src/renderer/util/batchActions.js +++ b/src/renderer/util/batchActions.js @@ -1,7 +1,7 @@ // https://github.com/reactjs/redux/issues/911 function batchActions(...actions) { return { - type: "BATCH_ACTIONS", + type: 'BATCH_ACTIONS', actions, }; } diff --git a/src/renderer/util/formatCredits.js b/src/renderer/util/formatCredits.js index fea63a00a..98383c05f 100644 --- a/src/renderer/util/formatCredits.js +++ b/src/renderer/util/formatCredits.js @@ -1,19 +1,16 @@ export function formatCredits(amount, precision) { - return amount.toFixed(precision || 1).replace(/\.?0+$/, ""); + return amount.toFixed(precision || 1).replace(/\.?0+$/, ''); } -export function formatFullPrice(amount, precision) { - let formated = ""; +export function formatFullPrice(amount, precision = 1) { + let formated = ''; - const quantity = amount.toString().split("."); + const quantity = amount.toString().split('.'); const fraction = quantity[1]; if (fraction) { - // Set precision - precision = precision || 1; - - const decimals = fraction.split(""); - const first = decimals.filter(number => number != "0")[0]; + const decimals = fraction.split(''); + const first = decimals.filter(number => number !== '0')[0]; const index = decimals.indexOf(first); // Set format fraction diff --git a/src/renderer/util/query_params.js b/src/renderer/util/query_params.js index 76ed1c754..e7f04d150 100644 --- a/src/renderer/util/query_params.js +++ b/src/renderer/util/query_params.js @@ -1,26 +1,28 @@ export function parseQueryParams(queryString) { - if (queryString === "") return {}; + if (queryString === '') return {}; const parts = queryString - .split("?") + .split('?') .pop() - .split("&") - .map(p => p.split("=")); + .split('&') + .map(p => p.split('=')); const params = {}; - parts.forEach(arr => { - params[arr[0]] = arr[1]; + parts.forEach(array => { + const [first, second] = array; + params[first] = second; }); return params; } export function toQueryString(params) { - if (!params) return ""; + if (!params) return ''; const parts = []; - for (const key in params) { - if (params.hasOwnProperty(key) && params[key]) { + Object.keys(params).forEach(key => { + if (Object.prototype.hasOwnProperty.call(params, key) && params[key]) { parts.push(`${key}=${params[key]}`); } - } - return parts.join("&"); + }); + + return parts.join('&'); } diff --git a/src/renderer/util/redux-utils.js b/src/renderer/util/redux-utils.js index b50e55812..4ff5adc21 100644 --- a/src/renderer/util/redux-utils.js +++ b/src/renderer/util/redux-utils.js @@ -1,10 +1,7 @@ // util for creating reducers // based off of redux-actions // https://redux-actions.js.org/docs/api/handleAction.html#handleactions -export const handleActions = (actionMap, defaultState) => ( - state = defaultState, - action -) => { +const handleActions = (actionMap, defaultState) => (state = defaultState, action) => { const handler = actionMap[action.type]; if (handler) { @@ -16,3 +13,5 @@ export const handleActions = (actionMap, defaultState) => ( // returning a copy here breaks redux-persist return state; }; + +export { handleActions as default }; diff --git a/src/renderer/util/setBadge.js b/src/renderer/util/setBadge.js index 372b8d4e1..005e63a11 100644 --- a/src/renderer/util/setBadge.js +++ b/src/renderer/util/setBadge.js @@ -1,7 +1,7 @@ -const { remote } = require("electron"); +const { remote } = require('electron'); const application = remote.app; -const dock = application.dock; +const { dock } = application; const win = remote.BrowserWindow.getFocusedWindow(); const setBadge = text => { if (!dock) return; diff --git a/src/renderer/util/setProgressBar.js b/src/renderer/util/setProgressBar.js index 942d4288c..936a90f47 100644 --- a/src/renderer/util/setProgressBar.js +++ b/src/renderer/util/setProgressBar.js @@ -1,6 +1,5 @@ -const { remote } = require("electron"); +import { remote } from 'electron'; -const application = remote.app; const win = remote.getCurrentWindow(); const setProgressBar = progress => { diff --git a/src/renderer/util/shape_shift.js b/src/renderer/util/shape_shift.js index 5b04100e3..b61880e35 100644 --- a/src/renderer/util/shape_shift.js +++ b/src/renderer/util/shape_shift.js @@ -19,7 +19,7 @@ const validateAddress = (coinType, address) => { return coinRegex.test(address); }; -export const validateShapeShiftForm = (vals, props) => { +export const validateShapeShiftForm = vals => { const errors = {}; if (!vals.returnAddress) { @@ -36,13 +36,13 @@ export const validateShapeShiftForm = (vals, props) => { }; const exampleCoinAddresses = { - BTC: "1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq", - BCH: "1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq", - ETH: "0x8507cA6a274123fC8f80d929AF9D83602bC4e8cC", - DASH: "XedBP7vLPFXbS3URjrH2Z57Fg9SWftBmQ6", - LTC: "LgZivMvFMTDoqcA5weCQ2QrmRp7pa56bBk", + BTC: '1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq', + BCH: '1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq', + ETH: '0x8507cA6a274123fC8f80d929AF9D83602bC4e8cC', + DASH: 'XedBP7vLPFXbS3URjrH2Z57Fg9SWftBmQ6', + LTC: 'LgZivMvFMTDoqcA5weCQ2QrmRp7pa56bBk', XMR: - "466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm", + '466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm', }; export const getExampleAddress = coin => exampleCoinAddresses[coin]; diff --git a/src/renderer/util/throttle.js b/src/renderer/util/throttle.js index bbb5e316c..941633deb 100644 --- a/src/renderer/util/throttle.js +++ b/src/renderer/util/throttle.js @@ -6,21 +6,25 @@ // as much as it can, without ever going more than once per `wait` duration; // but if you'd like to disable the execution on the leading edge, pass // `{leading: false}`. To disable execution on the trailing edge, ditto. -export default function throttle(func, wait, options) { - let timeout, context, args, result; +export default function throttle(func, wait, options = {}) { + let timeout; + let context; + let args; + let result; let previous = 0; const getNow = () => new Date().getTime(); - if (!options) options = {}; - const later = function() { previous = options.leading === false ? 0 : getNow(); timeout = null; result = func.apply(context, args); - if (!timeout) context = args = null; + if (!timeout) { + context = null; + args = null; + } }; - const throttled = function() { + const throttled = function(...funcArgs) { const now = getNow(); if (!previous && options.leading === false) previous = now; @@ -28,7 +32,7 @@ export default function throttle(func, wait, options) { const remaining = wait - (now - previous); context = this; - args = arguments; + args = funcArgs; if (remaining <= 0 || remaining > wait) { if (timeout) { @@ -39,7 +43,10 @@ export default function throttle(func, wait, options) { previous = now; result = func.apply(context, args); - if (!timeout) context = args = null; + if (!timeout) { + context = null; + args = null; + } } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } @@ -49,7 +56,9 @@ export default function throttle(func, wait, options) { throttled.cancel = function() { clearTimeout(timeout); previous = 0; - timeout = context = args = null; + timeout = null; + context = null; + args = null; }; return throttled; diff --git a/webpack.renderer.additions.js b/webpack.renderer.additions.js index d3465623a..b18039ad1 100644 --- a/webpack.renderer.additions.js +++ b/webpack.renderer.additions.js @@ -1,7 +1,7 @@ -const Path = require("path"); -const FlowFlowPlugin = require("./flowtype-plugin"); +const Path = require('path'); +const FlowFlowPlugin = require('./flowtype-plugin'); -const ELECTRON_RENDERER_PROCESS_ROOT = Path.resolve(__dirname, "src/renderer/"); +const ELECTRON_RENDERER_PROCESS_ROOT = Path.resolve(__dirname, 'src/renderer/'); module.exports = { // This rule is temporarily necessary until https://github.com/electron-userland/electron-webpack/issues/60 is fixed. @@ -9,27 +9,24 @@ module.exports = { rules: [ { test: /\.jsx?$/, - loader: "babel-loader", + loader: 'babel-loader', options: { - presets: ["env", "react", "stage-2"], + presets: ['env', 'react', 'stage-2'], }, }, ], }, // This allows imports to be made from the renderer process root (https://moduscreate.com/blog/es6-es2015-import-no-relative-path-webpack/). resolve: { - modules: [ELECTRON_RENDERER_PROCESS_ROOT, "node_modules", __dirname], - extensions: [".js", ".jsx", ".scss"], + modules: [ELECTRON_RENDERER_PROCESS_ROOT, 'node_modules', __dirname], + extensions: ['.js', '.jsx', '.scss'], }, }; -if (process.env.NODE_ENV === "development") { - module.exports = { - ...module.exports, - plugins: [ - new FlowFlowPlugin({ - warn: true, - }), - ] - }; +if (process.env.NODE_ENV === 'development') { + module.exports.plugins = [ + new FlowFlowPlugin({ + warn: true, + }), + ]; } diff --git a/yarn.lock b/yarn.lock index 690ed20b2..23c03e6d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5085,9 +5085,9 @@ keypress@0.1.x: version "0.1.0" resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a" -keytar@^4.0.3: - version "4.0.5" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-4.0.5.tgz#cc1255ef06eeea1a12440b773f7d4a375b048729" +keytar@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/keytar/-/keytar-4.1.0.tgz#9e3933e489d656de1a868e1293709313044989d7" dependencies: nan "2.5.1"