Apply ESLint auto fixing

This commit is contained in:
Igor Gassmann 2017-12-13 18:36:30 -03:00
parent 040b57352f
commit a40aecfb68
64 changed files with 729 additions and 722 deletions

View file

@ -1,52 +1,63 @@
// Module imports // Module imports
const {app, BrowserWindow, ipcMain, Menu, Tray, globalShortcut} = require('electron'); const {
const path = require('path'); app,
const url = require('url'); BrowserWindow,
const jayson = require('jayson'); ipcMain,
const semver = require('semver'); Menu,
const https = require('https'); Tray,
const keytar = require('keytar'); 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 // tree-kill has better cross-platform handling of
// killing a process. child-process.kill was unreliable // killing a process. child-process.kill was unreliable
const kill = require('tree-kill'); const kill = require("tree-kill");
const child_process = require('child_process'); const child_process = require("child_process");
const assert = require('assert'); const assert = require("assert");
const localVersion = app.getVersion(); const localVersion = app.getVersion();
const setMenu = require('./menu/main-menu.js'); const setMenu = require("./menu/main-menu.js");
export const contextMenu = require('./menu/context-menu'); export const contextMenu = require("./menu/context-menu");
// Debug configs // Debug configs
const isDevelopment = process.env.NODE_ENV === 'development'; const isDevelopment = process.env.NODE_ENV === "development";
if (isDevelopment) { if (isDevelopment) {
try try {
{ const {
const { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = require('electron-devtools-installer'); default: installExtension,
app.on('ready', () => { REACT_DEVELOPER_TOOLS,
REDUX_DEVTOOLS,
} = require("electron-devtools-installer");
app.on("ready", () => {
[REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => { [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => {
installExtension(extension) installExtension(extension)
.then((name) => console.log(`Added Extension: ${name}`)) .then(name => console.log(`Added Extension: ${name}`))
.catch((err) => console.log('An error occurred: ', err)); .catch(err => console.log("An error occurred: ", err));
}); });
}); });
} } catch (err) {
catch (err) console.error(err);
{
console.error(err)
} }
} }
// Misc constants // Misc constants
const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest'; const LATEST_RELEASE_API_URL =
const DAEMON_PATH = process.env.LBRY_DAEMON || path.join(__static, 'daemon/lbrynet-daemon'); "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 const rendererUrl = isDevelopment
? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`
: `file://${__dirname}/index.html`; : `file://${__dirname}/index.html`;
let client = jayson.client.http({ const client = jayson.client.http({
host: 'localhost', host: "localhost",
port: 5279, port: 5279,
path: '/', path: "/",
timeout: 1000 timeout: 1000,
}); });
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
@ -84,11 +95,10 @@ function processRequestedUri(uri) {
// lbry://channel/#claimid. We remove the slash here as well. // lbry://channel/#claimid. We remove the slash here as well.
// On Linux and Mac, we just return the URI as given. // On Linux and Mac, we just return the URI as given.
if (process.platform === 'win32') { if (process.platform === "win32") {
return uri.replace(/\/$/, '').replace('/#', '#'); return uri.replace(/\/$/, "").replace("/#", "#");
} else {
return uri;
} }
return uri;
} }
/* /*
@ -97,69 +107,85 @@ function processRequestedUri(uri) {
* when no windows are open. * when no windows are open.
*/ */
function openItem(fullPath) { function openItem(fullPath) {
const subprocOptions = { const subprocOptions = {
detached: true, detached: true,
stdio: 'ignore', stdio: "ignore",
}; };
let child; let child;
if (process.platform === 'darwin') { if (process.platform === "darwin") {
child = child_process.spawn('open', [fullPath], subprocOptions); child = child_process.spawn("open", [fullPath], subprocOptions);
} else if (process.platform === 'linux') { } else if (process.platform === "linux") {
child = child_process.spawn('xdg-open', [fullPath], subprocOptions); child = child_process.spawn("xdg-open", [fullPath], subprocOptions);
} else if (process.platform === 'win32') { } else if (process.platform === "win32") {
child = child_process.spawn(fullPath, Object.assign({}, subprocOptions, {shell: true})); child = child_process.spawn(
} fullPath,
Object.assign({}, subprocOptions, { shell: true })
);
}
// Causes child process reference to be garbage collected, allowing main process to exit // Causes child process reference to be garbage collected, allowing main process to exit
child.unref(); child.unref();
} }
function getPidsForProcessName(name) { function getPidsForProcessName(name) {
if (process.platform === 'win32') { if (process.platform === "win32") {
const tasklistOut = child_process.execSync(`tasklist /fi "Imagename eq ${name}.exe" /nh`, {encoding: 'utf8'}); const tasklistOut = child_process.execSync(
if (tasklistOut.startsWith('INFO')) { `tasklist /fi "Imagename eq ${name}.exe" /nh`,
{ encoding: "utf8" }
);
if (tasklistOut.startsWith("INFO")) {
return []; return [];
} else {
return tasklistOut.match(/[^\r\n]+/g).map((line) => line.split(/\s+/)[1]); // Second column of every non-empty line
} }
} else { 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);
} }
const pgrepOut = child_process.spawnSync("pgrep", ["-x", name], {
encoding: "utf8",
}).stdout;
return pgrepOut.match(/\d+/g);
} }
function createWindow () { function createWindow() {
// Disable renderer process's webSecurity on development to enable CORS. // Disable renderer process's webSecurity on development to enable CORS.
win = isDevelopment win = isDevelopment
? new BrowserWindow({backgroundColor: '#155B4A', minWidth: 800, minHeight: 600, webPreferences: {webSecurity: false}}) ? new BrowserWindow({
: new BrowserWindow({backgroundColor: '#155B4A', minWidth: 800, minHeight: 600}); backgroundColor: "#155B4A",
minWidth: 800,
minHeight: 600,
webPreferences: { webSecurity: false },
})
: new BrowserWindow({
backgroundColor: "#155B4A",
minWidth: 800,
minHeight: 600,
});
win.webContents.session.setUserAgent(`LBRY/${localVersion}`); win.webContents.session.setUserAgent(`LBRY/${localVersion}`);
win.maximize() win.maximize();
if (isDevelopment) { if (isDevelopment) {
win.webContents.openDevTools(); win.webContents.openDevTools();
} }
win.loadURL(rendererUrl) win.loadURL(rendererUrl);
if (openUri) { // We stored and received a URI that an external app requested before we had a window object if (openUri) {
win.webContents.on('did-finish-load', () => { // We stored and received a URI that an external app requested before we had a window object
win.webContents.send('open-uri-requested', openUri); win.webContents.on("did-finish-load", () => {
win.webContents.send("open-uri-requested", openUri);
}); });
} }
win.removeAllListeners(); win.removeAllListeners();
win.on('close', function(event) { win.on("close", event => {
if (minimize) { if (minimize) {
event.preventDefault(); event.preventDefault();
win.hide(); win.hide();
} }
}) });
win.on('closed', () => { win.on("closed", () => {
win = null win = null;
}) });
win.on("hide", () => { win.on("hide", () => {
// Checks what to show in the tray icon menu // Checks what to show in the tray icon menu
@ -176,7 +202,7 @@ function createWindow () {
if (minimize) updateTray(); if (minimize) updateTray();
// Unregisters Alt+F4 shortcut // Unregisters Alt+F4 shortcut
globalShortcut.unregister('Alt+F4'); globalShortcut.unregister("Alt+F4");
}); });
win.on("focus", () => { win.on("focus", () => {
@ -184,23 +210,22 @@ function createWindow () {
if (minimize) updateTray(); if (minimize) updateTray();
// Registers shortcut for closing(quitting) the app // Registers shortcut for closing(quitting) the app
globalShortcut.register('Alt+F4', () => safeQuit()); globalShortcut.register("Alt+F4", () => safeQuit());
win.webContents.send('window-is-focused', null); win.webContents.send("window-is-focused", null);
}); });
// Menu bar // Menu bar
win.setAutoHideMenuBar(true); win.setAutoHideMenuBar(true);
win.setMenuBarVisibility(isDevelopment); win.setMenuBarVisibility(isDevelopment);
setMenu(); setMenu();
}
}; function createTray() {
function createTray () {
// Minimize to tray logic follows: // Minimize to tray logic follows:
// Set the tray icon // Set the tray icon
let iconPath; let iconPath;
if (process.platform === 'darwin') { if (process.platform === "darwin") {
// Using @2x for mac retina screens so the icon isn't blurry // 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 // file name needs to include "Template" at the end for dark menu bar
iconPath = path.join(__static, "/img/fav/macTemplate@2x.png"); iconPath = path.join(__static, "/img/fav/macTemplate@2x.png");
@ -211,14 +236,14 @@ function createTray () {
tray = new Tray(iconPath); tray = new Tray(iconPath);
tray.setToolTip("LBRY App"); tray.setToolTip("LBRY App");
tray.setTitle("LBRY"); tray.setTitle("LBRY");
tray.on('double-click', () => { tray.on("double-click", () => {
win.show() win.show();
}) });
} }
// This needs to be done as for linux the context menu doesn't update automatically(docs) // This needs to be done as for linux the context menu doesn't update automatically(docs)
function updateTray() { function updateTray() {
let contextMenu = Menu.buildFromTemplate(getMenuTemplate()); const contextMenu = Menu.buildFromTemplate(getMenuTemplate());
if (tray) { if (tray) {
tray.setContextMenu(contextMenu); tray.setContextMenu(contextMenu);
} else { } else {
@ -226,28 +251,26 @@ function updateTray() {
} }
} }
function getMenuTemplate () { function getMenuTemplate() {
return [ return [
getToggleItem(), getToggleItem(),
{ {
label: "Quit", label: "Quit",
click: () => safeQuit(), click: () => safeQuit(),
}, },
] ];
function getToggleItem () { function getToggleItem() {
if (win.isVisible() && win.isFocused()) { if (win.isVisible() && win.isFocused()) {
return { return {
label: 'Hide LBRY App', label: "Hide LBRY App",
click: () => win.hide() click: () => win.hide(),
};
}
} else {
return {
label: 'Show LBRY App',
click: () => win.show()
}
} }
return {
label: "Show LBRY App",
click: () => win.show(),
};
} }
} }
@ -256,20 +279,19 @@ function handleOpenUriRequested(uri) {
// Window not created yet, so store up requested URI for when it is // Window not created yet, so store up requested URI for when it is
openUri = processRequestedUri(uri); openUri = processRequestedUri(uri);
} else { } else {
if (win.isMinimized()) { if (win.isMinimized()) {
win.restore() win.restore();
} else if (!win.isVisible()) { } else if (!win.isVisible()) {
win.show() win.show();
} }
win.focus(); win.focus();
win.webContents.send('open-uri-requested', processRequestedUri(uri)); win.webContents.send("open-uri-requested", processRequestedUri(uri));
} }
} }
function handleDaemonSubprocessExited() { function handleDaemonSubprocessExited() {
console.log('The daemon has exited.'); console.log("The daemon has exited.");
daemonSubprocess = null; daemonSubprocess = null;
if (!daemonStopRequested) { if (!daemonStopRequested) {
// We didn't request to stop the daemon, so display a // We didn't request to stop the daemon, so display a
@ -277,27 +299,31 @@ function handleDaemonSubprocessExited() {
// //
// TODO: maybe it would be better to restart the daemon? // TODO: maybe it would be better to restart the daemon?
if (win) { if (win) {
console.log('Did not request daemon stop, so quitting in 5 seconds.'); console.log("Did not request daemon stop, so quitting in 5 seconds.");
win.loadURL(`file://${__static}/warning.html`); win.loadURL(`file://${__static}/warning.html`);
setTimeout(quitNow, 5000); setTimeout(quitNow, 5000);
} else { } else {
console.log('Did not request daemon stop, so quitting.'); console.log("Did not request daemon stop, so quitting.");
quitNow(); quitNow();
} }
} }
} }
function launchDaemon() { function launchDaemon() {
assert(!daemonSubprocess, 'Tried to launch daemon twice'); assert(!daemonSubprocess, "Tried to launch daemon twice");
console.log('Launching daemon:', DAEMON_PATH) console.log("Launching daemon:", DAEMON_PATH);
daemonSubprocess = child_process.spawn(DAEMON_PATH) daemonSubprocess = child_process.spawn(DAEMON_PATH);
// Need to handle the data event instead of attaching to // Need to handle the data event instead of attaching to
// process.stdout because the latter doesn't work. I believe on // process.stdout because the latter doesn't work. I believe on
// windows it buffers stdout and we don't get any meaningful output // windows it buffers stdout and we don't get any meaningful output
daemonSubprocess.stdout.on('data', (buf) => {console.log(String(buf).trim());}); daemonSubprocess.stdout.on("data", buf => {
daemonSubprocess.stderr.on('data', (buf) => {console.log(String(buf).trim());}); console.log(String(buf).trim());
daemonSubprocess.on('exit', handleDaemonSubprocessExited); });
daemonSubprocess.stderr.on("data", buf => {
console.log(String(buf).trim());
});
daemonSubprocess.on("exit", handleDaemonSubprocessExited);
} }
/* /*
@ -318,7 +344,7 @@ function quitNow() {
safeQuit(); safeQuit();
} }
const isSecondaryInstance = app.makeSingleInstance((argv) => { const isSecondaryInstance = app.makeSingleInstance(argv => {
if (argv.length >= 2) { if (argv.length >= 2) {
handleOpenUriRequested(argv[1]); // This will handle restoring and focusing the window handleOpenUriRequested(argv[1]); // This will handle restoring and focusing the window
} else if (win) { } else if (win) {
@ -331,25 +357,23 @@ const isSecondaryInstance = app.makeSingleInstance((argv) => {
} }
}); });
if (isSecondaryInstance) { // We're not in the original process, so quit if (isSecondaryInstance) {
// We're not in the original process, so quit
quitNow(); quitNow();
} }
function launchDaemonIfNotRunning() { function launchDaemonIfNotRunning() {
// Check if the daemon is already running. If we get // Check if the daemon is already running. If we get
// an error its because its not running // an error its because its not running
console.log('Checking for lbrynet daemon'); console.log("Checking for lbrynet daemon");
client.request( client.request("status", [], (err, res) => {
'status', [], if (err) {
function (err, res) { console.log("lbrynet daemon needs to be launched");
if (err) { launchDaemon();
console.log('lbrynet daemon needs to be launched') } else {
launchDaemon(); console.log("lbrynet daemon is already running");
} else {
console.log('lbrynet daemon is already running')
}
} }
); });
} }
/* /*
@ -358,21 +382,31 @@ function launchDaemonIfNotRunning() {
* tries to force kill them. * tries to force kill them.
*/ */
function forceKillAllDaemonsAndQuit() { function forceKillAllDaemonsAndQuit() {
console.log('Attempting to force kill any running lbrynet-daemon instances...'); console.log(
"Attempting to force kill any running lbrynet-daemon instances..."
);
const daemonPids = getPidsForProcessName('lbrynet-daemon'); const daemonPids = getPidsForProcessName("lbrynet-daemon");
if (!daemonPids) { if (!daemonPids) {
console.log('No lbrynet-daemon found running.'); console.log("No lbrynet-daemon found running.");
quitNow(); quitNow();
} else { } else {
console.log(`Found ${daemonPids.length} running daemon instances. Attempting to force kill...`); console.log(
`Found ${
daemonPids.length
} running daemon instances. Attempting to force kill...`
);
for (const pid of daemonPids) { for (const pid of daemonPids) {
let daemonKillAttemptsComplete = 0; let daemonKillAttemptsComplete = 0;
kill(pid, 'SIGKILL', (err) => { kill(pid, "SIGKILL", err => {
daemonKillAttemptsComplete++; daemonKillAttemptsComplete++;
if (err) { if (err) {
console.log(`Failed to force kill daemon task with pid ${pid}. Error message: ${err.message}`); console.log(
`Failed to force kill daemon task with pid ${pid}. Error message: ${
err.message
}`
);
} else { } else {
console.log(`Force killed daemon task with pid ${pid}.`); console.log(`Force killed daemon task with pid ${pid}.`);
} }
@ -384,15 +418,15 @@ function forceKillAllDaemonsAndQuit() {
} }
} }
app.setAsDefaultProtocolClient('lbry'); app.setAsDefaultProtocolClient("lbry");
app.on('ready', function() { app.on("ready", () => {
launchDaemonIfNotRunning(); launchDaemonIfNotRunning();
if (process.platform === "linux") { if (process.platform === "linux") {
checkLinuxTraySupport( err => { checkLinuxTraySupport(err => {
if (!err) createTray(); if (!err) createTray();
else minimize = false; else minimize = false;
}) });
} else { } else {
createTray(); createTray();
} }
@ -400,36 +434,35 @@ app.on('ready', function() {
}); });
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', () => { app.on("window-all-closed", () => {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== "darwin") {
app.quit() app.quit();
} }
}) });
app.on("before-quit", event => {
app.on('before-quit', (event) => {
if (!readyToQuit) { if (!readyToQuit) {
// We need to shutdown the daemon before we're ready to actually quit. This // 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 will be triggered re-entrantly once preparation is done.
event.preventDefault(); event.preventDefault();
shutdownDaemonAndQuit(); shutdownDaemonAndQuit();
} else { } else {
console.log('Quitting.') console.log("Quitting.");
} }
}); });
app.on('activate', () => { app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the // 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. // dock icon is clicked and there are no other windows open.
if (win === null) { if (win === null) {
createWindow() createWindow();
} }
}); });
if (process.platform === 'darwin') { if (process.platform === "darwin") {
app.on('open-url', (event, uri) => { app.on("open-url", (event, uri) => {
handleOpenUriRequested(uri); handleOpenUriRequested(uri);
}); });
} else if (process.argv.length >= 2) { } else if (process.argv.length >= 2) {
@ -440,14 +473,18 @@ if (process.platform === 'darwin') {
// then calls quitNow() to quit for real. // then calls quitNow() to quit for real.
function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
function doShutdown() { function doShutdown() {
console.log('Shutting down daemon'); console.log("Shutting down daemon");
daemonStopRequested = true; daemonStopRequested = true;
client.request('daemon_stop', [], (err, res) => { client.request("daemon_stop", [], (err, res) => {
if (err) { if (err) {
console.log(`received error when stopping lbrynet-daemon. Error message: ${err.message}\n`); console.log(
console.log('You will need to manually kill the daemon.'); `received error when stopping lbrynet-daemon. Error message: ${
err.message
}\n`
);
console.log("You will need to manually kill the daemon.");
} else { } else {
console.log('Successfully stopped daemon via RPC call.') console.log("Successfully stopped daemon via RPC call.");
quitNow(); quitNow();
} }
}); });
@ -456,7 +493,7 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
if (daemonSubprocess) { if (daemonSubprocess) {
doShutdown(); doShutdown();
} else if (!evenIfNotStartedByApp) { } 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(); quitNow();
} else { } else {
doShutdown(); doShutdown();
@ -467,24 +504,27 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
} }
// Taken from webtorrent-desktop // Taken from webtorrent-desktop
function checkLinuxTraySupport (cb) { function checkLinuxTraySupport(cb) {
// Check that we're on Ubuntu (or another debian system) and that we have // Check that we're on Ubuntu (or another debian system) and that we have
// libappindicator1. // libappindicator1.
child_process.exec('dpkg --get-selections libappindicator1', function (err, stdout) { child_process.exec(
if (err) return cb(err) "dpkg --get-selections libappindicator1",
// Unfortunately there's no cleaner way, as far as I can tell, to check (err, stdout) => {
// whether a debian package is installed: if (err) return cb(err);
if (stdout.endsWith('\tinstall\n')) { // Unfortunately there's no cleaner way, as far as I can tell, to check
cb(null) // whether a debian package is installed:
} else { if (stdout.endsWith("\tinstall\n")) {
cb(new Error('debian package not installed')) cb(null);
} else {
cb(new Error("debian package not installed"));
}
} }
}) );
} }
ipcMain.on('upgrade', (event, installerPath) => { ipcMain.on("upgrade", (event, installerPath) => {
app.on('quit', () => { app.on("quit", () => {
console.log('Launching upgrade installer at', installerPath); console.log("Launching upgrade installer at", installerPath);
// This gets triggered called after *all* other quit-related events, so // 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. // we'll only get here if we're fully prepared and quitting for real.
openItem(installerPath); openItem(installerPath);
@ -497,58 +537,77 @@ ipcMain.on('upgrade', (event, installerPath) => {
shutdownDaemonAndQuit(true); shutdownDaemonAndQuit(true);
// wait for daemon to shut down before upgrading // wait for daemon to shut down before upgrading
// what to do if no shutdown in a long time? // 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.'); console.log(
console.log('After the install is complete, please reopen the app.'); "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.");
}); });
ipcMain.on('version-info-requested', () => { ipcMain.on("version-info-requested", () => {
function formatRc(ver) { function formatRc(ver) {
// Adds dash if needed to make RC suffix semver friendly // 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 = { const opts = {
headers: { headers: {
'User-Agent': `LBRY/${localVersion}`, "User-Agent": `LBRY/${localVersion}`,
} },
}; };
const req = https.get(Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)), (res) => { const req = https.get(
res.on('data', (data) => { Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)),
result += data; res => {
}); res.on("data", data => {
res.on('end', () => { result += data;
const tagName = JSON.parse(result).tag_name; });
const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); res.on("end", () => {
if (!remoteVersion) { const tagName = JSON.parse(result).tag_name;
if (win) { const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/);
win.webContents.send('version-info-received', null); 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,
});
}
} }
} else { });
const upgradeAvailable = semver.gt(formatRc(remoteVersion), formatRc(localVersion)); }
if (win) { );
win.webContents.send('version-info-received', {remoteVersion, localVersion, upgradeAvailable});
}
}
})
});
req.on('error', (err) => { req.on("error", err => {
console.log('Failed to get current version from GitHub. Error:', err); console.log("Failed to get current version from GitHub. Error:", err);
if (win) { if (win) {
win.webContents.send('version-info-received', null); win.webContents.send("version-info-received", null);
} }
}); });
}); });
ipcMain.on('get-auth-token', (event) => { ipcMain.on("get-auth-token", event => {
keytar.getPassword("LBRY", "auth_token").then(token => { keytar.getPassword("LBRY", "auth_token").then(token => {
event.sender.send('auth-token-response', token ? token.toString().trim() : null) event.sender.send(
"auth-token-response",
token ? token.toString().trim() : null
);
}); });
}); });
ipcMain.on('set-auth-token', (event, token) => { ipcMain.on("set-auth-token", (event, token) => {
keytar.setPassword("LBRY", "auth_token", token ? token.toString().trim() : null); keytar.setPassword(
"LBRY",
"auth_token",
token ? token.toString().trim() : null
);
}); });

View file

@ -1,34 +1,33 @@
const {Menu} = require('electron'); const { Menu } = require("electron");
const electron = require('electron'); const electron = require("electron");
const app = electron.app; const app = electron.app;
const contextMenuTemplate = [ const contextMenuTemplate = [
{ {
role: 'cut', role: "cut",
}, },
{ {
role: 'copy', role: "copy",
}, },
{ {
role: 'paste', role: "paste",
}, },
]; ];
module.exports = { module.exports = {
showContextMenu(win, posX, posY, showDevItems) { showContextMenu(win, posX, posY, showDevItems) {
let template = contextMenuTemplate.slice(); const template = contextMenuTemplate.slice();
if (showDevItems) { if (showDevItems) {
template.push({ template.push({
type: 'separator', type: "separator",
});
template.push({
label: "Inspect Element",
click() {
win.inspectElement(posX, posY);
},
}); });
template.push(
{
label: 'Inspect Element',
click() {
win.inspectElement(posX, posY);
}
}
);
} }
Menu.buildFromTemplate(template).popup(win); Menu.buildFromTemplate(template).popup(win);

View file

@ -1,136 +1,136 @@
const { app, shell, Menu } = require('electron'); const { app, shell, Menu } = require("electron");
const { safeQuit } = require('../index.js'); const { safeQuit } = require("../index.js");
const baseTemplate = [ const baseTemplate = [
{ {
label: 'File', label: "File",
submenu: [ submenu: [
{ {
label: 'Quit', label: "Quit",
accelerator: "CommandOrControl+Q", accelerator: "CommandOrControl+Q",
click: () => safeQuit(), click: () => safeQuit(),
}, },
] ],
}, },
{ {
label: 'Edit', label: "Edit",
submenu: [ submenu: [
{ {
role: 'undo', role: "undo",
}, },
{ {
role: 'redo', role: "redo",
}, },
{ {
type: 'separator', type: "separator",
}, },
{ {
role: 'cut', role: "cut",
}, },
{ {
role: 'copy', role: "copy",
}, },
{ {
role: 'paste', role: "paste",
}, },
{ {
role: 'selectall', role: "selectall",
}, },
] ],
}, },
{ {
label: 'View', label: "View",
submenu: [ submenu: [
{ {
role: 'reload' role: "reload",
}, },
{ {
label: 'Developer', label: "Developer",
submenu: [ submenu: [
{ {
role: 'forcereload' role: "forcereload",
}, },
{ {
role: 'toggledevtools' role: "toggledevtools",
}, },
] ],
}, },
{ {
type: 'separator' type: "separator",
}, },
{ {
role: 'togglefullscreen' role: "togglefullscreen",
} },
] ],
}, },
{ {
role: 'help', role: "help",
submenu: [ submenu: [
{ {
label: 'Learn More', label: "Learn More",
click(item, focusedWindow) { click(item, focusedWindow) {
if (focusedWindow) { if (focusedWindow) {
focusedWindow.webContents.send('open-menu', '/help'); focusedWindow.webContents.send("open-menu", "/help");
} }
} },
}, },
{ {
label: 'Frequently Asked Questions', label: "Frequently Asked Questions",
click(item, focusedWindow){ click(item, focusedWindow) {
shell.openExternal('https://lbry.io/faq') shell.openExternal("https://lbry.io/faq");
} },
}, },
{ {
type: 'separator' type: "separator",
}, },
{ {
label: 'Report Issue', label: "Report Issue",
click(item, focusedWindow){ click(item, focusedWindow) {
shell.openExternal('https://lbry.io/faq/contributing#report-a-bug'); shell.openExternal("https://lbry.io/faq/contributing#report-a-bug");
} },
}, },
{ {
type: 'separator' type: "separator",
}, },
{ {
label: 'Developer API Guide', label: "Developer API Guide",
click(item, focusedWindow){ click(item, focusedWindow) {
shell.openExternal('https://lbry.io/quickstart') shell.openExternal("https://lbry.io/quickstart");
} },
}, },
] ],
} },
]; ];
const macOSAppMenuTemplate = { const macOSAppMenuTemplate = {
label: app.getName(), label: app.getName(),
submenu: [ submenu: [
{ {
role: 'about', role: "about",
}, },
{ {
type: 'separator', type: "separator",
}, },
{ {
role: 'hide', role: "hide",
}, },
{ {
role: 'hideothers', role: "hideothers",
}, },
{ {
role: 'unhide', role: "unhide",
}, },
{ {
type: 'separator', type: "separator",
}, },
{ {
role: 'quit', role: "quit",
}, },
] ],
}; };
module.exports = () => { module.exports = () => {
let template = baseTemplate.slice(); const template = baseTemplate.slice();
(process.platform === 'darwin') && template.unshift(macOSAppMenuTemplate); process.platform === "darwin" && template.unshift(macOSAppMenuTemplate);
Menu.setApplicationMenu(Menu.buildFromTemplate(template)); Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}; };

View file

@ -6,18 +6,19 @@ const config = {
...require(`./config/${env}`), ...require(`./config/${env}`),
}; };
const i18n = require("y18n")({ const i18n = require("y18n")({
directory: remote.app.getAppPath() + "/locales", directory: `${remote.app.getAppPath()}/locales`,
updateFiles: false, updateFiles: false,
locale: "en", locale: "en",
}); });
const logs = []; const logs = [];
const app = { const app = {
env: env, env,
config: config, config,
store: store, store,
i18n: i18n, i18n,
logs: logs, logs,
log: function(message) { log(message) {
logs.push(message); logs.push(message);
}, },
}; };

View file

@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import { formatCredits, formatFullPrice } from "util/formatCredits"; import { formatCredits, formatFullPrice } from "util/formatCredits";
import lbry from "../lbry.js"; import lbry from "../lbry.js";
//component/icon.js // component/icon.js
export class Icon extends React.PureComponent { export class Icon extends React.PureComponent {
static propTypes = { static propTypes = {
icon: PropTypes.string.isRequired, icon: PropTypes.string.isRequired,
@ -13,12 +13,9 @@ export class Icon extends React.PureComponent {
render() { render() {
const { fixed, className } = this.props; const { fixed, className } = this.props;
const spanClassName = const spanClassName = `icon ${
"icon " + "fixed" in this.props ? "icon-fixed-width " : ""
("fixed" in this.props ? "icon-fixed-width " : "") + }${this.props.icon} ${this.props.className || ""}`;
this.props.icon +
" " +
(this.props.className || "");
return <span className={spanClassName} />; return <span className={spanClassName} />;
} }
} }
@ -90,14 +87,14 @@ export class CreditAmount extends React.PureComponent {
const { amount, precision, showFullPrice } = this.props; const { amount, precision, showFullPrice } = this.props;
let formattedAmount; let formattedAmount;
let fullPrice = formatFullPrice(amount, 2); const fullPrice = formatFullPrice(amount, 2);
if (showFullPrice) { if (showFullPrice) {
formattedAmount = fullPrice; formattedAmount = fullPrice;
} else { } else {
formattedAmount = formattedAmount =
amount > 0 && amount < minimumRenderableAmount amount > 0 && amount < minimumRenderableAmount
? "<" + minimumRenderableAmount ? `<${minimumRenderableAmount}`
: formatCredits(amount, precision); : formatCredits(amount, precision);
} }
@ -111,12 +108,12 @@ export class CreditAmount extends React.PureComponent {
? this.props.label ? this.props.label
: parseFloat(amount) == 1 ? __("credit") : __("credits"); : parseFloat(amount) == 1 ? __("credit") : __("credits");
amountText = formattedAmount + " " + label; amountText = `${formattedAmount} ${label}`;
} else { } else {
amountText = formattedAmount; amountText = formattedAmount;
} }
if (this.props.showPlus && amount > 0) { if (this.props.showPlus && amount > 0) {
amountText = "+" + amountText; amountText = `+${amountText}`;
} }
} }

View file

@ -2,6 +2,7 @@ import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
const { remote } = require("electron"); const { remote } = require("electron");
class FileSelector extends React.PureComponent { class FileSelector extends React.PureComponent {
static propTypes = { static propTypes = {
type: PropTypes.oneOf(["file", "directory"]), type: PropTypes.oneOf(["file", "directory"]),
@ -40,7 +41,7 @@ class FileSelector extends React.PureComponent {
const path = paths[0]; const path = paths[0];
this.setState({ this.setState({
path: path, path,
}); });
if (this.props.onFileChosen) { if (this.props.onFileChosen) {
this.props.onFileChosen(path); this.props.onFileChosen(path);

View file

@ -8,7 +8,7 @@ import FileActions from "./view";
const select = (state, props) => ({ const select = (state, props) => ({
fileInfo: makeSelectFileInfoForUri(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state),
/*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ /* availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix */
costInfo: makeSelectCostInfoForUri(props.uri)(state), costInfo: makeSelectCostInfoForUri(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state), claimIsMine: makeSelectClaimIsMine(props.uri)(state),
}); });

View file

@ -13,7 +13,7 @@ import FileDownloadLink from "./view";
const select = (state, props) => ({ const select = (state, props) => ({
fileInfo: makeSelectFileInfoForUri(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state),
/*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ /* availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix */
downloading: makeSelectDownloadingForUri(props.uri)(state), downloading: makeSelectDownloadingForUri(props.uri)(state),
costInfo: makeSelectCostInfoForUri(props.uri)(state), costInfo: makeSelectCostInfoForUri(props.uri)(state),
loading: makeSelectLoadingForUri(props.uri)(state), loading: makeSelectLoadingForUri(props.uri)(state),

View file

@ -8,7 +8,7 @@ let formFieldCounter = 0;
export const formFieldNestedLabelTypes = ["radio", "checkbox"]; export const formFieldNestedLabelTypes = ["radio", "checkbox"];
export function formFieldId() { export function formFieldId() {
return "form-field-" + ++formFieldCounter; return `form-field-${++formFieldCounter}`;
} }
export class Form extends React.PureComponent { export class Form extends React.PureComponent {
@ -129,21 +129,19 @@ export class FormRow extends React.PureComponent {
return ( return (
<div <div
className={"form-row" + (this.state.isFocus ? " form-row--focus" : "")} className={`form-row${this.state.isFocus ? " form-row--focus" : ""}`}
> >
{this.props.label && !renderLabelInFormField ? ( {this.props.label && !renderLabelInFormField ? (
<div <div
className={ className={`form-row__label-row ${
"form-row__label-row " + this.props.labelPrefix ? "form-row__label-row--prefix" : ""
(this.props.labelPrefix ? "form-row__label-row--prefix" : "") }`}
}
> >
<label <label
htmlFor={elementId} htmlFor={elementId}
className={ className={`form-field__label ${
"form-field__label " + this.state.isError ? "form-field__label--error" : " "
(this.state.isError ? "form-field__label--error" : " ") }`}
}
> >
{this.props.label} {this.props.label}
</label> </label>
@ -178,16 +176,14 @@ export class FormRow extends React.PureComponent {
export const Submit = props => { export const Submit = props => {
const { title, label, icon, disabled } = props; const { title, label, icon, disabled } = props;
const className = const className = `${"button-block" +
"button-block" +
" button-primary" + " button-primary" +
" button-set-item" + " button-set-item" +
" button--submit" + " button--submit"}${disabled ? " disabled" : ""}`;
(disabled ? " disabled" : "");
const content = ( const content = (
<span className="button__content"> <span className="button__content">
{"icon" in props ? <Icon icon={icon} fixed={true} /> : null} {"icon" in props ? <Icon icon={icon} fixed /> : null}
{label ? <span className="button-label">{label}</span> : null} {label ? <span className="button-label">{label}</span> : null}
</span> </span>
); );

View file

@ -37,15 +37,14 @@ class LoadScreen extends React.PureComponent {
) : ( ) : (
<span> <span>
<Icon icon="icon-warning" /> <Icon icon="icon-warning" />
{" " + this.props.message} {` ${this.props.message}`}
</span> </span>
)} )}
</h3> </h3>
<span <span
className={ className={`load-screen__details ${
"load-screen__details " + this.props.isWarning ? "load-screen__details--warning" : ""
(this.props.isWarning ? "load-screen__details--warning" : "") }`}
}
> >
{this.props.details} {this.props.details}
</span> </span>

View file

@ -16,7 +16,7 @@ export class DropDownMenuItem extends React.PureComponent {
}; };
render() { render() {
var icon = this.props.icon ? <Icon icon={this.props.icon} fixed /> : null; const icon = this.props.icon ? <Icon icon={this.props.icon} fixed /> : null;
return ( return (
<a <a
@ -70,7 +70,7 @@ export class DropDownMenu extends React.PureComponent {
}); });
} }
/*this will force "this" to always be the class, even when passed to an event listener*/ /* this will force "this" to always be the class, even when passed to an event listener */
handleWindowClick = e => { handleWindowClick = e => {
if ( if (
this.state.menuOpen && this.state.menuOpen &&

View file

@ -8,12 +8,10 @@ import {
import { doCheckDaemonVersion } from "redux/actions/app"; import { doCheckDaemonVersion } from "redux/actions/app";
import SplashScreen from "./view"; import SplashScreen from "./view";
const select = state => { const select = state => ({
return { modal: selectCurrentModal(state),
modal: selectCurrentModal(state), daemonVersionMatched: selectDaemonVersionMatched(state),
daemonVersionMatched: selectDaemonVersionMatched(state), });
};
};
const perform = dispatch => ({ const perform = dispatch => ({
checkDaemonVersion: () => dispatch(doCheckDaemonVersion()), checkDaemonVersion: () => dispatch(doCheckDaemonVersion()),

View file

@ -3,7 +3,8 @@ import {
doChannelSubscribe, doChannelSubscribe,
doChannelUnsubscribe, doChannelUnsubscribe,
} from "redux/actions/subscriptions"; } from "redux/actions/subscriptions";
import { selectSubscriptions } from "redux/selectors/subscriptions";; import { selectSubscriptions } from "redux/selectors/subscriptions";
import SubscribeButton from "./view"; import SubscribeButton from "./view";
const select = (state, props) => ({ const select = (state, props) => ({
@ -12,5 +13,5 @@ const select = (state, props) => ({
export default connect(select, { export default connect(select, {
doChannelSubscribe, doChannelSubscribe,
doChannelUnsubscribe doChannelUnsubscribe,
})(SubscribeButton); })(SubscribeButton);

View file

@ -29,7 +29,7 @@ export class ToolTip extends React.PureComponent {
render() { render() {
return ( return (
<span className={"tooltip " + (this.props.className || "")}> <span className={`tooltip ${this.props.className || ""}`}>
<a <a
className="tooltip__link" className="tooltip__link"
onClick={() => { onClick={() => {
@ -39,9 +39,7 @@ export class ToolTip extends React.PureComponent {
{this.props.label} {this.props.label}
</a> </a>
<div <div
className={ className={`tooltip__body ${this.state.showTooltip ? "" : " hidden"}`}
"tooltip__body " + (this.state.showTooltip ? "" : " hidden")
}
onMouseOut={() => { onMouseOut={() => {
this.handleTooltipMouseOut(); this.handleTooltipMouseOut();
}} }}

View file

@ -141,7 +141,7 @@ export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE";
export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR";
export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED";
//Language // Language
export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED"; export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED";
export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED"; export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED";

View file

@ -1,6 +1,6 @@
/*hardcoded names still exist for these in reducers/settings.js - only discovered when debugging*/ /* hardcoded names still exist for these in reducers/settings.js - only discovered when debugging */
/*Many settings are stored in the localStorage by their name - /* 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*/ 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 CREDIT_REQUIRED_ACKNOWLEDGED = "credit_required_acknowledged";
export const NEW_USER_ACKNOWLEDGED = "welcome_acknowledged"; export const NEW_USER_ACKNOWLEDGED = "welcome_acknowledged";
export const EMAIL_COLLECTION_ACKNOWLEDGED = "email_collection_acknowledged"; export const EMAIL_COLLECTION_ACKNOWLEDGED = "email_collection_acknowledged";

View file

@ -1,18 +1,18 @@
var extract = require("i18n-extract"); const extract = require("i18n-extract");
const fs = require("fs"); const fs = require("fs");
var dir = __dirname + "/../../dist/locales"; const dir = `${__dirname}/../../dist/locales`;
var path = dir + "/en.json"; const path = `${dir}/en.json`;
if (!fs.existsSync(dir)) { if (!fs.existsSync(dir)) {
fs.mkdirSync(dir); fs.mkdirSync(dir);
} }
fs.writeFile(path, "{}", "utf8", function(err) { fs.writeFile(path, "{}", "utf8", err => {
if (err) { if (err) {
return console.log(err); return console.log(err);
} }
var enLocale = require(path); const enLocale = require(path);
const keys = extract.extractFromFiles(["js/**/*.{js,jsx}"], { const keys = extract.extractFromFiles(["js/**/*.{js,jsx}"], {
marker: "__", marker: "__",
@ -22,21 +22,21 @@ fs.writeFile(path, "{}", "utf8", function(err) {
reports = reports.concat(extract.findMissing(enLocale, keys)); reports = reports.concat(extract.findMissing(enLocale, keys));
if (reports.length > 0) { if (reports.length > 0) {
fs.readFile(path, "utf8", function readFileCallback(err, data) { fs.readFile(path, "utf8", (err, data) => {
if (err) { if (err) {
console.log(err); console.log(err);
} else { } else {
localeObj = JSON.parse(data); localeObj = JSON.parse(data);
for (var i = 0; i < reports.length; i++) { for (let i = 0; i < reports.length; i++) {
// no need to care for other types than MISSING because starting file will always be empty // no need to care for other types than MISSING because starting file will always be empty
if (reports[i].type === "MISSING") { if (reports[i].type === "MISSING") {
localeObj[reports[i].key] = reports[i].key; localeObj[reports[i].key] = reports[i].key;
} }
} }
var json = JSON.stringify(localeObj, null, "\t"); //convert it back to json-string const json = JSON.stringify(localeObj, null, "\t"); // convert it back to json-string
fs.writeFile(path, json, "utf8", function callback(err) { fs.writeFile(path, json, "utf8", err => {
if (err) { if (err) {
throw err; throw err;
} }

View file

@ -15,12 +15,15 @@ import "scss/all.scss";
const env = process.env.NODE_ENV || "production"; const env = process.env.NODE_ENV || "production";
const { remote, ipcRenderer, shell } = require("electron"); const { remote, ipcRenderer, shell } = require("electron");
const contextMenu = remote.require("./main.js").contextMenu; const contextMenu = remote.require("./main.js").contextMenu;
const app = require("./app"); const app = require("./app");
// Workaround for https://github.com/electron-userland/electron-webpack/issues/52 // Workaround for https://github.com/electron-userland/electron-webpack/issues/52
if (process.env.NODE_ENV !== 'development') { if (process.env.NODE_ENV !== "development") {
window.staticResourcesPath = require("path").join(remote.app.getAppPath(), "../static").replace(/\\/g, "\\\\"); window.staticResourcesPath = require("path")
.join(remote.app.getAppPath(), "../static")
.replace(/\\/g, "\\\\");
} else { } else {
window.staticResourcesPath = ""; window.staticResourcesPath = "";
} }
@ -56,12 +59,12 @@ ipcRenderer.on("window-is-focused", (event, data) => {
}); });
document.addEventListener("click", event => { document.addEventListener("click", event => {
var target = event.target; let target = event.target;
while (target && target !== document) { 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) // TODO: Look into using accessiblity labels (this would also make the app more accessible)
let hrefParts = window.location.href.split("#"); const hrefParts = window.location.href.split("#");
let element = target.title || (target.text && target.text.trim()); const element = target.title || (target.text && target.text.trim());
if (element) { if (element) {
amplitude.getInstance().logEvent("CLICK", { amplitude.getInstance().logEvent("CLICK", {
target: element, target: element,
@ -89,7 +92,7 @@ document.addEventListener("click", event => {
const initialState = app.store.getState(); const initialState = app.store.getState();
var init = function() { const init = function() {
app.store.dispatch(doDownloadLanguages()); app.store.dispatch(doDownloadLanguages());
function onDaemonReady() { function onDaemonReady() {
@ -99,8 +102,8 @@ var init = function() {
"0b130efdcbdbf86ec2f7f9eff354033e", "0b130efdcbdbf86ec2f7f9eff354033e",
info.lbry_id, info.lbry_id,
null, null,
function() { () => {
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()); app.store.dispatch(doDaemonReady());
ReactDOM.render( ReactDOM.render(
@ -110,7 +113,7 @@ var init = function() {
<SnackBar /> <SnackBar />
</div> </div>
</Provider>, </Provider>,
document.getElementById('app') document.getElementById("app")
); );
} }
); );
@ -124,7 +127,7 @@ var init = function() {
<Provider store={store}> <Provider store={store}>
<SplashScreen onReadyToLaunch={onDaemonReady} /> <SplashScreen onReadyToLaunch={onDaemonReady} />
</Provider>, </Provider>,
document.getElementById('app') document.getElementById("app")
); );
} }
}; };

View file

@ -12,8 +12,10 @@ jsonrpc.call = function(
function checkAndParse(response) { function checkAndParse(response) {
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
return response.json(); return response.json();
} else { }
return response.json().then(json => { return response
.json()
.then(json => {
let error; let error;
if (json.error) { if (json.error) {
error = new Error(json.error); error = new Error(json.error);
@ -21,10 +23,10 @@ jsonrpc.call = function(
error = new Error("Protocol error with unknown response signature"); error = new Error("Protocol error with unknown response signature");
} }
return Promise.reject(error); return Promise.reject(error);
}).catch(e => { })
.catch(e => {
console.error(e); console.error(e);
}); });
}
} }
function makeRequest(url, options) { function makeRequest(url, options) {
@ -35,9 +37,7 @@ jsonrpc.call = function(
if (timeout) { if (timeout) {
const e = new Error(__("Protocol request timed out")); const e = new Error(__("Protocol request timed out"));
setTimeout(() => { setTimeout(() => reject(e), timeout);
return reject(e);
}, timeout);
} }
}); });
} }
@ -48,8 +48,8 @@ jsonrpc.call = function(
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
jsonrpc: "2.0", jsonrpc: "2.0",
method: method, method,
params: params, params,
id: counter, id: counter,
}), }),
}; };
@ -70,11 +70,11 @@ jsonrpc.call = function(
return errorCallback(error); return errorCallback(error);
} }
var errorEvent = new CustomEvent("unhandledError", { const errorEvent = new CustomEvent("unhandledError", {
detail: { detail: {
connectionString: connectionString, connectionString,
method: method, method,
params: params, params,
code: error.code, code: error.code,
message: error.message || error, message: error.message || error,
data: error.data, data: error.data,
@ -87,11 +87,11 @@ jsonrpc.call = function(
return connectFailedCallback(e); return connectFailedCallback(e);
} }
var errorEvent = new CustomEvent("unhandledError", { const errorEvent = new CustomEvent("unhandledError", {
detail: { detail: {
connectionString: connectionString, connectionString,
method: method, method,
params: params, params,
code: e.response && e.response.status, code: e.response && e.response.status,
message: __("Connection to API server failed"), message: __("Connection to API server failed"),
}, },

View file

@ -39,17 +39,17 @@ function savePendingPublish({ name, channel_name }) {
if (channel_name) { if (channel_name) {
uri = lbryuri.build({ name: channel_name, path: name }, false); uri = lbryuri.build({ name: channel_name, path: name }, false);
} else { } else {
uri = lbryuri.build({ name: name }, false); uri = lbryuri.build({ name }, false);
} }
++pendingId; ++pendingId;
const pendingPublishes = getLocal("pendingPublishes") || []; const pendingPublishes = getLocal("pendingPublishes") || [];
const newPendingPublish = { const newPendingPublish = {
name, name,
channel_name, channel_name,
claim_id: "pending-" + pendingId, claim_id: `pending-${pendingId}`,
txid: "pending-" + pendingId, txid: `pending-${pendingId}`,
nout: 0, nout: 0,
outpoint: "pending-" + pendingId + ":0", outpoint: `pending-${pendingId}:0`,
time: Date.now(), time: Date.now(),
}; };
setLocal("pendingPublishes", [...pendingPublishes, newPendingPublish]); setLocal("pendingPublishes", [...pendingPublishes, newPendingPublish]);
@ -119,7 +119,7 @@ function pendingPublishToDummyFileInfo({ name, outpoint, claim_id }) {
return { name, outpoint, claim_id, metadata: null }; return { name, outpoint, claim_id, metadata: null };
} }
//core // core
lbry._connectPromise = null; lbry._connectPromise = null;
lbry.connect = function() { lbry.connect = function() {
if (lbry._connectPromise === null) { if (lbry._connectPromise === null) {
@ -203,19 +203,19 @@ lbry.publishDeprecated = function(
}; };
lbry.imagePath = function(file) { lbry.imagePath = function(file) {
return staticResourcesPath + "/img/" + file; return `${staticResourcesPath}/img/${file}`;
}; };
lbry.getMediaType = function(contentType, fileName) { lbry.getMediaType = function(contentType, fileName) {
if (contentType) { if (contentType) {
return /^[^/]+/.exec(contentType)[0]; return /^[^/]+/.exec(contentType)[0];
} else if (fileName) { } else if (fileName) {
var dotIndex = fileName.lastIndexOf("."); const dotIndex = fileName.lastIndexOf(".");
if (dotIndex == -1) { if (dotIndex == -1) {
return "unknown"; return "unknown";
} }
var ext = fileName.substr(dotIndex + 1); const ext = fileName.substr(dotIndex + 1);
if (/^mp4|m4v|webm|flv|f4v|ogv$/i.test(ext)) { 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)) { } else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) {
@ -224,12 +224,10 @@ lbry.getMediaType = function(contentType, fileName) {
/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext) /^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext)
) { ) {
return "document"; return "document";
} else {
return "unknown";
} }
} else {
return "unknown"; return "unknown";
} }
return "unknown";
}; };
lbry.getAppVersionInfo = function() { lbry.getAppVersionInfo = function() {
@ -273,7 +271,7 @@ lbry.file_list = function(params = {}) {
fileInfos => { fileInfos => {
removePendingPublishIfNeeded({ name, channel_name, outpoint }); removePendingPublishIfNeeded({ name, channel_name, outpoint });
//if a naked file_list call, append the pending file infos // if a naked file_list call, append the pending file infos
if (!name && !channel_name && !outpoint) { if (!name && !channel_name && !outpoint) {
const dummyFileInfos = lbry const dummyFileInfos = lbry
.getPendingPublishes() .getPendingPublishes()
@ -295,11 +293,11 @@ lbry.claim_list_mine = function(params = {}) {
"claim_list_mine", "claim_list_mine",
params, params,
claims => { claims => {
for (let { name, channel_name, txid, nout } of claims) { for (const { name, channel_name, txid, nout } of claims) {
removePendingPublishIfNeeded({ removePendingPublishIfNeeded({
name, name,
channel_name, channel_name,
outpoint: txid + ":" + nout, outpoint: `${txid}:${nout}`,
}); });
} }
@ -318,7 +316,7 @@ lbry.resolve = function(params = {}) {
apiCall( apiCall(
"resolve", "resolve",
params, params,
function(data) { data => {
if ("uri" in params) { if ("uri" in params) {
// If only a single URI was requested, don't nest the results in an object // If only a single URI was requested, don't nest the results in an object
resolve(data && data[params.uri] ? data[params.uri] : {}); resolve(data && data[params.uri] ? data[params.uri] : {});
@ -332,7 +330,7 @@ lbry.resolve = function(params = {}) {
}; };
lbry = new Proxy(lbry, { lbry = new Proxy(lbry, {
get: function(target, name) { get(target, name) {
if (name in target) { if (name in target) {
return target[name]; return target[name];
} }

View file

@ -48,18 +48,17 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
function checkAndParse(response) { function checkAndParse(response) {
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
return response.json(); return response.json();
} else {
return response.json().then(json => {
let error;
if (json.error) {
error = new Error(json.error);
} else {
error = new Error("Unknown API error signature");
}
error.response = response; //this is primarily a hack used in actions/user.js
return Promise.reject(error);
});
} }
return response.json().then(json => {
let error;
if (json.error) {
error = new Error(json.error);
} else {
error = new Error("Unknown API error signature");
}
error.response = response; // this is primarily a hack used in actions/user.js
return Promise.reject(error);
});
} }
function makeRequest(url, options) { function makeRequest(url, options) {
@ -92,8 +91,8 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
lbryio._authToken = null; lbryio._authToken = null;
lbryio.getAuthToken = () => { lbryio.getAuthToken = () =>
return new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (lbryio._authToken) { if (lbryio._authToken) {
resolve(lbryio._authToken); resolve(lbryio._authToken);
} else { } else {
@ -104,16 +103,13 @@ lbryio.getAuthToken = () => {
ipcRenderer.send("get-auth-token"); ipcRenderer.send("get-auth-token");
} }
}); });
};
lbryio.setAuthToken = token => { lbryio.setAuthToken = token => {
lbryio._authToken = token ? token.toString().trim() : null; lbryio._authToken = token ? token.toString().trim() : null;
ipcRenderer.send("set-auth-token", token); ipcRenderer.send("set-auth-token", token);
}; };
lbryio.getCurrentUser = () => { lbryio.getCurrentUser = () => lbryio.call("user", "me");
return lbryio.call("user", "me");
};
lbryio.authenticate = function() { lbryio.authenticate = function() {
if (!lbryio.enabled) { if (!lbryio.enabled) {
@ -141,12 +137,8 @@ lbryio.authenticate = function() {
// check that token works // check that token works
return lbryio return lbryio
.getCurrentUser() .getCurrentUser()
.then(() => { .then(() => true)
return true; .catch(() => false);
})
.catch(() => {
return false;
});
}) })
.then(isTokenValid => { .then(isTokenValid => {
if (isTokenValid) { if (isTokenValid) {
@ -155,8 +147,8 @@ lbryio.authenticate = function() {
return lbry return lbry
.status() .status()
.then(status => { .then(status =>
return lbryio.call( lbryio.call(
"user", "user",
"new", "new",
{ {
@ -165,8 +157,8 @@ lbryio.authenticate = function() {
app_id: status.installation_id, app_id: status.installation_id,
}, },
"post" "post"
); )
}) )
.then(response => { .then(response => {
if (!response.auth_token) { if (!response.auth_token) {
throw new Error(__("auth_token is missing from response")); throw new Error(__("auth_token is missing from response"));
@ -182,10 +174,9 @@ lbryio.authenticate = function() {
return lbryio._authenticationPromise; return lbryio._authenticationPromise;
}; };
lbryio.getStripeToken = () => { lbryio.getStripeToken = () =>
return CONNECTION_STRING.startsWith("http://localhost:") CONNECTION_STRING.startsWith("http://localhost:")
? "pk_test_NoL1JWL7i1ipfhVId5KfDZgo" ? "pk_test_NoL1JWL7i1ipfhVId5KfDZgo"
: "pk_live_e8M4dRNnCCbmpZzduEUZBgJO"; : "pk_live_e8M4dRNnCCbmpZzduEUZBgJO";
};
export default lbryio; export default lbryio;

View file

@ -103,7 +103,7 @@ lbryuri.parse = function(uri, requireProto = false) {
if ( if (
claimId && claimId &&
(claimId.length > CLAIM_ID_MAX_LEN || !claimId.match(/^[0-9a-f]+$/)) && (claimId.length > CLAIM_ID_MAX_LEN || !claimId.match(/^[0-9a-f]+$/)) &&
!claimId.match(/^pending/) //ought to be dropped when savePendingPublish drops hack !claimId.match(/^pending/) // ought to be dropped when savePendingPublish drops hack
) { ) {
throw new Error(__(`Invalid claim ID %s.`, claimId)); throw new Error(__(`Invalid claim ID %s.`, claimId));
} }
@ -166,7 +166,7 @@ lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) {
if (channelName) { if (channelName) {
const channelNameFormatted = channelName.startsWith("@") const channelNameFormatted = channelName.startsWith("@")
? channelName ? channelName
: "@" + channelName; : `@${channelName}`;
if (!name) { if (!name) {
name = channelNameFormatted; name = channelNameFormatted;
} else if (name !== channelNameFormatted) { } else if (name !== channelNameFormatted) {

View file

@ -30,7 +30,7 @@ export class Modal extends React.PureComponent {
<ReactModal <ReactModal
onCloseRequested={this.props.onAborted || this.props.onConfirmed} onCloseRequested={this.props.onAborted || this.props.onConfirmed}
{...this.props} {...this.props}
className={(this.props.className || "") + " modal"} className={`${this.props.className || ""} modal`}
overlayClassName={ overlayClassName={
![null, undefined, ""].includes(this.props.overlayClassName) ![null, undefined, ""].includes(this.props.overlayClassName)
? this.props.overlayClassName ? this.props.overlayClassName

View file

@ -24,18 +24,16 @@ const select = (state, props) => {
}; };
}; };
const perform = dispatch => () => { const perform = dispatch => () => ({
return { addBalance: () => {
addBalance: () => { dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true));
dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true)); dispatch(doNavigate("/getcredits"));
dispatch(doNavigate("/getcredits")); dispatch(doCloseModal());
dispatch(doCloseModal()); },
}, closeModal: () => {
closeModal: () => { dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true));
dispatch(doSetClientSetting(settings.CREDIT_REQUIRED_ACKNOWLEDGED, true)); dispatch(doCloseModal());
dispatch(doCloseModal()); },
}, });
};
};
export default connect(select, perform)(ModalCreditIntro); export default connect(select, perform)(ModalCreditIntro);

View file

@ -71,10 +71,9 @@ class ReportPage extends React.Component {
onClick={event => { onClick={event => {
this.submitMessage(event); this.submitMessage(event);
}} }}
className={ className={`button-block button-primary ${
"button-block button-primary " + this.state.submitting ? "disabled" : ""
(this.state.submitting ? "disabled" : "") }`}
}
> >
{this.state.submitting {this.state.submitting
? __("Submitting...") ? __("Submitting...")

View file

@ -9,13 +9,11 @@ import { doAuthNavigate, doNavigate } from "redux/actions/navigation";
import { doRewardList } from "redux/actions/rewards"; import { doRewardList } from "redux/actions/rewards";
import RewardsPage from "./view"; import RewardsPage from "./view";
const select = (state, props) => { const select = (state, props) => ({
return { fetching: selectFetchingRewards(state),
fetching: selectFetchingRewards(state), rewards: selectUnclaimedRewards(state),
rewards: selectUnclaimedRewards(state), user: selectUser(state),
user: selectUser(state), });
};
};
const perform = dispatch => ({ const perform = dispatch => ({
fetchRewards: () => dispatch(doRewardList()), fetchRewards: () => dispatch(doRewardList()),

View file

@ -18,9 +18,11 @@ import { selectCurrentModal } from "redux/selectors/app";
const { remote, ipcRenderer, shell } = require("electron"); const { remote, ipcRenderer, shell } = require("electron");
const path = require("path"); const path = require("path");
const { download } = remote.require("electron-dl"); const { download } = remote.require("electron-dl");
const fs = remote.require("fs"); const fs = remote.require("fs");
const { lbrySettings: config } = require("package.json"); const { lbrySettings: config } = require("package.json");
const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000; const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000;
export function doOpenModal(modal, modalProps = {}) { export function doOpenModal(modal, modalProps = {}) {
@ -43,7 +45,7 @@ export function doUpdateDownloadProgress(percent) {
return { return {
type: types.UPGRADE_DOWNLOAD_PROGRESSED, type: types.UPGRADE_DOWNLOAD_PROGRESSED,
data: { data: {
percent: percent, percent,
}, },
}; };
} }
@ -72,7 +74,7 @@ export function doDownloadUpgrade() {
), ),
upgradeFilename = selectUpgradeFilename(state); upgradeFilename = selectUpgradeFilename(state);
let options = { const options = {
onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))), onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))),
directory: dir, directory: dir,
}; };

View file

@ -42,9 +42,9 @@ export function doResolveUris(uris) {
data: { uris }, data: { uris },
}); });
let resolveInfo = {}; const resolveInfo = {};
lbry.resolve({ uris: urisToResolve }).then(result => { lbry.resolve({ uris: urisToResolve }).then(result => {
for (let [uri, uriResolveInfo] of Object.entries(result)) { for (const [uri, uriResolveInfo] of Object.entries(result)) {
const fallbackResolveInfo = { const fallbackResolveInfo = {
claim: null, claim: null,
claims_in_channel: null, claims_in_channel: null,
@ -80,7 +80,7 @@ export function doFetchFeaturedUris() {
const success = ({ Uris }) => { const success = ({ Uris }) => {
let urisToResolve = []; let urisToResolve = [];
for (let category in Uris) { for (const category in Uris) {
urisToResolve = [...urisToResolve, ...Uris[category]]; urisToResolve = [...urisToResolve, ...Uris[category]];
} }
@ -144,7 +144,7 @@ export function doUpdateLoadStatus(uri, outpoint) {
lbry lbry
.file_list({ .file_list({
outpoint: outpoint, outpoint,
full_status: true, full_status: true,
}) })
.then(([fileInfo]) => { .then(([fileInfo]) => {
@ -239,7 +239,7 @@ export function doDownloadFile(uri, streamInfo) {
lbryio lbryio
.call("file", "view", { .call("file", "view", {
uri: uri, uri,
outpoint: streamInfo.outpoint, outpoint: streamInfo.outpoint,
claim_id: streamInfo.claim_id, claim_id: streamInfo.claim_id,
}) })
@ -288,7 +288,9 @@ export function doLoadVideo(uri) {
}); });
dispatch( dispatch(
doAlertError( doAlertError(
`Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.` `Failed to download ${
uri
}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.`
) )
); );
}); });
@ -511,7 +513,7 @@ export function doAbandonClaim(txid, nout) {
dispatch({ dispatch({
type: types.ABANDON_CLAIM_STARTED, type: types.ABANDON_CLAIM_STARTED,
data: { data: {
claimId: claimId, claimId,
}, },
}); });
@ -524,7 +526,7 @@ export function doAbandonClaim(txid, nout) {
dispatch({ dispatch({
type: types.ABANDON_CLAIM_SUCCEEDED, type: types.ABANDON_CLAIM_SUCCEEDED,
data: { data: {
claimId: claimId, claimId,
}, },
}); });
dispatch(doResolveUri(lbryuri.build({ name, claimId }))); dispatch(doResolveUri(lbryuri.build({ name, claimId })));
@ -536,8 +538,8 @@ export function doAbandonClaim(txid, nout) {
lbry lbry
.claim_abandon({ .claim_abandon({
txid: txid, txid,
nout: nout, nout,
}) })
.then(successCallback, errorCallback); .then(successCallback, errorCallback);
}; };

View file

@ -34,17 +34,15 @@ export function doFetchFileInfo(uri) {
}, },
}); });
lbry lbry.file_list({ outpoint, full_status: true }).then(fileInfos => {
.file_list({ outpoint: outpoint, full_status: true }) dispatch({
.then(fileInfos => { type: types.FETCH_FILE_INFO_COMPLETED,
dispatch({ data: {
type: types.FETCH_FILE_INFO_COMPLETED, outpoint,
data: { fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null,
outpoint, },
fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null,
},
});
}); });
});
} }
}; };
} }
@ -91,7 +89,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
const state = getState(); const state = getState();
lbry.file_delete({ lbry.file_delete({
outpoint: outpoint, outpoint,
delete_from_download_dir: deleteFromComputer, delete_from_download_dir: deleteFromComputer,
}); });

View file

@ -19,7 +19,7 @@ export function doNavigate(path, params = {}, options = {}) {
let url = path; let url = path;
if (params && Object.values(params).length) { if (params && Object.values(params).length) {
url += "?" + toQueryString(params); url += `?${toQueryString(params)}`;
} }
const scrollY = options.scrollY; const scrollY = options.scrollY;

View file

@ -39,7 +39,7 @@ export function doClaimRewardType(rewardType) {
userIsRewardApproved = selectUserIsRewardApproved(state); userIsRewardApproved = selectUserIsRewardApproved(state);
if (!reward || reward.transaction_id) { if (!reward || reward.transaction_id) {
//already claimed or doesn't exist, do nothing // already claimed or doesn't exist, do nothing
return; return;
} }

View file

@ -24,17 +24,18 @@ export function doSearch(rawQuery) {
}); });
if (page != "search") { if (page != "search") {
dispatch(doNavigate("search", { query: query })); dispatch(doNavigate("search", { query }));
} else { } else {
fetch("https://lighthouse.lbry.io/search?s=" + query) fetch(`https://lighthouse.lbry.io/search?s=${query}`)
.then(response => { .then(
return response.status === 200 response =>
? Promise.resolve(response.json()) response.status === 200
: Promise.reject(new Error(response.statusText)); ? Promise.resolve(response.json())
}) : Promise.reject(new Error(response.statusText))
)
.then(data => { .then(data => {
let uris = []; const uris = [];
let actions = []; const actions = [];
data.forEach(result => { data.forEach(result => {
const uri = lbryuri.build({ const uri = lbryuri.build({

View file

@ -22,7 +22,7 @@ export function doFetchDaemonSettings() {
export function doSetDaemonSetting(key, value) { export function doSetDaemonSetting(key, value) {
return function(dispatch, getState) { return function(dispatch, getState) {
let settings = {}; const settings = {};
settings[key] = value; settings[key] = value;
lbry.settings_set(settings).then(settings); lbry.settings_set(settings).then(settings);
lbry.settings_get().then(settings => { lbry.settings_get().then(settings => {
@ -49,19 +49,13 @@ export function doSetClientSetting(key, value) {
export function doGetThemes() { export function doGetThemes() {
return function(dispatch, getState) { return function(dispatch, getState) {
const themes = ["light", "dark"]; const themes = ["light", "dark"];
dispatch( dispatch(doSetClientSetting(settings.THEMES, themes));
doSetClientSetting(
settings.THEMES,
themes
)
);
}; };
} }
export function doDownloadLanguage(langFile) { export function doDownloadLanguage(langFile) {
return function(dispatch, getState) { return function(dispatch, getState) {
const destinationPath = app.i18n.directory + "/" + langFile; const destinationPath = `${app.i18n.directory}/${langFile}`;
const language = langFile.replace(".json", ""); const language = langFile.replace(".json", "");
const req = http.get( const req = http.get(
{ {
@ -82,7 +76,7 @@ export function doDownloadLanguage(langFile) {
// push to our local list // push to our local list
dispatch({ dispatch({
type: types.DOWNLOAD_LANGUAGE_SUCCEEDED, type: types.DOWNLOAD_LANGUAGE_SUCCEEDED,
data: { language: language }, data: { language },
}); });
}); });
@ -102,7 +96,7 @@ export function doDownloadLanguage(langFile) {
}); });
}; };
req.setTimeout(30000, function() { req.setTimeout(30000, () => {
req.abort(); req.abort();
}); });
@ -114,7 +108,7 @@ export function doDownloadLanguage(langFile) {
export function doDownloadLanguages() { export function doDownloadLanguages() {
return function(dispatch, getState) { return function(dispatch, getState) {
//temporarily disable i18n so I can get a working build out -- Jeremy // temporarily disable i18n so I can get a working build out -- Jeremy
return; return;
if (!fs.existsSync(app.i18n.directory)) { if (!fs.existsSync(app.i18n.directory)) {
@ -124,11 +118,10 @@ export function doDownloadLanguages() {
function checkStatus(response) { function checkStatus(response) {
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
return response; return response;
} else {
throw new Error(
__("The list of available languages could not be retrieved.")
);
} }
throw new Error(
__("The list of available languages could not be retrieved.")
);
} }
function parseJSON(response) { function parseJSON(response) {

View file

@ -106,7 +106,7 @@ export const createShapeShift = (
const pair = `${originCoin.toLowerCase()}_lbc`; const pair = `${originCoin.toLowerCase()}_lbc`;
const options = { const options = {
returnAddress: returnAddress, returnAddress,
}; };
dispatch({ type: types.PREPARE_SHAPE_SHIFT_START }); dispatch({ type: types.PREPARE_SHAPE_SHIFT_START });

View file

@ -1,26 +1,27 @@
// @flow // @flow
import * as actions from "constants/action_types"; import * as actions from "constants/action_types";
import type { Subscription, Action, Dispatch } from "redux/reducers/subscriptions"; import type {
Subscription,
Action,
Dispatch,
} from "redux/reducers/subscriptions";
import lbry from "lbry"; import lbry from "lbry";
export const doChannelSubscribe = (subscription: Subscription) => ( export const doChannelSubscribe = (subscription: Subscription) => (
dispatch: Dispatch dispatch: Dispatch
) => { ) =>
return dispatch({ dispatch({
type: actions.CHANNEL_SUBSCRIBE, type: actions.CHANNEL_SUBSCRIBE,
data: subscription, data: subscription,
}); });
};
export const doChannelUnsubscribe = (subscription: Subscription) => ( export const doChannelUnsubscribe = (subscription: Subscription) => (
dispatch: Dispatch dispatch: Dispatch
) => { ) =>
return dispatch({ dispatch({
type: actions.CHANNEL_UNSUBSCRIBE, type: actions.CHANNEL_UNSUBSCRIBE,
data: subscription, data: subscription,
}); });
};
export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) => { export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) =>
return dispatch({ type: actions.HAS_FETCHED_SUBSCRIPTIONS }) dispatch({ type: actions.HAS_FETCHED_SUBSCRIPTIONS });
}

View file

@ -59,7 +59,7 @@ export function doUserEmailNew(email) {
return function(dispatch, getState) { return function(dispatch, getState) {
dispatch({ dispatch({
type: types.USER_EMAIL_NEW_STARTED, type: types.USER_EMAIL_NEW_STARTED,
email: email, email,
}); });
const success = () => { const success = () => {
@ -68,30 +68,32 @@ export function doUserEmailNew(email) {
data: { email }, data: { email },
}); });
dispatch(doUserFetch()); dispatch(doUserFetch());
} };
const failure = error => { const failure = error => {
dispatch({ dispatch({
type: types.USER_EMAIL_NEW_FAILURE, type: types.USER_EMAIL_NEW_FAILURE,
data: { error }, data: { error },
}); });
} };
lbryio lbryio
.call( .call(
"user_email", "user_email",
"new", "new",
{ email: email, send_verification_email: true }, { email, send_verification_email: true },
"post" "post"
) )
.catch(error => { .catch(error => {
if (error.response && error.response.status == 409) { if (error.response && error.response.status == 409) {
return lbryio.call( return lbryio
"user_email", .call(
"resend_token", "user_email",
{ email: email, only_if_expired: true }, "resend_token",
"post" { email, only_if_expired: true },
).then(success, failure); "post"
)
.then(success, failure);
} }
throw error; throw error;
}) })
@ -113,7 +115,7 @@ export function doUserEmailVerify(verificationToken) {
.call( .call(
"user_email", "user_email",
"confirm", "confirm",
{ verification_token: verificationToken, email: email }, { verification_token: verificationToken, email },
"post" "post"
) )
.then(userEmail => { .then(userEmail => {
@ -125,7 +127,7 @@ export function doUserEmailVerify(verificationToken) {
dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL)), dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL)),
dispatch(doUserFetch()); dispatch(doUserFetch());
} else { } 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 => { .catch(error => {
@ -156,7 +158,7 @@ export function doUserIdentityVerify(stripeToken) {
} else { } else {
throw new Error( throw new Error(
"Your identity is still not verified. This should not happen." "Your identity is still not verified. This should not happen."
); //shouldn't happen ); // shouldn't happen
} }
}) })
.catch(error => { .catch(error => {
@ -214,7 +216,7 @@ export function doUserInviteNew(email) {
}); });
lbryio lbryio
.call("user", "invite", { email: email }, "post") .call("user", "invite", { email }, "post")
.then(invite => { .then(invite => {
dispatch({ dispatch({
type: types.USER_INVITE_NEW_SUCCESS, type: types.USER_INVITE_NEW_SUCCESS,

View file

@ -11,14 +11,14 @@ import * as modals from "constants/modal_types";
export function doUpdateBalance() { export function doUpdateBalance() {
return function(dispatch, getState) { return function(dispatch, getState) {
lbry.wallet_balance().then(balance => { lbry.wallet_balance().then(balance =>
return dispatch({ dispatch({
type: types.UPDATE_BALANCE, type: types.UPDATE_BALANCE,
data: { data: {
balance: balance, balance,
}, },
}); })
}); );
}; };
} }
@ -35,14 +35,16 @@ export function doFetchTransactions(fetch_tip_info = true) {
type: types.FETCH_TRANSACTIONS_STARTED, type: types.FETCH_TRANSACTIONS_STARTED,
}); });
lbry.transaction_list({ include_tip_info: fetch_tip_info }).then(results => { lbry
dispatch({ .transaction_list({ include_tip_info: fetch_tip_info })
type: types.FETCH_TRANSACTIONS_COMPLETED, .then(results => {
data: { dispatch({
transactions: results, type: types.FETCH_TRANSACTIONS_COMPLETED,
}, data: {
transactions: results,
},
});
}); });
});
}; };
} }
@ -63,7 +65,7 @@ export function doGetNewAddress() {
type: types.GET_NEW_ADDRESS_STARTED, type: types.GET_NEW_ADDRESS_STARTED,
}); });
lbry.wallet_new_address().then(function(address) { lbry.wallet_new_address().then(address => {
localStorage.setItem("wallet_address", address); localStorage.setItem("wallet_address", address);
dispatch({ dispatch({
type: types.GET_NEW_ADDRESS_COMPLETED, type: types.GET_NEW_ADDRESS_COMPLETED,
@ -201,8 +203,8 @@ export function doSendSupport(amount, claim_id, uri) {
lbry lbry
.wallet_send({ .wallet_send({
claim_id: claim_id, claim_id,
amount: amount, amount,
}) })
.then(successCallback, errorCallback); .then(successCallback, errorCallback);
}; };

View file

@ -9,7 +9,7 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
for (let [uri, { certificate, claim }] of Object.entries(resolveInfo)) { for (const [uri, { certificate, claim }] of Object.entries(resolveInfo)) {
if (claim) { if (claim) {
byId[claim.claim_id] = claim; byId[claim.claim_id] = claim;
byUri[uri] = claim.claim_id; byUri[uri] = claim.claim_id;
@ -51,12 +51,11 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
.forEach(claim => { .forEach(claim => {
byId[claim.claim_id] = claim; byId[claim.claim_id] = claim;
const pending = Object.values(pendingById).find(pendingClaim => { const pending = Object.values(pendingById).find(
return ( pendingClaim =>
pendingClaim.name == claim.name && pendingClaim.name == claim.name &&
pendingClaim.channel_name == claim.channel_name pendingClaim.channel_name == claim.channel_name
); );
});
if (pending) { if (pending) {
delete pendingById[pending.claim_id]; delete pendingById[pending.claim_id];
@ -115,7 +114,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
const claimsByChannel = Object.assign({}, state.claimsByChannel); const claimsByChannel = Object.assign({}, state.claimsByChannel);
const byChannel = Object.assign({}, claimsByChannel[uri]); const byChannel = Object.assign({}, claimsByChannel[uri]);
const allClaimIds = new Set(byChannel["all"]); const allClaimIds = new Set(byChannel.all);
const currentPageClaimIds = []; const currentPageClaimIds = [];
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims); const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
@ -128,7 +127,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
}); });
} }
byChannel["all"] = allClaimIds; byChannel.all = allClaimIds;
byChannel[page] = currentPageClaimIds; byChannel[page] = currentPageClaimIds;
claimsByChannel[uri] = byChannel; claimsByChannel[uri] = byChannel;
delete fetchingChannelClaims[uri]; delete fetchingChannelClaims[uri];

View file

@ -32,12 +32,12 @@ reducers[types.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) {
}; };
reducers[types.RESOLVE_URIS_STARTED] = function(state, action) { reducers[types.RESOLVE_URIS_STARTED] = function(state, action) {
let { uris } = action.data; const { uris } = action.data;
const oldResolving = state.resolvingUris || []; const oldResolving = state.resolvingUris || [];
const newResolving = Object.assign([], oldResolving); const newResolving = Object.assign([], oldResolving);
for (let uri of uris) { for (const uri of uris) {
if (!newResolving.includes(uri)) { if (!newResolving.includes(uri)) {
newResolving.push(uri); newResolving.push(uri);
} }
@ -52,7 +52,7 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
const { resolveInfo } = action.data; const { resolveInfo } = action.data;
const channelClaimCounts = Object.assign({}, state.channelClaimCounts); const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
for (let [uri, { certificate, claims_in_channel }] of Object.entries( for (const [uri, { certificate, claims_in_channel }] of Object.entries(
resolveInfo resolveInfo
)) { )) {
if (certificate && !isNaN(claims_in_channel)) { if (certificate && !isNaN(claims_in_channel)) {
@ -66,11 +66,10 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
}); });
}; };
reducers[types.SET_PLAYING_URI] = (state, action) => { reducers[types.SET_PLAYING_URI] = (state, action) =>
return Object.assign({}, state, { Object.assign({}, state, {
playingUri: action.data.uri, playingUri: action.data.uri,
}); });
};
reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) { reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
const channelClaimCounts = Object.assign({}, state.channelClaimCounts); const channelClaimCounts = Object.assign({}, state.channelClaimCounts);

View file

@ -4,7 +4,7 @@ import { parseQueryParams } from "util/query_params";
const currentPath = () => { const currentPath = () => {
const hash = document.location.hash; const hash = document.location.hash;
if (hash !== "") return hash.replace(/^#/, ""); if (hash !== "") return hash.replace(/^#/, "");
else return "/discover"; return "/discover";
}; };
const reducers = {}; const reducers = {};
@ -34,7 +34,7 @@ reducers[types.HISTORY_NAVIGATE] = (state, action) => {
const { stack, index } = state; const { stack, index } = state;
const { url: path, index: newIndex, scrollY } = action.data; const { url: path, index: newIndex, scrollY } = action.data;
let newState = { const newState = {
currentPath: path, currentPath: path,
}; };
@ -46,7 +46,7 @@ reducers[types.HISTORY_NAVIGATE] = (state, action) => {
newState.index = newState.stack.length - 1; newState.index = newState.stack.length - 1;
} }
history.replaceState(null, null, "#" + path); //this allows currentPath() to retain the URL on reload history.replaceState(null, null, `#${path}`); // this allows currentPath() to retain the URL on reload
return Object.assign({}, state, newState); return Object.assign({}, state, newState);
}; };
@ -61,7 +61,7 @@ reducers[types.WINDOW_SCROLLED] = (state, action) => {
} }
return { return {
...stackItem, ...stackItem,
scrollY: scrollY, scrollY,
}; };
}), }),
}); });

View file

@ -3,7 +3,7 @@ import * as types from "constants/action_types";
const reducers = {}; const reducers = {};
const defaultState = { const defaultState = {
fetching: false, fetching: false,
claimedRewardsById: {}, //id => reward claimedRewardsById: {}, // id => reward
unclaimedRewardsByType: {}, unclaimedRewardsByType: {},
claimPendingByType: {}, claimPendingByType: {},
claimErrorsByType: {}, claimErrorsByType: {},
@ -64,7 +64,10 @@ reducers[types.CLAIM_REWARD_STARTED] = function(state, action) {
reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) { reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) {
const { reward } = action.data; const { reward } = action.data;
let unclaimedRewardsByType = Object.assign({}, state.unclaimedRewardsByType); const unclaimedRewardsByType = Object.assign(
{},
state.unclaimedRewardsByType
);
const existingReward = unclaimedRewardsByType[reward.reward_type]; const existingReward = unclaimedRewardsByType[reward.reward_type];
delete state.unclaimedRewardsByType[reward.reward_type]; delete state.unclaimedRewardsByType[reward.reward_type];
@ -73,7 +76,7 @@ reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) {
reward_description: existingReward.reward_description, reward_description: existingReward.reward_description,
}); });
let claimedRewardsById = Object.assign({}, state.claimedRewardsById); const claimedRewardsById = Object.assign({}, state.claimedRewardsById);
claimedRewardsById[reward.id] = newReward; claimedRewardsById[reward.id] = newReward;
const newState = Object.assign({}, state, { const newState = Object.assign({}, state, {

View file

@ -3,7 +3,7 @@ import * as settings from "constants/settings";
import LANGUAGES from "constants/languages"; import LANGUAGES from "constants/languages";
function getLocalStorageSetting(setting, fallback) { function getLocalStorageSetting(setting, fallback) {
var localStorageVal = localStorage.getItem("setting_" + setting); const localStorageVal = localStorage.getItem(`setting_${setting}`);
return localStorageVal === null ? fallback : JSON.parse(localStorageVal); return localStorageVal === null ? fallback : JSON.parse(localStorageVal);
} }
@ -27,7 +27,7 @@ const defaultState = {
email_collection_acknowledged: getLocalStorageSetting( email_collection_acknowledged: getLocalStorageSetting(
settings.EMAIL_COLLECTION_ACKNOWLEDGED settings.EMAIL_COLLECTION_ACKNOWLEDGED
), ),
credit_required_acknowledged: false, //this needs to be re-acknowledged every run credit_required_acknowledged: false, // this needs to be re-acknowledged every run
language: getLocalStorageSetting(settings.LANGUAGE, "en"), language: getLocalStorageSetting(settings.LANGUAGE, "en"),
theme: getLocalStorageSetting(settings.THEME, "light"), theme: getLocalStorageSetting(settings.THEME, "light"),
themes: getLocalStorageSetting(settings.THEMES, []), themes: getLocalStorageSetting(settings.THEMES, []),
@ -47,8 +47,8 @@ reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) {
clientSettings[key] = value; clientSettings[key] = value;
//this technically probably shouldn't happen here, and should be fixed when we're no longer using localStorage at all for persistent app state // this technically probably shouldn't happen here, and should be fixed when we're no longer using localStorage at all for persistent app state
localStorage.setItem("setting_" + key, JSON.stringify(value)); localStorage.setItem(`setting_${key}`, JSON.stringify(value));
return Object.assign({}, state, { return Object.assign({}, state, {
clientSettings, clientSettings,
@ -62,8 +62,9 @@ reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
const langCode = language.substring(0, 2); const langCode = language.substring(0, 2);
if (LANGUAGES[langCode]) { if (LANGUAGES[langCode]) {
languages[language] = languages[language] = `${LANGUAGES[langCode][0]} (${
LANGUAGES[langCode][0] + " (" + LANGUAGES[langCode][1] + ")"; LANGUAGES[langCode][1]
})`;
} else { } else {
languages[langCode] = langCode; languages[langCode] = langCode;
} }

View file

@ -5,7 +5,7 @@ import { handleActions } from "util/redux-utils";
// Subscription redux types // Subscription redux types
export type SubscriptionState = { export type SubscriptionState = {
subscriptions: Array<Subscription>, subscriptions: Array<Subscription>,
hasFetchedSubscriptions: boolean hasFetchedSubscriptions: boolean,
}; };
export type Subscription = { export type Subscription = {
@ -25,15 +25,18 @@ type doChannelUnsubscribe = {
}; };
type HasFetchedSubscriptions = { 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; export type Dispatch = (action: Action) => any;
const defaultState = { const defaultState = {
subscriptions: [], subscriptions: [],
hasFetchedSubscriptions: false hasFetchedSubscriptions: false,
}; };
export default handleActions( export default handleActions(
@ -43,7 +46,7 @@ export default handleActions(
action: doChannelSubscribe action: doChannelSubscribe
): SubscriptionState => { ): SubscriptionState => {
const newSubscription: Subscription = action.data; const newSubscription: Subscription = action.data;
let newSubscriptions: Array<Subscription> = state.subscriptions.slice(); const newSubscriptions: Array<Subscription> = state.subscriptions.slice();
newSubscriptions.unshift(newSubscription); newSubscriptions.unshift(newSubscription);
return { return {
@ -59,9 +62,10 @@ export default handleActions(
const newSubscriptions = state.subscriptions const newSubscriptions = state.subscriptions
.slice() .slice()
.filter(subscription => { .filter(
return subscription.channelName !== subscriptionToRemove.channelName; subscription =>
}); subscription.channelName !== subscriptionToRemove.channelName
);
return { return {
...state, ...state,
@ -73,8 +77,8 @@ export default handleActions(
action: HasFetchedSubscriptions action: HasFetchedSubscriptions
): SubscriptionState => ({ ): SubscriptionState => ({
...state, ...state,
hasFetchedSubscriptions: true hasFetchedSubscriptions: true,
}) }),
}, },
defaultState defaultState
); );

View file

@ -69,17 +69,17 @@ reducers[types.USER_EMAIL_NEW_STARTED] = function(state, action) {
}; };
reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) { reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
let user = Object.assign({}, state.user); const user = Object.assign({}, state.user);
user.primary_email = action.data.email; user.primary_email = action.data.email;
return Object.assign({}, state, { return Object.assign({}, state, {
emailToVerify: action.data.email, emailToVerify: action.data.email,
emailNewIsPending: false, emailNewIsPending: false,
user: user, user,
}); });
}; };
reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) { reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) {
let user = Object.assign({}, state.user); const user = Object.assign({}, state.user);
return Object.assign({}, state, { return Object.assign({}, state, {
emailToVerify: action.data.email, emailToVerify: action.data.email,
emailNewIsPending: false, emailNewIsPending: false,
@ -101,12 +101,12 @@ reducers[types.USER_EMAIL_VERIFY_STARTED] = function(state, action) {
}; };
reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) {
let user = Object.assign({}, state.user); const user = Object.assign({}, state.user);
user.primary_email = action.data.email; user.primary_email = action.data.email;
return Object.assign({}, state, { return Object.assign({}, state, {
emailToVerify: "", emailToVerify: "",
emailVerifyIsPending: false, emailVerifyIsPending: false,
user: user, user,
}); });
}; };

View file

@ -25,7 +25,7 @@ reducers[types.FETCH_TRANSACTIONS_STARTED] = function(state, action) {
}; };
reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
let byId = Object.assign({}, state.transactions); const byId = Object.assign({}, state.transactions);
const { transactions } = action.data; const { transactions } = action.data;

View file

@ -7,21 +7,16 @@ export const selectAvailabilityByUri = createSelector(
state => state.byUri || {} state => state.byUri || {}
); );
export const makeSelectIsAvailableForUri = uri => { export const makeSelectIsAvailableForUri = uri =>
return createSelector( createSelector(
selectAvailabilityByUri, selectAvailabilityByUri,
byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0) byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0)
); );
};
export const selectFetchingAvailability = createSelector( export const selectFetchingAvailability = createSelector(
_selectState, _selectState,
state => state.fetching || {} state => state.fetching || {}
); );
export const makeSelectFetchingAvailabilityForUri = uri => { export const makeSelectFetchingAvailabilityForUri = uri =>
return createSelector( createSelector(selectFetchingAvailability, byUri => byUri && byUri[uri]);
selectFetchingAvailability,
byUri => byUri && byUri[uri]
);
};

View file

@ -40,12 +40,11 @@ export const selectAllClaimsByChannel = createSelector(
state => state.claimsByChannel || {} state => state.claimsByChannel || {}
); );
export const makeSelectClaimForUri = uri => { export const makeSelectClaimForUri = uri =>
return createSelector( createSelector(
selectClaimsByUri, selectClaimsByUri,
claims => claims && claims[lbryuri.normalize(uri)] claims => claims && claims[lbryuri.normalize(uri)]
); );
};
export const makeSelectClaimIsMine = rawUri => { export const makeSelectClaimIsMine = rawUri => {
const uri = lbryuri.normalize(rawUri); const uri = lbryuri.normalize(rawUri);
@ -65,12 +64,11 @@ export const selectAllFetchingChannelClaims = createSelector(
state => state.fetchingChannelClaims || {} state => state.fetchingChannelClaims || {}
); );
export const makeSelectFetchingChannelClaims = uri => { export const makeSelectFetchingChannelClaims = uri =>
return createSelector( createSelector(
selectAllFetchingChannelClaims, selectAllFetchingChannelClaims,
fetching => fetching && fetching[uri] fetching => fetching && fetching[uri]
); );
};
export const makeSelectClaimsInChannelForCurrentPage = uri => { export const makeSelectClaimsInChannelForCurrentPage = uri => {
const pageSelector = makeSelectCurrentParam("page"); const pageSelector = makeSelectCurrentParam("page");
@ -90,30 +88,27 @@ export const makeSelectClaimsInChannelForCurrentPage = uri => {
); );
}; };
export const makeSelectMetadataForUri = uri => { export const makeSelectMetadataForUri = uri =>
return createSelector(makeSelectClaimForUri(uri), claim => { createSelector(makeSelectClaimForUri(uri), claim => {
const metadata = const metadata =
claim && claim.value && claim.value.stream && claim.value.stream.metadata; claim && claim.value && claim.value.stream && claim.value.stream.metadata;
const value = metadata ? metadata : claim === undefined ? undefined : null; const value = metadata || (claim === undefined ? undefined : null);
return value; return value;
}); });
};
export const makeSelectTitleForUri = uri => { export const makeSelectTitleForUri = uri =>
return createSelector( createSelector(
makeSelectMetadataForUri(uri), makeSelectMetadataForUri(uri),
metadata => metadata && metadata.title metadata => metadata && metadata.title
); );
};
export const makeSelectContentTypeForUri = uri => { export const makeSelectContentTypeForUri = uri =>
return createSelector(makeSelectClaimForUri(uri), claim => { createSelector(makeSelectClaimForUri(uri), claim => {
const source = const source =
claim && claim.value && claim.value.stream && claim.value.stream.source; claim && claim.value && claim.value.stream && claim.value.stream.source;
return source ? source.contentType : undefined; return source ? source.contentType : undefined;
}); });
};
export const selectIsFetchingClaimListMine = createSelector( export const selectIsFetchingClaimListMine = createSelector(
_selectState, _selectState,
@ -203,7 +198,7 @@ export const selectMyChannelClaims = createSelector(
ids.forEach(id => { ids.forEach(id => {
if (byId[id]) { if (byId[id]) {
//I'm not sure why this check is necessary, but it ought to be a quick fix for https://github.com/lbryio/lbry-app/issues/544 // I'm not sure why this check is necessary, but it ought to be a quick fix for https://github.com/lbryio/lbry-app/issues/544
claims.push(byId[id]); claims.push(byId[id]);
} }
}); });

View file

@ -22,28 +22,25 @@ export const selectPlayingUri = createSelector(
state => state.playingUri state => state.playingUri
); );
export const makeSelectIsUriResolving = uri => { export const makeSelectIsUriResolving = uri =>
return createSelector( createSelector(
selectResolvingUris, selectResolvingUris,
resolvingUris => resolvingUris && resolvingUris.indexOf(uri) != -1 resolvingUris => resolvingUris && resolvingUris.indexOf(uri) != -1
); );
};
export const selectChannelClaimCounts = createSelector( export const selectChannelClaimCounts = createSelector(
_selectState, _selectState,
state => state.channelClaimCounts || {} state => state.channelClaimCounts || {}
); );
export const makeSelectTotalItemsForChannel = uri => { export const makeSelectTotalItemsForChannel = uri =>
return createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri]); createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri]);
};
export const makeSelectTotalPagesForChannel = uri => { export const makeSelectTotalPagesForChannel = uri =>
return createSelector( createSelector(
selectChannelClaimCounts, selectChannelClaimCounts,
byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / 10) byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / 10)
); );
};
export const selectRewardContentClaimIds = createSelector( export const selectRewardContentClaimIds = createSelector(
_selectState, _selectState,

View file

@ -8,12 +8,11 @@ export const selectAllCostInfoByUri = createSelector(
state => state.byUri || {} state => state.byUri || {}
); );
export const makeSelectCostInfoForUri = uri => { export const makeSelectCostInfoForUri = uri =>
return createSelector( createSelector(
selectAllCostInfoByUri, selectAllCostInfoByUri,
costInfos => costInfos && costInfos[uri] costInfos => costInfos && costInfos[uri]
); );
};
export const selectCostForCurrentPageUri = createSelector( export const selectCostForCurrentPageUri = createSelector(
selectAllCostInfoByUri, selectAllCostInfoByUri,
@ -27,9 +26,8 @@ export const selectFetchingCostInfo = createSelector(
state => state.fetching || {} state => state.fetching || {}
); );
export const makeSelectFetchingCostInfoForUri = uri => { export const makeSelectFetchingCostInfoForUri = uri =>
return createSelector( createSelector(
selectFetchingCostInfo, selectFetchingCostInfo,
fetchingByUri => fetchingByUri && fetchingByUri[uri] fetchingByUri => fetchingByUri && fetchingByUri[uri]
); );
};

View file

@ -26,8 +26,8 @@ export const selectIsFetchingFileListDownloadedOrPublished = createSelector(
isFetchingFileList || isFetchingClaimListMine isFetchingFileList || isFetchingClaimListMine
); );
export const makeSelectFileInfoForUri = uri => { export const makeSelectFileInfoForUri = uri =>
return createSelector( createSelector(
selectClaimsByUri, selectClaimsByUri,
selectFileInfosByOutpoint, selectFileInfosByOutpoint,
(claims, byOutpoint) => { (claims, byOutpoint) => {
@ -37,15 +37,14 @@ export const makeSelectFileInfoForUri = uri => {
return outpoint ? byOutpoint[outpoint] : undefined; return outpoint ? byOutpoint[outpoint] : undefined;
} }
); );
};
export const selectDownloadingByOutpoint = createSelector( export const selectDownloadingByOutpoint = createSelector(
_selectState, _selectState,
state => state.downloadingByOutpoint || {} state => state.downloadingByOutpoint || {}
); );
export const makeSelectDownloadingForUri = uri => { export const makeSelectDownloadingForUri = uri =>
return createSelector( createSelector(
selectDownloadingByOutpoint, selectDownloadingByOutpoint,
makeSelectFileInfoForUri(uri), makeSelectFileInfoForUri(uri),
(byOutpoint, fileInfo) => { (byOutpoint, fileInfo) => {
@ -53,16 +52,14 @@ export const makeSelectDownloadingForUri = uri => {
return byOutpoint[fileInfo.outpoint]; return byOutpoint[fileInfo.outpoint];
} }
); );
};
export const selectUrisLoading = createSelector( export const selectUrisLoading = createSelector(
_selectState, _selectState,
state => state.urisLoading || {} state => state.urisLoading || {}
); );
export const makeSelectLoadingForUri = uri => { export const makeSelectLoadingForUri = uri =>
return createSelector(selectUrisLoading, byUri => byUri && byUri[uri]); createSelector(selectUrisLoading, byUri => byUri && byUri[uri]);
};
export const selectFileInfosPendingPublish = createSelector( export const selectFileInfosPendingPublish = createSelector(
_selectState, _selectState,
@ -72,8 +69,8 @@ export const selectFileInfosPendingPublish = createSelector(
export const selectFileInfosDownloaded = createSelector( export const selectFileInfosDownloaded = createSelector(
selectFileInfosByOutpoint, selectFileInfosByOutpoint,
selectMyClaims, selectMyClaims,
(byOutpoint, myClaims) => { (byOutpoint, myClaims) =>
return Object.values(byOutpoint).filter(fileInfo => { Object.values(byOutpoint).filter(fileInfo => {
const myClaimIds = myClaims.map(claim => claim.claim_id); const myClaimIds = myClaims.map(claim => claim.claim_id);
return ( return (
@ -81,8 +78,7 @@ export const selectFileInfosDownloaded = createSelector(
myClaimIds.indexOf(fileInfo.claim_id) === -1 && myClaimIds.indexOf(fileInfo.claim_id) === -1 &&
(fileInfo.completed || fileInfo.written_bytes) (fileInfo.completed || fileInfo.written_bytes)
); );
}); })
}
); );
export const selectFileInfosPublished = createSelector( export const selectFileInfosPublished = createSelector(
@ -157,6 +153,6 @@ export const selectTotalDownloadProgress = createSelector(
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; if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
else return -1; return -1;
} }
); );

View file

@ -13,9 +13,9 @@ export const selectCurrentPath = createSelector(
export const computePageFromPath = path => export const computePageFromPath = path =>
path.replace(/^\//, "").split("?")[0]; path.replace(/^\//, "").split("?")[0];
export const selectCurrentPage = createSelector(selectCurrentPath, path => { export const selectCurrentPage = createSelector(selectCurrentPath, path =>
return computePageFromPath(path); computePageFromPath(path)
}); );
export const selectCurrentParams = createSelector(selectCurrentPath, path => { export const selectCurrentParams = createSelector(selectCurrentPath, path => {
if (path === undefined) return {}; if (path === undefined) return {};
@ -24,12 +24,11 @@ export const selectCurrentParams = createSelector(selectCurrentPath, path => {
return parseQueryParams(path.split("?")[1]); return parseQueryParams(path.split("?")[1]);
}); });
export const makeSelectCurrentParam = param => { export const makeSelectCurrentParam = param =>
return createSelector( createSelector(
selectCurrentParams, selectCurrentParams,
params => (params ? params[param] : undefined) params => (params ? params[param] : undefined)
); );
};
export const selectHeaderLinks = createSelector(selectCurrentPage, page => { export const selectHeaderLinks = createSelector(selectCurrentPage, page => {
// This contains intentional fall throughs // This contains intentional fall throughs

View file

@ -31,12 +31,13 @@ export const selectClaimedRewardsByTransactionId = createSelector(
export const selectUnclaimedRewards = createSelector( export const selectUnclaimedRewards = createSelector(
selectUnclaimedRewardsByType, selectUnclaimedRewardsByType,
byType => byType =>
Object.values(byType).sort(function(a, b) { Object.values(byType).sort(
return rewards.SORT_ORDER.indexOf(a.reward_type) < (a, b) =>
rewards.SORT_ORDER.indexOf(a.reward_type) <
rewards.SORT_ORDER.indexOf(b.reward_type) rewards.SORT_ORDER.indexOf(b.reward_type)
? -1 ? -1
: 1; : 1
}) || [] ) || []
); );
export const selectIsRewardEligible = createSelector( export const selectIsRewardEligible = createSelector(
@ -51,10 +52,7 @@ export const selectFetchingRewards = createSelector(
export const selectUnclaimedRewardValue = createSelector( export const selectUnclaimedRewardValue = createSelector(
selectUnclaimedRewards, selectUnclaimedRewards,
rewards => rewards => rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
rewards.reduce((sum, reward) => {
return sum + reward.reward_amount;
}, 0)
); );
export const selectHasClaimedReward = (state, props) => { export const selectHasClaimedReward = (state, props) => {
@ -62,47 +60,39 @@ export const selectHasClaimedReward = (state, props) => {
return reward && reward.transaction_id !== ""; return reward && reward.transaction_id !== "";
}; };
export const makeSelectHasClaimedReward = () => { export const makeSelectHasClaimedReward = () =>
return createSelector(selectHasClaimedReward, claimed => claimed); createSelector(selectHasClaimedReward, claimed => claimed);
};
export const selectClaimsPendingByType = createSelector( export const selectClaimsPendingByType = createSelector(
_selectState, _selectState,
state => state.claimPendingByType state => state.claimPendingByType
); );
const selectIsClaimRewardPending = (state, props) => { const selectIsClaimRewardPending = (state, props) =>
return selectClaimsPendingByType(state, props)[props.reward_type]; selectClaimsPendingByType(state, props)[props.reward_type];
};
export const makeSelectIsRewardClaimPending = () => { export const makeSelectIsRewardClaimPending = () =>
return createSelector(selectIsClaimRewardPending, isClaiming => isClaiming); createSelector(selectIsClaimRewardPending, isClaiming => isClaiming);
};
export const selectClaimErrorsByType = createSelector( export const selectClaimErrorsByType = createSelector(
_selectState, _selectState,
state => state.claimErrorsByType state => state.claimErrorsByType
); );
const selectClaimRewardError = (state, props) => { const selectClaimRewardError = (state, props) =>
return selectClaimErrorsByType(state, props)[props.reward_type]; selectClaimErrorsByType(state, props)[props.reward_type];
};
export const makeSelectClaimRewardError = () => { export const makeSelectClaimRewardError = () =>
return createSelector(selectClaimRewardError, errorMessage => errorMessage); createSelector(selectClaimRewardError, errorMessage => errorMessage);
};
const selectRewardByType = (state, props) => { const selectRewardByType = (state, props) =>
return selectUnclaimedRewardsByType(state)[props.reward_type]; selectUnclaimedRewardsByType(state)[props.reward_type];
};
export const makeSelectRewardByType = () => { export const makeSelectRewardByType = () =>
return createSelector(selectRewardByType, reward => reward); createSelector(selectRewardByType, reward => reward);
};
export const makeSelectRewardAmountByType = () => { export const makeSelectRewardAmountByType = () =>
return createSelector( createSelector(
selectRewardByType, selectRewardByType,
reward => (reward ? reward.reward_amount : 0) reward => (reward ? reward.reward_amount : 0)
); );
};

View file

@ -23,19 +23,18 @@ export const selectSearchUrisByQuery = createSelector(
state => state.urisByQuery state => state.urisByQuery
); );
export const makeSelectSearchUris = query => { export const makeSelectSearchUris = query =>
//replace statement below is kind of ugly, and repeated in doSearch action // replace statement below is kind of ugly, and repeated in doSearch action
return createSelector( createSelector(
selectSearchUrisByQuery, selectSearchUrisByQuery,
byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, "") : query] byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, "") : query]
); );
};
export const selectWunderBarAddress = createSelector( export const selectWunderBarAddress = createSelector(
selectCurrentPage, selectCurrentPage,
selectPageTitle, selectPageTitle,
selectSearchQuery, selectSearchQuery,
(page, title, query) => (page != "search" ? title : query ? query : title) (page, title, query) => (page != "search" ? title : query || title)
); );
export const selectWunderBarIcon = createSelector( export const selectWunderBarIcon = createSelector(

View file

@ -14,19 +14,18 @@ export const selectClientSettings = createSelector(
state => state.clientSettings || {} state => state.clientSettings || {}
); );
export const makeSelectClientSetting = setting => { export const makeSelectClientSetting = setting =>
return createSelector( createSelector(
selectClientSettings, selectClientSettings,
settings => (settings ? settings[setting] : undefined) settings => (settings ? settings[setting] : undefined)
); );
};
export const selectSettingsIsGenerous = createSelector( export const selectSettingsIsGenerous = createSelector(
selectDaemonSettings, selectDaemonSettings,
settings => settings && settings.is_generous_host settings => settings && settings.is_generous_host
); );
//refactor me // refactor me
export const selectShowNsfw = makeSelectClientSetting(settings.SHOW_NSFW); export const selectShowNsfw = makeSelectClientSetting(settings.SHOW_NSFW);
export const selectLanguages = createSelector( export const selectLanguages = createSelector(
@ -36,5 +35,5 @@ export const selectLanguages = createSelector(
export const selectThemePath = createSelector( export const selectThemePath = createSelector(
makeSelectClientSetting(settings.THEME), makeSelectClientSetting(settings.THEME),
theme => staticResourcesPath + "/themes/" + (theme || "light") + ".css" theme => `${staticResourcesPath}/themes/${theme || "light"}.css`
); );

View file

@ -21,7 +21,7 @@ export const selectSubscriptionsFromClaims = createSelector(
return []; return [];
} }
let fetchedSubscriptions = []; const fetchedSubscriptions = [];
savedSubscriptions.forEach(subscription => { savedSubscriptions.forEach(subscription => {
let channelClaims = []; let channelClaims = [];
@ -40,9 +40,9 @@ export const selectSubscriptionsFromClaims = createSelector(
} }
// all we really need is a uri for each claim // all we really need is a uri for each claim
channelClaims = channelClaims.map(claim => { channelClaims = channelClaims.map(
return `${claim.name}#${claim.claim_id}`; claim => `${claim.name}#${claim.claim_id}`
}) );
fetchedSubscriptions.push({ fetchedSubscriptions.push({
claims: channelClaims, claims: channelClaims,

View file

@ -20,7 +20,7 @@ export const selectTransactionItems = createSelector(
Object.keys(byId).forEach(txid => { Object.keys(byId).forEach(txid => {
const tx = byId[txid]; const tx = byId[txid];
//ignore dust/fees // ignore dust/fees
// it is fee only txn if all infos are also empty // it is fee only txn if all infos are also empty
if ( if (
Math.abs(tx.value) === Math.abs(tx.fee) && Math.abs(tx.value) === Math.abs(tx.fee) &&
@ -31,7 +31,7 @@ export const selectTransactionItems = createSelector(
return; return;
} }
let append = []; const append = [];
append.push( append.push(
...tx.claim_info.map(item => ...tx.claim_info.map(item =>
@ -63,16 +63,16 @@ export const selectTransactionItems = createSelector(
items.push( items.push(
...append.map(item => { ...append.map(item => {
//value on transaction, amount on outpoint // value on transaction, amount on outpoint
//amount is always positive, but should match sign of value // amount is always positive, but should match sign of value
const amount = parseFloat( const amount = parseFloat(
item.balance_delta ? item.balance_delta : item.value item.balance_delta ? item.balance_delta : item.value
); );
return { return {
txid: txid, txid,
date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null,
amount: amount, amount,
fee: amount < 0 ? -1 * tx.fee / append.length : 0, fee: amount < 0 ? -1 * tx.fee / append.length : 0,
claim_id: item.claim_id, claim_id: item.claim_id,
claim_name: item.claim_name, claim_name: item.claim_name,
@ -89,19 +89,15 @@ export const selectTransactionItems = createSelector(
export const selectRecentTransactions = createSelector( export const selectRecentTransactions = createSelector(
selectTransactionItems, selectTransactionItems,
transactions => { transactions => {
let threshold = new Date(); const threshold = new Date();
threshold.setDate(threshold.getDate() - 7); threshold.setDate(threshold.getDate() - 7);
return transactions.filter(transaction => { return transactions.filter(transaction => transaction.date > threshold);
return transaction.date > threshold;
});
} }
); );
export const selectHasTransactions = createSelector( export const selectHasTransactions = createSelector(
selectTransactionItems, selectTransactionItems,
transactions => { transactions => transactions && transactions.length > 0
return transactions && transactions.length > 0;
}
); );
export const selectIsFetchingTransactions = createSelector( export const selectIsFetchingTransactions = createSelector(
@ -146,10 +142,9 @@ export const selectDraftTransactionError = createSelector(
export const selectBlocks = createSelector(_selectState, state => state.blocks); export const selectBlocks = createSelector(_selectState, state => state.blocks);
export const makeSelectBlockDate = block => { export const makeSelectBlockDate = block =>
return createSelector( createSelector(
selectBlocks, selectBlocks,
blocks => blocks =>
blocks && blocks[block] ? new Date(blocks[block].time * 1000) : undefined blocks && blocks[block] ? new Date(blocks[block].time * 1000) : undefined
); );
};

View file

@ -95,15 +95,16 @@ rewards.claimReward = function(type) {
case rewards.TYPE_FIRST_CHANNEL: case rewards.TYPE_FIRST_CHANNEL:
lbry lbry
.claim_list_mine() .claim_list_mine()
.then(function(claims) { .then(claims => {
let claim = claims.reverse().find(function(claim) { const claim = claims
return ( .reverse()
claim.name.length && .find(
claim.name[0] == "@" && claim =>
claim.txid.length && claim.name.length &&
claim.category == "claim" claim.name[0] == "@" &&
claim.txid.length &&
claim.category == "claim"
); );
});
if (claim) { if (claim) {
params.transaction_id = claim.txid; params.transaction_id = claim.txid;
requestReward(resolve, reject, params); requestReward(resolve, reject, params);
@ -120,14 +121,15 @@ rewards.claimReward = function(type) {
lbry lbry
.claim_list_mine() .claim_list_mine()
.then(claims => { .then(claims => {
let claim = claims.reverse().find(function(claim) { const claim = claims
return ( .reverse()
claim.name.length && .find(
claim.name[0] != "@" && claim =>
claim.txid.length && claim.name.length &&
claim.category == "claim" claim.name[0] != "@" &&
claim.txid.length &&
claim.category == "claim"
); );
});
if (claim) { if (claim) {
params.transaction_id = claim.txid; params.transaction_id = claim.txid;
requestReward(resolve, reject, params); requestReward(resolve, reject, params);

View file

@ -2,7 +2,7 @@
function batchActions(...actions) { function batchActions(...actions) {
return { return {
type: "BATCH_ACTIONS", type: "BATCH_ACTIONS",
actions: actions, actions,
}; };
} }

View file

@ -17,7 +17,7 @@ export function formatFullPrice(amount, precision) {
const index = decimals.indexOf(first); const index = decimals.indexOf(first);
// Set format fraction // Set format fraction
formated = "." + fraction.substring(0, index + precision); formated = `.${fraction.substring(0, index + precision)}`;
} }
return parseFloat(quantity[0] + formated); return parseFloat(quantity[0] + formated);

View file

@ -4,12 +4,10 @@ export function parseQueryParams(queryString) {
.split("?") .split("?")
.pop() .pop()
.split("&") .split("&")
.map(function(p) { .map(p => p.split("="));
return p.split("=");
});
const params = {}; const params = {};
parts.forEach(function(arr) { parts.forEach(arr => {
params[arr[0]] = arr[1]; params[arr[0]] = arr[1];
}); });
return params; return params;
@ -21,7 +19,7 @@ export function toQueryString(params) {
const parts = []; const parts = [];
for (const key in params) { for (const key in params) {
if (params.hasOwnProperty(key) && params[key]) { if (params.hasOwnProperty(key) && params[key]) {
parts.push(key + "=" + params[key]); parts.push(`${key}=${params[key]}`);
} }
} }
return parts.join("&"); return parts.join("&");

View file

@ -1,17 +1,18 @@
// util for creating reducers // util for creating reducers
// based off of redux-actions // based off of redux-actions
// https://redux-actions.js.org/docs/api/handleAction.html#handleactions // https://redux-actions.js.org/docs/api/handleAction.html#handleactions
export const handleActions = (actionMap, defaultState) => { export const handleActions = (actionMap, defaultState) => (
return (state = defaultState, action) => { state = defaultState,
const handler = actionMap[action.type]; action
) => {
const handler = actionMap[action.type];
if (handler) { if (handler) {
const newState = handler(state, action); const newState = handler(state, action);
return Object.assign({}, state, newState); return Object.assign({}, state, newState);
} }
// just return the original state if no handler // just return the original state if no handler
// returning a copy here breaks redux-persist // returning a copy here breaks redux-persist
return state; return state;
};
}; };

View file

@ -1,4 +1,5 @@
const { remote } = require("electron"); const { remote } = require("electron");
const application = remote.app; const application = remote.app;
const dock = application.dock; const dock = application.dock;
const win = remote.BrowserWindow.getFocusedWindow(); const win = remote.BrowserWindow.getFocusedWindow();

View file

@ -1,4 +1,5 @@
const { remote } = require("electron"); const { remote } = require("electron");
const application = remote.app; const application = remote.app;
const win = remote.getCurrentWindow(); const win = remote.getCurrentWindow();

View file

@ -20,7 +20,7 @@ const validateAddress = (coinType, address) => {
}; };
export const validateShapeShiftForm = (vals, props) => { export const validateShapeShiftForm = (vals, props) => {
let errors = {}; const errors = {};
if (!vals.returnAddress) { if (!vals.returnAddress) {
return errors; return errors;
@ -45,6 +45,4 @@ const exampleCoinAddresses = {
"466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm", "466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm",
}; };
export const getExampleAddress = coin => { export const getExampleAddress = coin => exampleCoinAddresses[coin];
return exampleCoinAddresses[coin];
};