Pretty print and lint non-component sources
This commit is contained in:
parent
4a48d0a521
commit
7cd25e777a
103 changed files with 3577 additions and 4210 deletions
|
@ -22,8 +22,8 @@
|
||||||
"build": "yarn compile && electron-builder build",
|
"build": "yarn compile && electron-builder build",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"precommit": "lint-staged",
|
"precommit": "lint-staged",
|
||||||
"lint": "eslint src/**/*.{js,jsx} --fix",
|
"lint": "eslint 'src/**/*.{js,jsx}' --fix",
|
||||||
"pretty": "prettier src/**/*.{js,jsx,scss,json} --write"
|
"pretty-print": "prettier 'src/**/*.{js,jsx,scss,json}' --write"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"lbry"
|
"lbry"
|
||||||
|
|
|
@ -1,68 +1,39 @@
|
||||||
|
/* eslint-disable no-console */
|
||||||
// Module imports
|
// Module imports
|
||||||
const {
|
import Path from 'path';
|
||||||
app,
|
import Url from 'url';
|
||||||
BrowserWindow,
|
import Jayson from 'jayson';
|
||||||
ipcMain,
|
import Semver from 'semver';
|
||||||
Menu,
|
import Https from 'https';
|
||||||
Tray,
|
import Keytar from 'keytar';
|
||||||
globalShortcut,
|
import ChildProcess from 'child_process';
|
||||||
} = require("electron");
|
import Assert from 'assert';
|
||||||
const path = require("path");
|
import { app, BrowserWindow, globalShortcut, ipcMain, Menu, Tray } from 'electron';
|
||||||
const url = require("url");
|
import mainMenu from './menu/mainMenu';
|
||||||
const jayson = require("jayson");
|
|
||||||
const semver = require("semver");
|
|
||||||
const https = require("https");
|
|
||||||
const keytar = require("keytar");
|
|
||||||
// tree-kill has better cross-platform handling of
|
|
||||||
// killing a process. child-process.kill was unreliable
|
|
||||||
const kill = require("tree-kill");
|
|
||||||
const child_process = require("child_process");
|
|
||||||
const assert = require("assert");
|
|
||||||
|
|
||||||
const localVersion = app.getVersion();
|
const localVersion = app.getVersion();
|
||||||
const setMenu = require("./menu/main-menu.js");
|
export { contextMenu as Default } from './menu/contextMenu';
|
||||||
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) {
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
default: installExtension,
|
|
||||||
REACT_DEVELOPER_TOOLS,
|
|
||||||
REDUX_DEVTOOLS,
|
|
||||||
} = require("electron-devtools-installer");
|
|
||||||
app.on("ready", () => {
|
|
||||||
[REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => {
|
|
||||||
installExtension(extension)
|
|
||||||
.then(name => console.log(`Added Extension: ${name}`))
|
|
||||||
.catch(err => console.log("An error occurred: ", err));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Misc constants
|
// Misc constants
|
||||||
const LATEST_RELEASE_API_URL =
|
const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest';
|
||||||
"https://api.github.com/repos/lbryio/lbry-app/releases/latest";
|
const DAEMON_PATH = process.env.LBRY_DAEMON || Path.join(__static, 'daemon/lbrynet-daemon');
|
||||||
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`;
|
||||||
|
|
||||||
const 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
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
let win;
|
let rendererWindow;
|
||||||
// Also keep the daemon subprocess alive
|
// Also keep the daemon subprocess alive
|
||||||
let daemonSubprocess;
|
let daemonSubprocess;
|
||||||
|
|
||||||
|
@ -95,8 +66,8 @@ 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('/#', '#');
|
||||||
}
|
}
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
@ -109,223 +80,22 @@ function processRequestedUri(uri) {
|
||||||
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 = ChildProcess.spawn('open', [fullPath], subprocOptions);
|
||||||
} else if (process.platform === "linux") {
|
} else if (process.platform === 'linux') {
|
||||||
child = child_process.spawn("xdg-open", [fullPath], subprocOptions);
|
child = ChildProcess.spawn('xdg-open', [fullPath], subprocOptions);
|
||||||
} else if (process.platform === "win32") {
|
} else if (process.platform === 'win32') {
|
||||||
child = child_process.spawn(
|
child = ChildProcess.spawn(fullPath, Object.assign({}, subprocOptions, { shell: true }));
|
||||||
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) {
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
const tasklistOut = child_process.execSync(
|
|
||||||
`tasklist /fi "Imagename eq ${name}.exe" /nh`,
|
|
||||||
{ encoding: "utf8" }
|
|
||||||
);
|
|
||||||
if (tasklistOut.startsWith("INFO")) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return tasklistOut.match(/[^\r\n]+/g).map(line => line.split(/\s+/)[1]); // Second column of every non-empty line
|
|
||||||
}
|
|
||||||
const pgrepOut = child_process.spawnSync("pgrep", ["-x", name], {
|
|
||||||
encoding: "utf8",
|
|
||||||
}).stdout;
|
|
||||||
return pgrepOut.match(/\d+/g);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createWindow() {
|
|
||||||
// Disable renderer process's webSecurity on development to enable CORS.
|
|
||||||
win = isDevelopment
|
|
||||||
? new BrowserWindow({
|
|
||||||
backgroundColor: "#155B4A",
|
|
||||||
minWidth: 800,
|
|
||||||
minHeight: 600,
|
|
||||||
webPreferences: { webSecurity: false },
|
|
||||||
})
|
|
||||||
: new BrowserWindow({
|
|
||||||
backgroundColor: "#155B4A",
|
|
||||||
minWidth: 800,
|
|
||||||
minHeight: 600,
|
|
||||||
});
|
|
||||||
|
|
||||||
win.webContents.session.setUserAgent(`LBRY/${localVersion}`);
|
|
||||||
|
|
||||||
win.maximize();
|
|
||||||
if (isDevelopment) {
|
|
||||||
win.webContents.openDevTools();
|
|
||||||
}
|
|
||||||
win.loadURL(rendererUrl);
|
|
||||||
if (openUri) {
|
|
||||||
// We stored and received a URI that an external app requested before we had a window object
|
|
||||||
win.webContents.on("did-finish-load", () => {
|
|
||||||
win.webContents.send("open-uri-requested", openUri);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
win.removeAllListeners();
|
|
||||||
|
|
||||||
win.on("close", event => {
|
|
||||||
if (minimize) {
|
|
||||||
event.preventDefault();
|
|
||||||
win.hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
win.on("closed", () => {
|
|
||||||
win = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
win.on("hide", () => {
|
|
||||||
// Checks what to show in the tray icon menu
|
|
||||||
if (minimize) updateTray();
|
|
||||||
});
|
|
||||||
|
|
||||||
win.on("show", () => {
|
|
||||||
// Checks what to show in the tray icon menu
|
|
||||||
if (minimize) updateTray();
|
|
||||||
});
|
|
||||||
|
|
||||||
win.on("blur", () => {
|
|
||||||
// Checks what to show in the tray icon menu
|
|
||||||
if (minimize) updateTray();
|
|
||||||
|
|
||||||
// Unregisters Alt+F4 shortcut
|
|
||||||
globalShortcut.unregister("Alt+F4");
|
|
||||||
});
|
|
||||||
|
|
||||||
win.on("focus", () => {
|
|
||||||
// Checks what to show in the tray icon menu
|
|
||||||
if (minimize) updateTray();
|
|
||||||
|
|
||||||
// Registers shortcut for closing(quitting) the app
|
|
||||||
globalShortcut.register("Alt+F4", () => safeQuit());
|
|
||||||
|
|
||||||
win.webContents.send("window-is-focused", null);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Menu bar
|
|
||||||
win.setAutoHideMenuBar(true);
|
|
||||||
win.setMenuBarVisibility(isDevelopment);
|
|
||||||
setMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
function createTray() {
|
|
||||||
// Minimize to tray logic follows:
|
|
||||||
// Set the tray icon
|
|
||||||
let iconPath;
|
|
||||||
if (process.platform === "darwin") {
|
|
||||||
// Using @2x for mac retina screens so the icon isn't blurry
|
|
||||||
// file name needs to include "Template" at the end for dark menu bar
|
|
||||||
iconPath = path.join(__static, "/img/fav/macTemplate@2x.png");
|
|
||||||
} else {
|
|
||||||
iconPath = path.join(__static, "/img/fav/32x32.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
tray = new Tray(iconPath);
|
|
||||||
tray.setToolTip("LBRY App");
|
|
||||||
tray.setTitle("LBRY");
|
|
||||||
tray.on("double-click", () => {
|
|
||||||
win.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This needs to be done as for linux the context menu doesn't update automatically(docs)
|
|
||||||
function updateTray() {
|
|
||||||
const contextMenu = Menu.buildFromTemplate(getMenuTemplate());
|
|
||||||
if (tray) {
|
|
||||||
tray.setContextMenu(contextMenu);
|
|
||||||
} else {
|
|
||||||
console.log("How did update tray get called without a tray?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMenuTemplate() {
|
|
||||||
return [
|
|
||||||
getToggleItem(),
|
|
||||||
{
|
|
||||||
label: "Quit",
|
|
||||||
click: () => safeQuit(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function getToggleItem() {
|
|
||||||
if (win.isVisible() && win.isFocused()) {
|
|
||||||
return {
|
|
||||||
label: "Hide LBRY App",
|
|
||||||
click: () => win.hide(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
label: "Show LBRY App",
|
|
||||||
click: () => win.show(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleOpenUriRequested(uri) {
|
|
||||||
if (!win) {
|
|
||||||
// Window not created yet, so store up requested URI for when it is
|
|
||||||
openUri = processRequestedUri(uri);
|
|
||||||
} else {
|
|
||||||
if (win.isMinimized()) {
|
|
||||||
win.restore();
|
|
||||||
} else if (!win.isVisible()) {
|
|
||||||
win.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
win.focus();
|
|
||||||
win.webContents.send("open-uri-requested", processRequestedUri(uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDaemonSubprocessExited() {
|
|
||||||
console.log("The daemon has exited.");
|
|
||||||
daemonSubprocess = null;
|
|
||||||
if (!daemonStopRequested) {
|
|
||||||
// We didn't request to stop the daemon, so display a
|
|
||||||
// warning and schedule a quit.
|
|
||||||
//
|
|
||||||
// TODO: maybe it would be better to restart the daemon?
|
|
||||||
if (win) {
|
|
||||||
console.log("Did not request daemon stop, so quitting in 5 seconds.");
|
|
||||||
win.loadURL(`file://${__static}/warning.html`);
|
|
||||||
setTimeout(quitNow, 5000);
|
|
||||||
} else {
|
|
||||||
console.log("Did not request daemon stop, so quitting.");
|
|
||||||
quitNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function launchDaemon() {
|
|
||||||
assert(!daemonSubprocess, "Tried to launch daemon twice");
|
|
||||||
|
|
||||||
console.log("Launching daemon:", DAEMON_PATH);
|
|
||||||
daemonSubprocess = child_process.spawn(DAEMON_PATH);
|
|
||||||
// Need to handle the data event instead of attaching to
|
|
||||||
// process.stdout because the latter doesn't work. I believe on
|
|
||||||
// windows it buffers stdout and we don't get any meaningful output
|
|
||||||
daemonSubprocess.stdout.on("data", buf => {
|
|
||||||
console.log(String(buf).trim());
|
|
||||||
});
|
|
||||||
daemonSubprocess.stderr.on("data", buf => {
|
|
||||||
console.log(String(buf).trim());
|
|
||||||
});
|
|
||||||
daemonSubprocess.on("exit", handleDaemonSubprocessExited);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quits by first killing the daemon, the calling quitting for real.
|
* Quits by first killing the daemon, the calling quitting for real.
|
||||||
*/
|
*/
|
||||||
|
@ -334,6 +104,155 @@ export function safeQuit() {
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMenuTemplate() {
|
||||||
|
function getToggleItem() {
|
||||||
|
if (rendererWindow.isVisible() && rendererWindow.isFocused()) {
|
||||||
|
return {
|
||||||
|
label: 'Hide LBRY App',
|
||||||
|
click: () => rendererWindow.hide(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
label: 'Show LBRY App',
|
||||||
|
click: () => rendererWindow.show(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
getToggleItem(),
|
||||||
|
{
|
||||||
|
label: 'Quit',
|
||||||
|
click: () => safeQuit(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// This needs to be done as for linux the context menu doesn't update automatically(docs)
|
||||||
|
function updateTray() {
|
||||||
|
const trayContextMenu = Menu.buildFromTemplate(getMenuTemplate());
|
||||||
|
if (tray) {
|
||||||
|
tray.setContextMenu(trayContextMenu);
|
||||||
|
} else {
|
||||||
|
console.log('How did update tray get called without a tray?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWindow() {
|
||||||
|
// Disable renderer process's webSecurity on development to enable CORS.
|
||||||
|
let windowConfiguration = {
|
||||||
|
backgroundColor: '#155B4A',
|
||||||
|
minWidth: 800,
|
||||||
|
minHeight: 600,
|
||||||
|
autoHideMenuBar: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
windowConfiguration = isDevelopment
|
||||||
|
? {
|
||||||
|
...windowConfiguration,
|
||||||
|
webPreferences: {
|
||||||
|
webSecurity: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: windowConfiguration;
|
||||||
|
|
||||||
|
let window = new BrowserWindow(windowConfiguration);
|
||||||
|
|
||||||
|
window.webContents.session.setUserAgent(`LBRY/${localVersion}`);
|
||||||
|
|
||||||
|
window.maximize();
|
||||||
|
if (isDevelopment) {
|
||||||
|
window.webContents.openDevTools();
|
||||||
|
}
|
||||||
|
window.loadURL(rendererUrl);
|
||||||
|
if (openUri) {
|
||||||
|
// We stored and received a URI that an external app requested before we had a window object
|
||||||
|
window.webContents.on('did-finish-load', () => {
|
||||||
|
window.webContents.send('open-uri-requested', openUri);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.removeAllListeners();
|
||||||
|
|
||||||
|
window.on('close', event => {
|
||||||
|
if (minimize) {
|
||||||
|
event.preventDefault();
|
||||||
|
window.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.on('closed', () => {
|
||||||
|
window = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.on('hide', () => {
|
||||||
|
// Checks what to show in the tray icon menu
|
||||||
|
if (minimize) updateTray();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.on('show', () => {
|
||||||
|
// Checks what to show in the tray icon menu
|
||||||
|
if (minimize) updateTray();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.on('blur', () => {
|
||||||
|
// Checks what to show in the tray icon menu
|
||||||
|
if (minimize) updateTray();
|
||||||
|
|
||||||
|
// Unregisters Alt+F4 shortcut
|
||||||
|
globalShortcut.unregister('Alt+F4');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.on('focus', () => {
|
||||||
|
// Checks what to show in the tray icon menu
|
||||||
|
if (minimize) updateTray();
|
||||||
|
|
||||||
|
// Registers shortcut for closing(quitting) the app
|
||||||
|
globalShortcut.register('Alt+F4', () => safeQuit());
|
||||||
|
|
||||||
|
window.webContents.send('window-is-focused', null);
|
||||||
|
});
|
||||||
|
|
||||||
|
mainMenu();
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTray() {
|
||||||
|
// Minimize to tray logic follows:
|
||||||
|
// Set the tray icon
|
||||||
|
let iconPath;
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
// Using @2x for mac retina screens so the icon isn't blurry
|
||||||
|
// file name needs to include "Template" at the end for dark menu bar
|
||||||
|
iconPath = Path.join(__static, '/img/fav/macTemplate@2x.png');
|
||||||
|
} else {
|
||||||
|
iconPath = Path.join(__static, '/img/fav/32x32.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
tray = new Tray(iconPath);
|
||||||
|
tray.setToolTip('LBRY App');
|
||||||
|
tray.setTitle('LBRY');
|
||||||
|
tray.on('double-click', () => {
|
||||||
|
rendererWindow.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOpenUriRequested(uri) {
|
||||||
|
if (!rendererWindow) {
|
||||||
|
// Window not created yet, so store up requested URI for when it is
|
||||||
|
openUri = processRequestedUri(uri);
|
||||||
|
} else {
|
||||||
|
if (rendererWindow.isMinimized()) {
|
||||||
|
rendererWindow.restore();
|
||||||
|
} else if (!rendererWindow.isVisible()) {
|
||||||
|
rendererWindow.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
rendererWindow.focus();
|
||||||
|
rendererWindow.webContents.send('open-uri-requested', processRequestedUri(uri));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quits without any preparation. When a quit is requested (either through the
|
* Quits without any preparation. When a quit is requested (either through the
|
||||||
* interface or through app.quit()), we abort the quit, try to shut down the daemon,
|
* interface or through app.quit()), we abort the quit, try to shut down the daemon,
|
||||||
|
@ -344,16 +263,52 @@ function quitNow() {
|
||||||
safeQuit();
|
safeQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleDaemonSubprocessExited() {
|
||||||
|
console.log('The daemon has exited.');
|
||||||
|
daemonSubprocess = null;
|
||||||
|
if (!daemonStopRequested) {
|
||||||
|
// We didn't request to stop the daemon, so display a
|
||||||
|
// warning and schedule a quit.
|
||||||
|
//
|
||||||
|
// TODO: maybe it would be better to restart the daemon?
|
||||||
|
if (rendererWindow) {
|
||||||
|
console.log('Did not request daemon stop, so quitting in 5 seconds.');
|
||||||
|
rendererWindow.loadURL(`file://${__static}/warning.html`);
|
||||||
|
setTimeout(quitNow, 5000);
|
||||||
|
} else {
|
||||||
|
console.log('Did not request daemon stop, so quitting.');
|
||||||
|
quitNow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function launchDaemon() {
|
||||||
|
Assert(!daemonSubprocess, 'Tried to launch daemon twice');
|
||||||
|
|
||||||
|
console.log('Launching daemon:', DAEMON_PATH);
|
||||||
|
daemonSubprocess = ChildProcess.spawn(DAEMON_PATH);
|
||||||
|
// Need to handle the data event instead of attaching to
|
||||||
|
// process.stdout because the latter doesn't work. I believe on
|
||||||
|
// windows it buffers stdout and we don't get any meaningful output
|
||||||
|
daemonSubprocess.stdout.on('data', buf => {
|
||||||
|
console.log(String(buf).trim());
|
||||||
|
});
|
||||||
|
daemonSubprocess.stderr.on('data', buf => {
|
||||||
|
console.log(String(buf).trim());
|
||||||
|
});
|
||||||
|
daemonSubprocess.on('exit', handleDaemonSubprocessExited);
|
||||||
|
}
|
||||||
|
|
||||||
const isSecondaryInstance = app.makeSingleInstance(argv => {
|
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 (rendererWindow) {
|
||||||
if (win.isMinimized()) {
|
if (rendererWindow.isMinimized()) {
|
||||||
win.restore();
|
rendererWindow.restore();
|
||||||
} else if (!win.isVisible()) {
|
} else if (!rendererWindow.isVisible()) {
|
||||||
win.show();
|
rendererWindow.show();
|
||||||
}
|
}
|
||||||
win.focus();
|
rendererWindow.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -365,126 +320,44 @@ if (isSecondaryInstance) {
|
||||||
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("status", [], (err, res) => {
|
client.request('status', [], err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("lbrynet daemon needs to be launched");
|
console.log('lbrynet daemon needs to be launched');
|
||||||
launchDaemon();
|
launchDaemon();
|
||||||
} else {
|
} else {
|
||||||
console.log("lbrynet daemon is already running");
|
console.log('lbrynet daemon is already running');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Taken from webtorrent-desktop
|
||||||
* Last resort for killing unresponsive daemon instances.
|
function checkLinuxTraySupport(cb) {
|
||||||
* Looks for any processes called "lbrynet-daemon" and
|
// Check that we're on Ubuntu (or another debian system) and that we have
|
||||||
* tries to force kill them.
|
// libappindicator1.
|
||||||
*/
|
ChildProcess.exec('dpkg --get-selections libappindicator1', (err, stdout) => {
|
||||||
function forceKillAllDaemonsAndQuit() {
|
if (err) return cb(err);
|
||||||
console.log(
|
// Unfortunately there's no cleaner way, as far as I can tell, to check
|
||||||
"Attempting to force kill any running lbrynet-daemon instances..."
|
// whether a debian package is installed:
|
||||||
);
|
if (stdout.endsWith('\tinstall\n')) {
|
||||||
|
return cb(null);
|
||||||
const daemonPids = getPidsForProcessName("lbrynet-daemon");
|
|
||||||
if (!daemonPids) {
|
|
||||||
console.log("No lbrynet-daemon found running.");
|
|
||||||
quitNow();
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
`Found ${
|
|
||||||
daemonPids.length
|
|
||||||
} running daemon instances. Attempting to force kill...`
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const pid of daemonPids) {
|
|
||||||
let daemonKillAttemptsComplete = 0;
|
|
||||||
kill(pid, "SIGKILL", err => {
|
|
||||||
daemonKillAttemptsComplete++;
|
|
||||||
if (err) {
|
|
||||||
console.log(
|
|
||||||
`Failed to force kill daemon task with pid ${pid}. Error message: ${
|
|
||||||
err.message
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.log(`Force killed daemon task with pid ${pid}.`);
|
|
||||||
}
|
|
||||||
if (daemonKillAttemptsComplete >= daemonPids.length - 1) {
|
|
||||||
quitNow();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
return cb(new Error('debian package not installed'));
|
||||||
}
|
|
||||||
|
|
||||||
app.setAsDefaultProtocolClient("lbry");
|
|
||||||
|
|
||||||
app.on("ready", () => {
|
|
||||||
launchDaemonIfNotRunning();
|
|
||||||
if (process.platform === "linux") {
|
|
||||||
checkLinuxTraySupport(err => {
|
|
||||||
if (!err) createTray();
|
|
||||||
else minimize = false;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
createTray();
|
|
||||||
}
|
|
||||||
createWindow();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
|
||||||
app.on("window-all-closed", () => {
|
|
||||||
// On macOS it is common for applications and their menu bar
|
|
||||||
// to stay active until the user quits explicitly with Cmd + Q
|
|
||||||
if (process.platform !== "darwin") {
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.on("before-quit", event => {
|
|
||||||
if (!readyToQuit) {
|
|
||||||
// We need to shutdown the daemon before we're ready to actually quit. This
|
|
||||||
// event will be triggered re-entrantly once preparation is done.
|
|
||||||
event.preventDefault();
|
|
||||||
shutdownDaemonAndQuit();
|
|
||||||
} else {
|
|
||||||
console.log("Quitting.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.on("activate", () => {
|
|
||||||
// On macOS it's common to re-create a window in the app when the
|
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (win === null) {
|
|
||||||
createWindow();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.platform === "darwin") {
|
|
||||||
app.on("open-url", (event, uri) => {
|
|
||||||
handleOpenUriRequested(uri);
|
|
||||||
});
|
});
|
||||||
} else if (process.argv.length >= 2) {
|
|
||||||
handleOpenUriRequested(process.argv[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When a quit is attempted, this is called. It attempts to shutdown the daemon,
|
// When a quit is attempted, this is called. It attempts to shutdown the daemon,
|
||||||
// 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 => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(
|
console.log(`received error when stopping lbrynet-daemon. Error message: ${err.message}\n`);
|
||||||
`received error when stopping lbrynet-daemon. Error message: ${
|
console.log('You will need to manually kill the daemon.');
|
||||||
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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -493,7 +366,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();
|
||||||
|
@ -503,111 +376,154 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
|
||||||
// If not, we should wait until the daemon is closed before we start the install.
|
// If not, we should wait until the daemon is closed before we start the install.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Taken from webtorrent-desktop
|
if (isDevelopment) {
|
||||||
function checkLinuxTraySupport(cb) {
|
import('devtron')
|
||||||
// Check that we're on Ubuntu (or another debian system) and that we have
|
.then(({ install }) => {
|
||||||
// libappindicator1.
|
install();
|
||||||
child_process.exec(
|
console.log('Added Extension: Devtron');
|
||||||
"dpkg --get-selections libappindicator1",
|
})
|
||||||
(err, stdout) => {
|
.catch(error => {
|
||||||
if (err) return cb(err);
|
console.error(error);
|
||||||
// Unfortunately there's no cleaner way, as far as I can tell, to check
|
});
|
||||||
// whether a debian package is installed:
|
import('electron-devtools-installer')
|
||||||
if (stdout.endsWith("\tinstall\n")) {
|
.then(({ default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS }) => {
|
||||||
cb(null);
|
app.on('ready', () => {
|
||||||
} else {
|
[REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => {
|
||||||
cb(new Error("debian package not installed"));
|
installExtension(extension)
|
||||||
}
|
.then(name => console.log(`Added Extension: ${name}`))
|
||||||
}
|
.catch(err => console.log('An error occurred: ', err));
|
||||||
);
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.on("upgrade", (event, installerPath) => {
|
app.setAsDefaultProtocolClient('lbry');
|
||||||
app.on("quit", () => {
|
|
||||||
console.log("Launching upgrade installer at", installerPath);
|
app.on('ready', () => {
|
||||||
|
launchDaemonIfNotRunning();
|
||||||
|
if (process.platform === 'linux') {
|
||||||
|
checkLinuxTraySupport(err => {
|
||||||
|
if (!err) createTray();
|
||||||
|
else minimize = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
createTray();
|
||||||
|
}
|
||||||
|
rendererWindow = createWindow();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Quit when all windows are closed.
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
// On macOS it is common for applications and their menu bar
|
||||||
|
// to stay active until the user quits explicitly with Cmd + Q
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('before-quit', event => {
|
||||||
|
if (!readyToQuit) {
|
||||||
|
// We need to shutdown the daemon before we're ready to actually quit. This
|
||||||
|
// event will be triggered re-entrantly once preparation is done.
|
||||||
|
event.preventDefault();
|
||||||
|
shutdownDaemonAndQuit();
|
||||||
|
} else {
|
||||||
|
console.log('Quitting.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
// On macOS it's common to re-create a window in the app when the
|
||||||
|
// dock icon is clicked and there are no other windows open.
|
||||||
|
if (rendererWindow === null) {
|
||||||
|
createWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
app.on('open-url', (event, uri) => {
|
||||||
|
handleOpenUriRequested(uri);
|
||||||
|
});
|
||||||
|
} else if (process.argv.length >= 2) {
|
||||||
|
handleOpenUriRequested(process.argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcMain.on('upgrade', (event, installerPath) => {
|
||||||
|
app.on('quit', () => {
|
||||||
|
console.log('Launching upgrade installer at', installerPath);
|
||||||
// This gets triggered called after *all* other quit-related events, so
|
// 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);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (win) {
|
if (rendererWindow) {
|
||||||
win.loadURL(`file://${__static}/upgrade.html`);
|
rendererWindow.loadURL(`file://${__static}/upgrade.html`);
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
console.log(
|
||||||
"The app will close, and you will be prompted to install the latest version of LBRY."
|
'The app will close, and you will be prompted to install the latest version of LBRY.'
|
||||||
);
|
);
|
||||||
console.log("After the install is complete, please reopen the app.");
|
console.log('After the install is complete, please reopen the app.');
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on("version-info-requested", () => {
|
ipcMain.on('version-info-requested', () => {
|
||||||
function formatRc(ver) {
|
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(
|
const req = Https.get(Object.assign(opts, Url.parse(LATEST_RELEASE_API_URL)), res => {
|
||||||
Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)),
|
res.on('data', data => {
|
||||||
res => {
|
result += data;
|
||||||
res.on("data", data => {
|
});
|
||||||
result += data;
|
res.on('end', () => {
|
||||||
});
|
const tagName = JSON.parse(result).tag_name;
|
||||||
res.on("end", () => {
|
const [, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/);
|
||||||
const tagName = JSON.parse(result).tag_name;
|
if (!remoteVersion) {
|
||||||
const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/);
|
if (rendererWindow) {
|
||||||
if (!remoteVersion) {
|
rendererWindow.webContents.send('version-info-received', null);
|
||||||
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 (rendererWindow) {
|
||||||
|
rendererWindow.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 (rendererWindow) {
|
||||||
win.webContents.send("version-info-received", null);
|
rendererWindow.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(
|
event.sender.send('auth-token-response', token ? token.toString().trim() : null);
|
||||||
"auth-token-response",
|
|
||||||
token ? token.toString().trim() : null
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on("set-auth-token", (event, token) => {
|
ipcMain.on('set-auth-token', (event, token) => {
|
||||||
keytar.setPassword(
|
Keytar.setPassword('LBRY', 'auth_token', token ? token.toString().trim() : null);
|
||||||
"LBRY",
|
|
||||||
"auth_token",
|
|
||||||
token ? token.toString().trim() : null
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
const { Menu } = require("electron");
|
|
||||||
const electron = require("electron");
|
|
||||||
|
|
||||||
const app = electron.app;
|
|
||||||
|
|
||||||
const contextMenuTemplate = [
|
|
||||||
{
|
|
||||||
role: "cut",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "copy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "paste",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
showContextMenu(win, posX, posY, showDevItems) {
|
|
||||||
const template = contextMenuTemplate.slice();
|
|
||||||
if (showDevItems) {
|
|
||||||
template.push({
|
|
||||||
type: "separator",
|
|
||||||
});
|
|
||||||
template.push({
|
|
||||||
label: "Inspect Element",
|
|
||||||
click() {
|
|
||||||
win.inspectElement(posX, posY);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu.buildFromTemplate(template).popup(win);
|
|
||||||
},
|
|
||||||
};
|
|
30
src/main/menu/contextMenu.js
Normal file
30
src/main/menu/contextMenu.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { Menu } from 'electron';
|
||||||
|
|
||||||
|
const contextMenuTemplate = [
|
||||||
|
{
|
||||||
|
role: 'cut',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'copy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'paste',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function contextMenu(win, posX, posY, showDevItems) {
|
||||||
|
const template = contextMenuTemplate.slice();
|
||||||
|
if (showDevItems) {
|
||||||
|
template.push({
|
||||||
|
type: 'separator',
|
||||||
|
});
|
||||||
|
template.push({
|
||||||
|
label: 'Inspect Element',
|
||||||
|
click() {
|
||||||
|
win.inspectElement(posX, posY);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu.buildFromTemplate(template).popup(win);
|
||||||
|
}
|
|
@ -1,136 +0,0 @@
|
||||||
const { app, shell, Menu } = require("electron");
|
|
||||||
const { safeQuit } = require("../index.js");
|
|
||||||
|
|
||||||
const baseTemplate = [
|
|
||||||
{
|
|
||||||
label: "File",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: "Quit",
|
|
||||||
accelerator: "CommandOrControl+Q",
|
|
||||||
click: () => safeQuit(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Edit",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
role: "undo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "redo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "separator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "cut",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "copy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "paste",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "selectall",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "View",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
role: "reload",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Developer",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
role: "forcereload",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "toggledevtools",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "separator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "togglefullscreen",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "help",
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: "Learn More",
|
|
||||||
click(item, focusedWindow) {
|
|
||||||
if (focusedWindow) {
|
|
||||||
focusedWindow.webContents.send("open-menu", "/help");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Frequently Asked Questions",
|
|
||||||
click(item, focusedWindow) {
|
|
||||||
shell.openExternal("https://lbry.io/faq");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "separator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Report Issue",
|
|
||||||
click(item, focusedWindow) {
|
|
||||||
shell.openExternal("https://lbry.io/faq/contributing#report-a-bug");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "separator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Developer API Guide",
|
|
||||||
click(item, focusedWindow) {
|
|
||||||
shell.openExternal("https://lbry.io/quickstart");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const macOSAppMenuTemplate = {
|
|
||||||
label: app.getName(),
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
role: "about",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "separator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "hide",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "hideothers",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "unhide",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "separator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "quit",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
const template = baseTemplate.slice();
|
|
||||||
process.platform === "darwin" && template.unshift(macOSAppMenuTemplate);
|
|
||||||
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
|
|
||||||
};
|
|
138
src/main/menu/mainMenu.js
Normal file
138
src/main/menu/mainMenu.js
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
import { app, Menu, shell } from 'electron';
|
||||||
|
import { safeQuit } from '../index';
|
||||||
|
|
||||||
|
const baseTemplate = [
|
||||||
|
{
|
||||||
|
label: 'File',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: 'Quit',
|
||||||
|
accelerator: 'CommandOrControl+Q',
|
||||||
|
click: () => safeQuit(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
role: 'undo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'redo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'cut',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'copy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'paste',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'selectall',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'View',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
role: 'reload',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Developer',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
role: 'forcereload',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'toggledevtools',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'togglefullscreen',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'help',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: 'Learn More',
|
||||||
|
click(item, focusedWindow) {
|
||||||
|
if (focusedWindow) {
|
||||||
|
focusedWindow.webContents.send('open-menu', '/help');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Frequently Asked Questions',
|
||||||
|
click() {
|
||||||
|
shell.openExternal('https://lbry.io/faq');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Report Issue',
|
||||||
|
click() {
|
||||||
|
shell.openExternal('https://lbry.io/faq/contributing#report-a-bug');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Developer API Guide',
|
||||||
|
click() {
|
||||||
|
shell.openExternal('https://lbry.io/quickstart');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const macOSAppMenuTemplate = {
|
||||||
|
label: app.getName(),
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
role: 'about',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'hide',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'hideothers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'unhide',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'quit',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const template = baseTemplate.slice();
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
template.unshift(macOSAppMenuTemplate);
|
||||||
|
}
|
||||||
|
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
|
||||||
|
};
|
|
@ -1,17 +1,16 @@
|
||||||
import store from "store";
|
import store from 'store';
|
||||||
import { remote } from "electron";
|
import { remote } from 'electron';
|
||||||
import path from "path";
|
import path from 'path';
|
||||||
|
import y18n from 'y18n';
|
||||||
|
|
||||||
const env = process.env.NODE_ENV || "production";
|
const env = process.env.NODE_ENV || 'production';
|
||||||
const config = {
|
const config = {
|
||||||
...require(`./config/${env}`),
|
...import(`./config/${env}`),
|
||||||
};
|
};
|
||||||
const i18n = require("y18n")({
|
const i18n = y18n({
|
||||||
directory: path
|
directory: path.join(remote.app.getAppPath(), '/../static/locales').replace(/\\/g, '\\\\'),
|
||||||
.join(remote.app.getAppPath(), "/../static/locales")
|
|
||||||
.replace(/\\/g, "\\\\"),
|
|
||||||
updateFiles: false,
|
updateFiles: false,
|
||||||
locale: "en",
|
locale: 'en',
|
||||||
});
|
});
|
||||||
|
|
||||||
const logs = [];
|
const logs = [];
|
||||||
|
@ -26,8 +25,17 @@ const app = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
window.__ = i18n.__;
|
// Workaround for https://github.com/electron-userland/electron-webpack/issues/52
|
||||||
window.__n = i18n.__n;
|
if (env !== 'development') {
|
||||||
|
window.staticResourcesPath = path
|
||||||
|
.join(remote.app.getAppPath(), '../static')
|
||||||
|
.replace(/\\/g, '\\\\');
|
||||||
|
} else {
|
||||||
|
window.staticResourcesPath = '';
|
||||||
|
}
|
||||||
|
|
||||||
global.app = app;
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
module.exports = app;
|
window.__ = i18n.__;
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
window.__n = i18n.__n;
|
||||||
|
window.app = app;
|
||||||
|
|
|
@ -1,166 +1,156 @@
|
||||||
export const OPEN_MODAL = "OPEN_MODAL";
|
export const OPEN_MODAL = 'OPEN_MODAL';
|
||||||
export const CLOSE_MODAL = "CLOSE_MODAL";
|
export const CLOSE_MODAL = 'CLOSE_MODAL';
|
||||||
export const SHOW_SNACKBAR = "SHOW_SNACKBAR";
|
export const SHOW_SNACKBAR = 'SHOW_SNACKBAR';
|
||||||
export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
|
export const REMOVE_SNACKBAR_SNACK = 'REMOVE_SNACKBAR_SNACK';
|
||||||
export const WINDOW_FOCUSED = "WINDOW_FOCUSED";
|
export const WINDOW_FOCUSED = 'WINDOW_FOCUSED';
|
||||||
export const DAEMON_READY = "DAEMON_READY";
|
export const DAEMON_READY = 'DAEMON_READY';
|
||||||
export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH";
|
export const DAEMON_VERSION_MATCH = 'DAEMON_VERSION_MATCH';
|
||||||
export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH";
|
export const DAEMON_VERSION_MISMATCH = 'DAEMON_VERSION_MISMATCH';
|
||||||
export const VOLUME_CHANGED = "VOLUME_CHANGED";
|
export const VOLUME_CHANGED = 'VOLUME_CHANGED';
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
export const CHANGE_AFTER_AUTH_PATH = "CHANGE_AFTER_AUTH_PATH";
|
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
|
||||||
export const WINDOW_SCROLLED = "WINDOW_SCROLLED";
|
export const WINDOW_SCROLLED = 'WINDOW_SCROLLED';
|
||||||
export const HISTORY_NAVIGATE = "HISTORY_NAVIGATE";
|
export const HISTORY_NAVIGATE = 'HISTORY_NAVIGATE';
|
||||||
|
|
||||||
// Upgrades
|
// Upgrades
|
||||||
export const UPGRADE_CANCELLED = "UPGRADE_CANCELLED";
|
export const UPGRADE_CANCELLED = 'UPGRADE_CANCELLED';
|
||||||
export const DOWNLOAD_UPGRADE = "DOWNLOAD_UPGRADE";
|
export const DOWNLOAD_UPGRADE = 'DOWNLOAD_UPGRADE';
|
||||||
export const UPGRADE_DOWNLOAD_STARTED = "UPGRADE_DOWNLOAD_STARTED";
|
export const UPGRADE_DOWNLOAD_STARTED = 'UPGRADE_DOWNLOAD_STARTED';
|
||||||
export const UPGRADE_DOWNLOAD_COMPLETED = "UPGRADE_DOWNLOAD_COMPLETED";
|
export const UPGRADE_DOWNLOAD_COMPLETED = 'UPGRADE_DOWNLOAD_COMPLETED';
|
||||||
export const UPGRADE_DOWNLOAD_PROGRESSED = "UPGRADE_DOWNLOAD_PROGRESSED";
|
export const UPGRADE_DOWNLOAD_PROGRESSED = 'UPGRADE_DOWNLOAD_PROGRESSED';
|
||||||
export const CHECK_UPGRADE_AVAILABLE = "CHECK_UPGRADE_AVAILABLE";
|
export const CHECK_UPGRADE_AVAILABLE = 'CHECK_UPGRADE_AVAILABLE';
|
||||||
export const CHECK_UPGRADE_START = "CHECK_UPGRADE_START";
|
export const CHECK_UPGRADE_START = 'CHECK_UPGRADE_START';
|
||||||
export const CHECK_UPGRADE_SUCCESS = "CHECK_UPGRADE_SUCCESS";
|
export const CHECK_UPGRADE_SUCCESS = 'CHECK_UPGRADE_SUCCESS';
|
||||||
export const CHECK_UPGRADE_FAIL = "CHECK_UPGRADE_FAIL";
|
export const CHECK_UPGRADE_FAIL = 'CHECK_UPGRADE_FAIL';
|
||||||
export const CHECK_UPGRADE_SUBSCRIBE = "CHECK_UPGRADE_SUBSCRIBE";
|
export const CHECK_UPGRADE_SUBSCRIBE = 'CHECK_UPGRADE_SUBSCRIBE';
|
||||||
export const UPDATE_VERSION = "UPDATE_VERSION";
|
export const UPDATE_VERSION = 'UPDATE_VERSION';
|
||||||
export const UPDATE_REMOTE_VERSION = "UPDATE_REMOTE_VERSION";
|
export const UPDATE_REMOTE_VERSION = 'UPDATE_REMOTE_VERSION';
|
||||||
export const SKIP_UPGRADE = "SKIP_UPGRADE";
|
export const SKIP_UPGRADE = 'SKIP_UPGRADE';
|
||||||
export const START_UPGRADE = "START_UPGRADE";
|
export const START_UPGRADE = 'START_UPGRADE';
|
||||||
|
|
||||||
// Wallet
|
// Wallet
|
||||||
export const GET_NEW_ADDRESS_STARTED = "GET_NEW_ADDRESS_STARTED";
|
export const GET_NEW_ADDRESS_STARTED = 'GET_NEW_ADDRESS_STARTED';
|
||||||
export const GET_NEW_ADDRESS_COMPLETED = "GET_NEW_ADDRESS_COMPLETED";
|
export const GET_NEW_ADDRESS_COMPLETED = 'GET_NEW_ADDRESS_COMPLETED';
|
||||||
export const FETCH_TRANSACTIONS_STARTED = "FETCH_TRANSACTIONS_STARTED";
|
export const FETCH_TRANSACTIONS_STARTED = 'FETCH_TRANSACTIONS_STARTED';
|
||||||
export const FETCH_TRANSACTIONS_COMPLETED = "FETCH_TRANSACTIONS_COMPLETED";
|
export const FETCH_TRANSACTIONS_COMPLETED = 'FETCH_TRANSACTIONS_COMPLETED';
|
||||||
export const UPDATE_BALANCE = "UPDATE_BALANCE";
|
export const UPDATE_BALANCE = 'UPDATE_BALANCE';
|
||||||
export const CHECK_ADDRESS_IS_MINE_STARTED = "CHECK_ADDRESS_IS_MINE_STARTED";
|
export const CHECK_ADDRESS_IS_MINE_STARTED = 'CHECK_ADDRESS_IS_MINE_STARTED';
|
||||||
export const CHECK_ADDRESS_IS_MINE_COMPLETED =
|
export const CHECK_ADDRESS_IS_MINE_COMPLETED = 'CHECK_ADDRESS_IS_MINE_COMPLETED';
|
||||||
"CHECK_ADDRESS_IS_MINE_COMPLETED";
|
export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT';
|
||||||
export const SET_DRAFT_TRANSACTION_AMOUNT = "SET_DRAFT_TRANSACTION_AMOUNT";
|
export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS';
|
||||||
export const SET_DRAFT_TRANSACTION_ADDRESS = "SET_DRAFT_TRANSACTION_ADDRESS";
|
export const SEND_TRANSACTION_STARTED = 'SEND_TRANSACTION_STARTED';
|
||||||
export const SEND_TRANSACTION_STARTED = "SEND_TRANSACTION_STARTED";
|
export const SEND_TRANSACTION_COMPLETED = 'SEND_TRANSACTION_COMPLETED';
|
||||||
export const SEND_TRANSACTION_COMPLETED = "SEND_TRANSACTION_COMPLETED";
|
export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED';
|
||||||
export const SEND_TRANSACTION_FAILED = "SEND_TRANSACTION_FAILED";
|
export const FETCH_BLOCK_SUCCESS = 'FETCH_BLOCK_SUCCESS';
|
||||||
export const FETCH_BLOCK_SUCCESS = "FETCH_BLOCK_SUCCESS";
|
export const SUPPORT_TRANSACTION_STARTED = 'SUPPORT_TRANSACTION_STARTED';
|
||||||
export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED";
|
export const SUPPORT_TRANSACTION_COMPLETED = 'SUPPORT_TRANSACTION_COMPLETED';
|
||||||
export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED";
|
export const SUPPORT_TRANSACTION_FAILED = 'SUPPORT_TRANSACTION_FAILED';
|
||||||
export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED";
|
|
||||||
|
|
||||||
// Claims
|
// Claims
|
||||||
export const FETCH_FEATURED_CONTENT_STARTED = "FETCH_FEATURED_CONTENT_STARTED";
|
export const FETCH_FEATURED_CONTENT_STARTED = 'FETCH_FEATURED_CONTENT_STARTED';
|
||||||
export const FETCH_FEATURED_CONTENT_COMPLETED =
|
export const FETCH_FEATURED_CONTENT_COMPLETED = 'FETCH_FEATURED_CONTENT_COMPLETED';
|
||||||
"FETCH_FEATURED_CONTENT_COMPLETED";
|
export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED';
|
||||||
export const RESOLVE_URIS_STARTED = "RESOLVE_URIS_STARTED";
|
export const RESOLVE_URIS_COMPLETED = 'RESOLVE_URIS_COMPLETED';
|
||||||
export const RESOLVE_URIS_COMPLETED = "RESOLVE_URIS_COMPLETED";
|
export const FETCH_CHANNEL_CLAIMS_STARTED = 'FETCH_CHANNEL_CLAIMS_STARTED';
|
||||||
export const FETCH_CHANNEL_CLAIMS_STARTED = "FETCH_CHANNEL_CLAIMS_STARTED";
|
export const FETCH_CHANNEL_CLAIMS_COMPLETED = 'FETCH_CHANNEL_CLAIMS_COMPLETED';
|
||||||
export const FETCH_CHANNEL_CLAIMS_COMPLETED = "FETCH_CHANNEL_CLAIMS_COMPLETED";
|
export const FETCH_CHANNEL_CLAIM_COUNT_STARTED = 'FETCH_CHANNEL_CLAIM_COUNT_STARTED';
|
||||||
export const FETCH_CHANNEL_CLAIM_COUNT_STARTED =
|
export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED = 'FETCH_CHANNEL_CLAIM_COUNT_COMPLETED';
|
||||||
"FETCH_CHANNEL_CLAIM_COUNT_STARTED";
|
export const FETCH_CLAIM_LIST_MINE_STARTED = 'FETCH_CLAIM_LIST_MINE_STARTED';
|
||||||
export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED =
|
export const FETCH_CLAIM_LIST_MINE_COMPLETED = 'FETCH_CLAIM_LIST_MINE_COMPLETED';
|
||||||
"FETCH_CHANNEL_CLAIM_COUNT_COMPLETED";
|
export const ABANDON_CLAIM_STARTED = 'ABANDON_CLAIM_STARTED';
|
||||||
export const FETCH_CLAIM_LIST_MINE_STARTED = "FETCH_CLAIM_LIST_MINE_STARTED";
|
export const ABANDON_CLAIM_SUCCEEDED = 'ABANDON_CLAIM_SUCCEEDED';
|
||||||
export const FETCH_CLAIM_LIST_MINE_COMPLETED =
|
export const FETCH_CHANNEL_LIST_MINE_STARTED = 'FETCH_CHANNEL_LIST_MINE_STARTED';
|
||||||
"FETCH_CLAIM_LIST_MINE_COMPLETED";
|
export const FETCH_CHANNEL_LIST_MINE_COMPLETED = 'FETCH_CHANNEL_LIST_MINE_COMPLETED';
|
||||||
export const ABANDON_CLAIM_STARTED = "ABANDON_CLAIM_STARTED";
|
export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED';
|
||||||
export const ABANDON_CLAIM_SUCCEEDED = "ABANDON_CLAIM_SUCCEEDED";
|
export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED';
|
||||||
export const FETCH_CHANNEL_LIST_MINE_STARTED =
|
export const PUBLISH_STARTED = 'PUBLISH_STARTED';
|
||||||
"FETCH_CHANNEL_LIST_MINE_STARTED";
|
export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED';
|
||||||
export const FETCH_CHANNEL_LIST_MINE_COMPLETED =
|
export const PUBLISH_FAILED = 'PUBLISH_FAILED';
|
||||||
"FETCH_CHANNEL_LIST_MINE_COMPLETED";
|
export const SET_PLAYING_URI = 'PLAY_URI';
|
||||||
export const CREATE_CHANNEL_STARTED = "CREATE_CHANNEL_STARTED";
|
|
||||||
export const CREATE_CHANNEL_COMPLETED = "CREATE_CHANNEL_COMPLETED";
|
|
||||||
export const PUBLISH_STARTED = "PUBLISH_STARTED";
|
|
||||||
export const PUBLISH_COMPLETED = "PUBLISH_COMPLETED";
|
|
||||||
export const PUBLISH_FAILED = "PUBLISH_FAILED";
|
|
||||||
export const SET_PLAYING_URI = "PLAY_URI";
|
|
||||||
|
|
||||||
// Files
|
// Files
|
||||||
export const FILE_LIST_STARTED = "FILE_LIST_STARTED";
|
export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
||||||
export const FILE_LIST_SUCCEEDED = "FILE_LIST_SUCCEEDED";
|
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
|
||||||
export const FETCH_FILE_INFO_STARTED = "FETCH_FILE_INFO_STARTED";
|
export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED';
|
||||||
export const FETCH_FILE_INFO_COMPLETED = "FETCH_FILE_INFO_COMPLETED";
|
export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED';
|
||||||
export const FETCH_COST_INFO_STARTED = "FETCH_COST_INFO_STARTED";
|
export const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED';
|
||||||
export const FETCH_COST_INFO_COMPLETED = "FETCH_COST_INFO_COMPLETED";
|
export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED';
|
||||||
export const LOADING_VIDEO_STARTED = "LOADING_VIDEO_STARTED";
|
export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED';
|
||||||
export const LOADING_VIDEO_COMPLETED = "LOADING_VIDEO_COMPLETED";
|
export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED';
|
||||||
export const LOADING_VIDEO_FAILED = "LOADING_VIDEO_FAILED";
|
export const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED';
|
||||||
export const DOWNLOADING_STARTED = "DOWNLOADING_STARTED";
|
export const DOWNLOADING_STARTED = 'DOWNLOADING_STARTED';
|
||||||
export const DOWNLOADING_PROGRESSED = "DOWNLOADING_PROGRESSED";
|
export const DOWNLOADING_PROGRESSED = 'DOWNLOADING_PROGRESSED';
|
||||||
export const DOWNLOADING_COMPLETED = "DOWNLOADING_COMPLETED";
|
export const DOWNLOADING_COMPLETED = 'DOWNLOADING_COMPLETED';
|
||||||
export const PLAY_VIDEO_STARTED = "PLAY_VIDEO_STARTED";
|
export const PLAY_VIDEO_STARTED = 'PLAY_VIDEO_STARTED';
|
||||||
export const FETCH_AVAILABILITY_STARTED = "FETCH_AVAILABILITY_STARTED";
|
export const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED';
|
||||||
export const FETCH_AVAILABILITY_COMPLETED = "FETCH_AVAILABILITY_COMPLETED";
|
export const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED';
|
||||||
export const FILE_DELETE = "FILE_DELETE";
|
export const FILE_DELETE = 'FILE_DELETE';
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
export const SEARCH_STARTED = "SEARCH_STARTED";
|
export const SEARCH_STARTED = 'SEARCH_STARTED';
|
||||||
export const SEARCH_COMPLETED = "SEARCH_COMPLETED";
|
export const SEARCH_COMPLETED = 'SEARCH_COMPLETED';
|
||||||
export const SEARCH_CANCELLED = "SEARCH_CANCELLED";
|
export const SEARCH_CANCELLED = 'SEARCH_CANCELLED';
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED";
|
export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED';
|
||||||
export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED";
|
export const CLIENT_SETTING_CHANGED = 'CLIENT_SETTING_CHANGED';
|
||||||
|
|
||||||
// User
|
// User
|
||||||
export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED";
|
export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED';
|
||||||
export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS";
|
export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS';
|
||||||
export const AUTHENTICATION_FAILURE = "AUTHENTICATION_FAILURE";
|
export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE';
|
||||||
export const USER_EMAIL_DECLINE = "USER_EMAIL_DECLINE";
|
export const USER_EMAIL_DECLINE = 'USER_EMAIL_DECLINE';
|
||||||
export const USER_EMAIL_NEW_STARTED = "USER_EMAIL_NEW_STARTED";
|
export const USER_EMAIL_NEW_STARTED = 'USER_EMAIL_NEW_STARTED';
|
||||||
export const USER_EMAIL_NEW_SUCCESS = "USER_EMAIL_NEW_SUCCESS";
|
export const USER_EMAIL_NEW_SUCCESS = 'USER_EMAIL_NEW_SUCCESS';
|
||||||
export const USER_EMAIL_NEW_EXISTS = "USER_EMAIL_NEW_EXISTS";
|
export const USER_EMAIL_NEW_EXISTS = 'USER_EMAIL_NEW_EXISTS';
|
||||||
export const USER_EMAIL_NEW_FAILURE = "USER_EMAIL_NEW_FAILURE";
|
export const USER_EMAIL_NEW_FAILURE = 'USER_EMAIL_NEW_FAILURE';
|
||||||
export const USER_EMAIL_VERIFY_STARTED = "USER_EMAIL_VERIFY_STARTED";
|
export const USER_EMAIL_VERIFY_STARTED = 'USER_EMAIL_VERIFY_STARTED';
|
||||||
export const USER_EMAIL_VERIFY_SUCCESS = "USER_EMAIL_VERIFY_SUCCESS";
|
export const USER_EMAIL_VERIFY_SUCCESS = 'USER_EMAIL_VERIFY_SUCCESS';
|
||||||
export const USER_EMAIL_VERIFY_FAILURE = "USER_EMAIL_VERIFY_FAILURE";
|
export const USER_EMAIL_VERIFY_FAILURE = 'USER_EMAIL_VERIFY_FAILURE';
|
||||||
export const USER_IDENTITY_VERIFY_STARTED = "USER_IDENTITY_VERIFY_STARTED";
|
export const USER_IDENTITY_VERIFY_STARTED = 'USER_IDENTITY_VERIFY_STARTED';
|
||||||
export const USER_IDENTITY_VERIFY_SUCCESS = "USER_IDENTITY_VERIFY_SUCCESS";
|
export const USER_IDENTITY_VERIFY_SUCCESS = 'USER_IDENTITY_VERIFY_SUCCESS';
|
||||||
export const USER_IDENTITY_VERIFY_FAILURE = "USER_IDENTITY_VERIFY_FAILURE";
|
export const USER_IDENTITY_VERIFY_FAILURE = 'USER_IDENTITY_VERIFY_FAILURE';
|
||||||
export const USER_FETCH_STARTED = "USER_FETCH_STARTED";
|
export const USER_FETCH_STARTED = 'USER_FETCH_STARTED';
|
||||||
export const USER_FETCH_SUCCESS = "USER_FETCH_SUCCESS";
|
export const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS';
|
||||||
export const USER_FETCH_FAILURE = "USER_FETCH_FAILURE";
|
export const USER_FETCH_FAILURE = 'USER_FETCH_FAILURE';
|
||||||
export const USER_INVITE_STATUS_FETCH_STARTED =
|
export const USER_INVITE_STATUS_FETCH_STARTED = 'USER_INVITE_STATUS_FETCH_STARTED';
|
||||||
"USER_INVITE_STATUS_FETCH_STARTED";
|
export const USER_INVITE_STATUS_FETCH_SUCCESS = 'USER_INVITE_STATUS_FETCH_SUCCESS';
|
||||||
export const USER_INVITE_STATUS_FETCH_SUCCESS =
|
export const USER_INVITE_STATUS_FETCH_FAILURE = 'USER_INVITE_STATUS_FETCH_FAILURE';
|
||||||
"USER_INVITE_STATUS_FETCH_SUCCESS";
|
export const USER_INVITE_NEW_STARTED = 'USER_INVITE_NEW_STARTED';
|
||||||
export const USER_INVITE_STATUS_FETCH_FAILURE =
|
export const USER_INVITE_NEW_SUCCESS = 'USER_INVITE_NEW_SUCCESS';
|
||||||
"USER_INVITE_STATUS_FETCH_FAILURE";
|
export const USER_INVITE_NEW_FAILURE = 'USER_INVITE_NEW_FAILURE';
|
||||||
export const USER_INVITE_NEW_STARTED = "USER_INVITE_NEW_STARTED";
|
export const FETCH_ACCESS_TOKEN_SUCCESS = 'FETCH_ACCESS_TOKEN_SUCCESS';
|
||||||
export const USER_INVITE_NEW_SUCCESS = "USER_INVITE_NEW_SUCCESS";
|
|
||||||
export const USER_INVITE_NEW_FAILURE = "USER_INVITE_NEW_FAILURE";
|
|
||||||
export const FETCH_ACCESS_TOKEN_SUCCESS = "FETCH_ACCESS_TOKEN_SUCCESS";
|
|
||||||
|
|
||||||
// Rewards
|
// Rewards
|
||||||
export const FETCH_REWARDS_STARTED = "FETCH_REWARDS_STARTED";
|
export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED';
|
||||||
export const FETCH_REWARDS_COMPLETED = "FETCH_REWARDS_COMPLETED";
|
export const FETCH_REWARDS_COMPLETED = 'FETCH_REWARDS_COMPLETED';
|
||||||
export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED";
|
export const CLAIM_REWARD_STARTED = 'CLAIM_REWARD_STARTED';
|
||||||
export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS";
|
export const CLAIM_REWARD_SUCCESS = 'CLAIM_REWARD_SUCCESS';
|
||||||
export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE";
|
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';
|
||||||
|
|
||||||
// ShapeShift
|
// ShapeShift
|
||||||
export const GET_SUPPORTED_COINS_START = "GET_SUPPORTED_COINS_START";
|
export const GET_SUPPORTED_COINS_START = 'GET_SUPPORTED_COINS_START';
|
||||||
export const GET_SUPPORTED_COINS_SUCCESS = "GET_SUPPORTED_COINS_SUCCESS";
|
export const GET_SUPPORTED_COINS_SUCCESS = 'GET_SUPPORTED_COINS_SUCCESS';
|
||||||
export const GET_SUPPORTED_COINS_FAIL = "GET_SUPPORTED_COINS_FAIL";
|
export const GET_SUPPORTED_COINS_FAIL = 'GET_SUPPORTED_COINS_FAIL';
|
||||||
export const GET_COIN_STATS_START = "GET_COIN_STATS_START";
|
export const GET_COIN_STATS_START = 'GET_COIN_STATS_START';
|
||||||
export const GET_COIN_STATS_SUCCESS = "GET_COIN_STATS_SUCCESS";
|
export const GET_COIN_STATS_SUCCESS = 'GET_COIN_STATS_SUCCESS';
|
||||||
export const GET_COIN_STATS_FAIL = "GET_COIN_STATS_FAIL";
|
export const GET_COIN_STATS_FAIL = 'GET_COIN_STATS_FAIL';
|
||||||
export const PREPARE_SHAPE_SHIFT_START = "PREPARE_SHAPE_SHIFT_START";
|
export const PREPARE_SHAPE_SHIFT_START = 'PREPARE_SHAPE_SHIFT_START';
|
||||||
export const PREPARE_SHAPE_SHIFT_SUCCESS = "PREPARE_SHAPE_SHIFT_SUCCESS";
|
export const PREPARE_SHAPE_SHIFT_SUCCESS = 'PREPARE_SHAPE_SHIFT_SUCCESS';
|
||||||
export const PREPARE_SHAPE_SHIFT_FAIL = "PREPARE_SHAPE_SHIFT_FAIL";
|
export const PREPARE_SHAPE_SHIFT_FAIL = 'PREPARE_SHAPE_SHIFT_FAIL';
|
||||||
export const GET_ACTIVE_SHIFT_START = "GET_ACTIVE_SHIFT_START";
|
export const GET_ACTIVE_SHIFT_START = 'GET_ACTIVE_SHIFT_START';
|
||||||
export const GET_ACTIVE_SHIFT_SUCCESS = "GET_ACTIVE_SHIFT_SUCCESS";
|
export const GET_ACTIVE_SHIFT_SUCCESS = 'GET_ACTIVE_SHIFT_SUCCESS';
|
||||||
export const GET_ACTIVE_SHIFT_FAIL = "GET_ACTIVE_SHIFT_FAIL";
|
export const GET_ACTIVE_SHIFT_FAIL = 'GET_ACTIVE_SHIFT_FAIL';
|
||||||
export const CLEAR_SHAPE_SHIFT = "CLEAR_SHAPE_SHIFT";
|
export const CLEAR_SHAPE_SHIFT = 'CLEAR_SHAPE_SHIFT';
|
||||||
|
|
||||||
// Subscriptions
|
// Subscriptions
|
||||||
export const CHANNEL_SUBSCRIBE = "CHANNEL_SUBSCRIBE";
|
export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE';
|
||||||
export const CHANNEL_UNSUBSCRIBE = "CHANNEL_UNSUBSCRIBE";
|
export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE';
|
||||||
export const HAS_FETCHED_SUBSCRIPTIONS = "HAS_FETCHED_SUBSCRIPTIONS";
|
export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export const FEATURED = "rocket";
|
export const FEATURED = 'rocket';
|
||||||
export const LOCAL = "folder";
|
export const LOCAL = 'folder';
|
||||||
export const FILE = "file";
|
export const FILE = 'file';
|
||||||
export const HISTORY = "history";
|
export const HISTORY = 'history';
|
||||||
export const HELP_CIRCLE = "question-circle";
|
export const HELP_CIRCLE = 'question-circle';
|
||||||
|
|
|
@ -1,187 +1,187 @@
|
||||||
const LANGUAGES = {
|
const LANGUAGES = {
|
||||||
aa: ["Afar", "Afar"],
|
aa: ['Afar', 'Afar'],
|
||||||
ab: ["Abkhazian", "Аҧсуа"],
|
ab: ['Abkhazian', 'Аҧсуа'],
|
||||||
af: ["Afrikaans", "Afrikaans"],
|
af: ['Afrikaans', 'Afrikaans'],
|
||||||
ak: ["Akan", "Akana"],
|
ak: ['Akan', 'Akana'],
|
||||||
am: ["Amharic", "አማርኛ"],
|
am: ['Amharic', 'አማርኛ'],
|
||||||
an: ["Aragonese", "Aragonés"],
|
an: ['Aragonese', 'Aragonés'],
|
||||||
ar: ["Arabic", "العربية"],
|
ar: ['Arabic', 'العربية'],
|
||||||
as: ["Assamese", "অসমীয়া"],
|
as: ['Assamese', 'অসমীয়া'],
|
||||||
av: ["Avar", "Авар"],
|
av: ['Avar', 'Авар'],
|
||||||
ay: ["Aymara", "Aymar"],
|
ay: ['Aymara', 'Aymar'],
|
||||||
az: ["Azerbaijani", "Azərbaycanca / آذربايجان"],
|
az: ['Azerbaijani', 'Azərbaycanca / آذربايجان'],
|
||||||
ba: ["Bashkir", "Башҡорт"],
|
ba: ['Bashkir', 'Башҡорт'],
|
||||||
be: ["Belarusian", "Беларуская"],
|
be: ['Belarusian', 'Беларуская'],
|
||||||
bg: ["Bulgarian", "Български"],
|
bg: ['Bulgarian', 'Български'],
|
||||||
bh: ["Bihari", "भोजपुरी"],
|
bh: ['Bihari', 'भोजपुरी'],
|
||||||
bi: ["Bislama", "Bislama"],
|
bi: ['Bislama', 'Bislama'],
|
||||||
bm: ["Bambara", "Bamanankan"],
|
bm: ['Bambara', 'Bamanankan'],
|
||||||
bn: ["Bengali", "বাংলা"],
|
bn: ['Bengali', 'বাংলা'],
|
||||||
bo: ["Tibetan", "བོད་ཡིག / Bod skad"],
|
bo: ['Tibetan', 'བོད་ཡིག / Bod skad'],
|
||||||
br: ["Breton", "Brezhoneg"],
|
br: ['Breton', 'Brezhoneg'],
|
||||||
bs: ["Bosnian", "Bosanski"],
|
bs: ['Bosnian', 'Bosanski'],
|
||||||
ca: ["Catalan", "Català"],
|
ca: ['Catalan', 'Català'],
|
||||||
ce: ["Chechen", "Нохчийн"],
|
ce: ['Chechen', 'Нохчийн'],
|
||||||
ch: ["Chamorro", "Chamoru"],
|
ch: ['Chamorro', 'Chamoru'],
|
||||||
co: ["Corsican", "Corsu"],
|
co: ['Corsican', 'Corsu'],
|
||||||
cr: ["Cree", "Nehiyaw"],
|
cr: ['Cree', 'Nehiyaw'],
|
||||||
cs: ["Czech", "Česky"],
|
cs: ['Czech', 'Česky'],
|
||||||
cu: ["Old Church Slavonic / Old Bulgarian", "словѣньскъ / slověnĭskŭ"],
|
cu: ['Old Church Slavonic / Old Bulgarian', 'словѣньскъ / slověnĭskŭ'],
|
||||||
cv: ["Chuvash", "Чăваш"],
|
cv: ['Chuvash', 'Чăваш'],
|
||||||
cy: ["Welsh", "Cymraeg"],
|
cy: ['Welsh', 'Cymraeg'],
|
||||||
da: ["Danish", "Dansk"],
|
da: ['Danish', 'Dansk'],
|
||||||
de: ["German", "Deutsch"],
|
de: ['German', 'Deutsch'],
|
||||||
dv: ["Divehi", "ދިވެހިބަސް"],
|
dv: ['Divehi', 'ދިވެހިބަސް'],
|
||||||
dz: ["Dzongkha", "ཇོང་ཁ"],
|
dz: ['Dzongkha', 'ཇོང་ཁ'],
|
||||||
ee: ["Ewe", "Ɛʋɛ"],
|
ee: ['Ewe', 'Ɛʋɛ'],
|
||||||
el: ["Greek", "Ελληνικά"],
|
el: ['Greek', 'Ελληνικά'],
|
||||||
en: ["English", "English"],
|
en: ['English', 'English'],
|
||||||
eo: ["Esperanto", "Esperanto"],
|
eo: ['Esperanto', 'Esperanto'],
|
||||||
es: ["Spanish", "Español"],
|
es: ['Spanish', 'Español'],
|
||||||
et: ["Estonian", "Eesti"],
|
et: ['Estonian', 'Eesti'],
|
||||||
eu: ["Basque", "Euskara"],
|
eu: ['Basque', 'Euskara'],
|
||||||
fa: ["Persian", "فارسی"],
|
fa: ['Persian', 'فارسی'],
|
||||||
ff: ["Peul", "Fulfulde"],
|
ff: ['Peul', 'Fulfulde'],
|
||||||
fi: ["Finnish", "Suomi"],
|
fi: ['Finnish', 'Suomi'],
|
||||||
fj: ["Fijian", "Na Vosa Vakaviti"],
|
fj: ['Fijian', 'Na Vosa Vakaviti'],
|
||||||
fo: ["Faroese", "Føroyskt"],
|
fo: ['Faroese', 'Føroyskt'],
|
||||||
fr: ["French", "Français"],
|
fr: ['French', 'Français'],
|
||||||
fy: ["West Frisian", "Frysk"],
|
fy: ['West Frisian', 'Frysk'],
|
||||||
ga: ["Irish", "Gaeilge"],
|
ga: ['Irish', 'Gaeilge'],
|
||||||
gd: ["Scottish Gaelic", "Gàidhlig"],
|
gd: ['Scottish Gaelic', 'Gàidhlig'],
|
||||||
gl: ["Galician", "Galego"],
|
gl: ['Galician', 'Galego'],
|
||||||
gn: ["Guarani", "Avañe'ẽ"],
|
gn: ['Guarani', "Avañe'ẽ"],
|
||||||
gu: ["Gujarati", "ગુજરાતી"],
|
gu: ['Gujarati', 'ગુજરાતી'],
|
||||||
gv: ["Manx", "Gaelg"],
|
gv: ['Manx', 'Gaelg'],
|
||||||
ha: ["Hausa", "هَوُسَ"],
|
ha: ['Hausa', 'هَوُسَ'],
|
||||||
he: ["Hebrew", "עברית"],
|
he: ['Hebrew', 'עברית'],
|
||||||
hi: ["Hindi", "हिन्दी"],
|
hi: ['Hindi', 'हिन्दी'],
|
||||||
ho: ["Hiri Motu", "Hiri Motu"],
|
ho: ['Hiri Motu', 'Hiri Motu'],
|
||||||
hr: ["Croatian", "Hrvatski"],
|
hr: ['Croatian', 'Hrvatski'],
|
||||||
ht: ["Haitian", "Krèyol ayisyen"],
|
ht: ['Haitian', 'Krèyol ayisyen'],
|
||||||
hu: ["Hungarian", "Magyar"],
|
hu: ['Hungarian', 'Magyar'],
|
||||||
hy: ["Armenian", "Հայերեն"],
|
hy: ['Armenian', 'Հայերեն'],
|
||||||
hz: ["Herero", "Otsiherero"],
|
hz: ['Herero', 'Otsiherero'],
|
||||||
ia: ["Interlingua", "Interlingua"],
|
ia: ['Interlingua', 'Interlingua'],
|
||||||
id: ["Indonesian", "Bahasa Indonesia"],
|
id: ['Indonesian', 'Bahasa Indonesia'],
|
||||||
ie: ["Interlingue", "Interlingue"],
|
ie: ['Interlingue', 'Interlingue'],
|
||||||
ig: ["Igbo", "Igbo"],
|
ig: ['Igbo', 'Igbo'],
|
||||||
ii: ["Sichuan Yi", "ꆇꉙ / 四川彝语"],
|
ii: ['Sichuan Yi', 'ꆇꉙ / 四川彝语'],
|
||||||
ik: ["Inupiak", "Iñupiak"],
|
ik: ['Inupiak', 'Iñupiak'],
|
||||||
io: ["Ido", "Ido"],
|
io: ['Ido', 'Ido'],
|
||||||
is: ["Icelandic", "Íslenska"],
|
is: ['Icelandic', 'Íslenska'],
|
||||||
it: ["Italian", "Italiano"],
|
it: ['Italian', 'Italiano'],
|
||||||
iu: ["Inuktitut", "ᐃᓄᒃᑎᑐᑦ"],
|
iu: ['Inuktitut', 'ᐃᓄᒃᑎᑐᑦ'],
|
||||||
ja: ["Japanese", "日本語"],
|
ja: ['Japanese', '日本語'],
|
||||||
jv: ["Javanese", "Basa Jawa"],
|
jv: ['Javanese', 'Basa Jawa'],
|
||||||
ka: ["Georgian", "ქართული"],
|
ka: ['Georgian', 'ქართული'],
|
||||||
kg: ["Kongo", "KiKongo"],
|
kg: ['Kongo', 'KiKongo'],
|
||||||
ki: ["Kikuyu", "Gĩkũyũ"],
|
ki: ['Kikuyu', 'Gĩkũyũ'],
|
||||||
kj: ["Kuanyama", "Kuanyama"],
|
kj: ['Kuanyama', 'Kuanyama'],
|
||||||
kk: ["Kazakh", "Қазақша"],
|
kk: ['Kazakh', 'Қазақша'],
|
||||||
kl: ["Greenlandic", "Kalaallisut"],
|
kl: ['Greenlandic', 'Kalaallisut'],
|
||||||
km: ["Cambodian", "ភាសាខ្មែរ"],
|
km: ['Cambodian', 'ភាសាខ្មែរ'],
|
||||||
kn: ["Kannada", "ಕನ್ನಡ"],
|
kn: ['Kannada', 'ಕನ್ನಡ'],
|
||||||
ko: ["Korean", "한국어"],
|
ko: ['Korean', '한국어'],
|
||||||
kr: ["Kanuri", "Kanuri"],
|
kr: ['Kanuri', 'Kanuri'],
|
||||||
ks: ["Kashmiri", "कश्मीरी / كشميري"],
|
ks: ['Kashmiri', 'कश्मीरी / كشميري'],
|
||||||
ku: ["Kurdish", "Kurdî / كوردی"],
|
ku: ['Kurdish', 'Kurdî / كوردی'],
|
||||||
kv: ["Komi", "Коми"],
|
kv: ['Komi', 'Коми'],
|
||||||
kw: ["Cornish", "Kernewek"],
|
kw: ['Cornish', 'Kernewek'],
|
||||||
ky: ["Kirghiz", "Kırgızca / Кыргызча"],
|
ky: ['Kirghiz', 'Kırgızca / Кыргызча'],
|
||||||
la: ["Latin", "Latina"],
|
la: ['Latin', 'Latina'],
|
||||||
lb: ["Luxembourgish", "Lëtzebuergesch"],
|
lb: ['Luxembourgish', 'Lëtzebuergesch'],
|
||||||
lg: ["Ganda", "Luganda"],
|
lg: ['Ganda', 'Luganda'],
|
||||||
li: ["Limburgian", "Limburgs"],
|
li: ['Limburgian', 'Limburgs'],
|
||||||
ln: ["Lingala", "Lingála"],
|
ln: ['Lingala', 'Lingála'],
|
||||||
lo: ["Laotian", "ລາວ / Pha xa lao"],
|
lo: ['Laotian', 'ລາວ / Pha xa lao'],
|
||||||
lt: ["Lithuanian", "Lietuvių"],
|
lt: ['Lithuanian', 'Lietuvių'],
|
||||||
lv: ["Latvian", "Latviešu"],
|
lv: ['Latvian', 'Latviešu'],
|
||||||
mg: ["Malagasy", "Malagasy"],
|
mg: ['Malagasy', 'Malagasy'],
|
||||||
mh: ["Marshallese", "Kajin Majel / Ebon"],
|
mh: ['Marshallese', 'Kajin Majel / Ebon'],
|
||||||
mi: ["Maori", "Māori"],
|
mi: ['Maori', 'Māori'],
|
||||||
mk: ["Macedonian", "Македонски"],
|
mk: ['Macedonian', 'Македонски'],
|
||||||
ml: ["Malayalam", "മലയാളം"],
|
ml: ['Malayalam', 'മലയാളം'],
|
||||||
mn: ["Mongolian", "Монгол"],
|
mn: ['Mongolian', 'Монгол'],
|
||||||
mo: ["Moldovan", "Moldovenească"],
|
mo: ['Moldovan', 'Moldovenească'],
|
||||||
mr: ["Marathi", "मराठी"],
|
mr: ['Marathi', 'मराठी'],
|
||||||
ms: ["Malay", "Bahasa Melayu"],
|
ms: ['Malay', 'Bahasa Melayu'],
|
||||||
mt: ["Maltese", "bil-Malti"],
|
mt: ['Maltese', 'bil-Malti'],
|
||||||
my: ["Burmese", "Myanmasa"],
|
my: ['Burmese', 'Myanmasa'],
|
||||||
na: ["Nauruan", "Dorerin Naoero"],
|
na: ['Nauruan', 'Dorerin Naoero'],
|
||||||
nd: ["North Ndebele", "Sindebele"],
|
nd: ['North Ndebele', 'Sindebele'],
|
||||||
ne: ["Nepali", "नेपाली"],
|
ne: ['Nepali', 'नेपाली'],
|
||||||
ng: ["Ndonga", "Oshiwambo"],
|
ng: ['Ndonga', 'Oshiwambo'],
|
||||||
nl: ["Dutch", "Nederlands"],
|
nl: ['Dutch', 'Nederlands'],
|
||||||
nn: ["Norwegian Nynorsk", "Norsk (nynorsk)"],
|
nn: ['Norwegian Nynorsk', 'Norsk (nynorsk)'],
|
||||||
no: ["Norwegian", "Norsk (bokmål / riksmål)"],
|
no: ['Norwegian', 'Norsk (bokmål / riksmål)'],
|
||||||
nr: ["South Ndebele", "isiNdebele"],
|
nr: ['South Ndebele', 'isiNdebele'],
|
||||||
nv: ["Navajo", "Diné bizaad"],
|
nv: ['Navajo', 'Diné bizaad'],
|
||||||
ny: ["Chichewa", "Chi-Chewa"],
|
ny: ['Chichewa', 'Chi-Chewa'],
|
||||||
oc: ["Occitan", "Occitan"],
|
oc: ['Occitan', 'Occitan'],
|
||||||
oj: ["Ojibwa", "ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin"],
|
oj: ['Ojibwa', 'ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin'],
|
||||||
om: ["Oromo", "Oromoo"],
|
om: ['Oromo', 'Oromoo'],
|
||||||
or: ["Oriya", "ଓଡ଼ିଆ"],
|
or: ['Oriya', 'ଓଡ଼ିଆ'],
|
||||||
os: ["Ossetian / Ossetic", "Иронау"],
|
os: ['Ossetian / Ossetic', 'Иронау'],
|
||||||
pa: ["Panjabi / Punjabi", "ਪੰਜਾਬੀ / पंजाबी / پنجابي"],
|
pa: ['Panjabi / Punjabi', 'ਪੰਜਾਬੀ / पंजाबी / پنجابي'],
|
||||||
pi: ["Pali", "Pāli / पाऴि"],
|
pi: ['Pali', 'Pāli / पाऴि'],
|
||||||
pl: ["Polish", "Polski"],
|
pl: ['Polish', 'Polski'],
|
||||||
ps: ["Pashto", "پښتو"],
|
ps: ['Pashto', 'پښتو'],
|
||||||
pt: ["Portuguese", "Português"],
|
pt: ['Portuguese', 'Português'],
|
||||||
qu: ["Quechua", "Runa Simi"],
|
qu: ['Quechua', 'Runa Simi'],
|
||||||
rm: ["Raeto Romance", "Rumantsch"],
|
rm: ['Raeto Romance', 'Rumantsch'],
|
||||||
rn: ["Kirundi", "Kirundi"],
|
rn: ['Kirundi', 'Kirundi'],
|
||||||
ro: ["Romanian", "Română"],
|
ro: ['Romanian', 'Română'],
|
||||||
ru: ["Russian", "Русский"],
|
ru: ['Russian', 'Русский'],
|
||||||
rw: ["Rwandi", "Kinyarwandi"],
|
rw: ['Rwandi', 'Kinyarwandi'],
|
||||||
sa: ["Sanskrit", "संस्कृतम्"],
|
sa: ['Sanskrit', 'संस्कृतम्'],
|
||||||
sc: ["Sardinian", "Sardu"],
|
sc: ['Sardinian', 'Sardu'],
|
||||||
sd: ["Sindhi", "सिनधि"],
|
sd: ['Sindhi', 'सिनधि'],
|
||||||
se: ["Northern Sami", "Sámegiella"],
|
se: ['Northern Sami', 'Sámegiella'],
|
||||||
sg: ["Sango", "Sängö"],
|
sg: ['Sango', 'Sängö'],
|
||||||
sh: ["Serbo-Croatian", "Srpskohrvatski / Српскохрватски"],
|
sh: ['Serbo-Croatian', 'Srpskohrvatski / Српскохрватски'],
|
||||||
si: ["Sinhalese", "සිංහල"],
|
si: ['Sinhalese', 'සිංහල'],
|
||||||
sk: ["Slovak", "Slovenčina"],
|
sk: ['Slovak', 'Slovenčina'],
|
||||||
sl: ["Slovenian", "Slovenščina"],
|
sl: ['Slovenian', 'Slovenščina'],
|
||||||
sm: ["Samoan", "Gagana Samoa"],
|
sm: ['Samoan', 'Gagana Samoa'],
|
||||||
sn: ["Shona", "chiShona"],
|
sn: ['Shona', 'chiShona'],
|
||||||
so: ["Somalia", "Soomaaliga"],
|
so: ['Somalia', 'Soomaaliga'],
|
||||||
sq: ["Albanian", "Shqip"],
|
sq: ['Albanian', 'Shqip'],
|
||||||
sr: ["Serbian", "Српски"],
|
sr: ['Serbian', 'Српски'],
|
||||||
ss: ["Swati", "SiSwati"],
|
ss: ['Swati', 'SiSwati'],
|
||||||
st: ["Southern Sotho", "Sesotho"],
|
st: ['Southern Sotho', 'Sesotho'],
|
||||||
su: ["Sundanese", "Basa Sunda"],
|
su: ['Sundanese', 'Basa Sunda'],
|
||||||
sv: ["Swedish", "Svenska"],
|
sv: ['Swedish', 'Svenska'],
|
||||||
sw: ["Swahili", "Kiswahili"],
|
sw: ['Swahili', 'Kiswahili'],
|
||||||
ta: ["Tamil", "தமிழ்"],
|
ta: ['Tamil', 'தமிழ்'],
|
||||||
te: ["Telugu", "తెలుగు"],
|
te: ['Telugu', 'తెలుగు'],
|
||||||
tg: ["Tajik", "Тоҷикӣ"],
|
tg: ['Tajik', 'Тоҷикӣ'],
|
||||||
th: ["Thai", "ไทย / Phasa Thai"],
|
th: ['Thai', 'ไทย / Phasa Thai'],
|
||||||
ti: ["Tigrinya", "ትግርኛ"],
|
ti: ['Tigrinya', 'ትግርኛ'],
|
||||||
tk: ["Turkmen", "Туркмен / تركمن"],
|
tk: ['Turkmen', 'Туркмен / تركمن'],
|
||||||
tl: ["Tagalog / Filipino", "Tagalog"],
|
tl: ['Tagalog / Filipino', 'Tagalog'],
|
||||||
tn: ["Tswana", "Setswana"],
|
tn: ['Tswana', 'Setswana'],
|
||||||
to: ["Tonga", "Lea Faka-Tonga"],
|
to: ['Tonga', 'Lea Faka-Tonga'],
|
||||||
tr: ["Turkish", "Türkçe"],
|
tr: ['Turkish', 'Türkçe'],
|
||||||
ts: ["Tsonga", "Xitsonga"],
|
ts: ['Tsonga', 'Xitsonga'],
|
||||||
tt: ["Tatar", "Tatarça"],
|
tt: ['Tatar', 'Tatarça'],
|
||||||
tw: ["Twi", "Twi"],
|
tw: ['Twi', 'Twi'],
|
||||||
ty: ["Tahitian", "Reo Mā`ohi"],
|
ty: ['Tahitian', 'Reo Mā`ohi'],
|
||||||
ug: ["Uyghur", "Uyƣurqə / ئۇيغۇرچە"],
|
ug: ['Uyghur', 'Uyƣurqə / ئۇيغۇرچە'],
|
||||||
uk: ["Ukrainian", "Українська"],
|
uk: ['Ukrainian', 'Українська'],
|
||||||
ur: ["Urdu", "اردو"],
|
ur: ['Urdu', 'اردو'],
|
||||||
uz: ["Uzbek", "Ўзбек"],
|
uz: ['Uzbek', 'Ўзбек'],
|
||||||
ve: ["Venda", "Tshivenḓa"],
|
ve: ['Venda', 'Tshivenḓa'],
|
||||||
vi: ["Vietnamese", "Tiếng Việt"],
|
vi: ['Vietnamese', 'Tiếng Việt'],
|
||||||
vo: ["Volapük", "Volapük"],
|
vo: ['Volapük', 'Volapük'],
|
||||||
wa: ["Walloon", "Walon"],
|
wa: ['Walloon', 'Walon'],
|
||||||
wo: ["Wolof", "Wollof"],
|
wo: ['Wolof', 'Wollof'],
|
||||||
xh: ["Xhosa", "isiXhosa"],
|
xh: ['Xhosa', 'isiXhosa'],
|
||||||
yi: ["Yiddish", "ייִדיש"],
|
yi: ['Yiddish', 'ייִדיש'],
|
||||||
yo: ["Yoruba", "Yorùbá"],
|
yo: ['Yoruba', 'Yorùbá'],
|
||||||
za: ["Zhuang", "Cuengh / Tôô / 壮语"],
|
za: ['Zhuang', 'Cuengh / Tôô / 壮语'],
|
||||||
zh: ["Chinese", "中文"],
|
zh: ['Chinese', '中文'],
|
||||||
zu: ["Zulu", "isiZulu"],
|
zu: ['Zulu', 'isiZulu'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LANGUAGES;
|
export default LANGUAGES;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
export const CONFIRM_FILE_REMOVE = "confirmFileRemove";
|
export const CONFIRM_FILE_REMOVE = 'confirmFileRemove';
|
||||||
export const INCOMPATIBLE_DAEMON = "incompatibleDaemon";
|
export const INCOMPATIBLE_DAEMON = 'incompatibleDaemon';
|
||||||
export const FILE_TIMEOUT = "file_timeout";
|
export const FILE_TIMEOUT = 'file_timeout';
|
||||||
export const DOWNLOADING = "downloading";
|
export const DOWNLOADING = 'downloading';
|
||||||
export const ERROR = "error";
|
export const ERROR = 'error';
|
||||||
export const INSUFFICIENT_CREDITS = "insufficient_credits";
|
export const INSUFFICIENT_CREDITS = 'insufficient_credits';
|
||||||
export const UPGRADE = "upgrade";
|
export const UPGRADE = 'upgrade';
|
||||||
export const WELCOME = "welcome";
|
export const WELCOME = 'welcome';
|
||||||
export const EMAIL_COLLECTION = "email_collection";
|
export const EMAIL_COLLECTION = 'email_collection';
|
||||||
export const FIRST_REWARD = "first_reward";
|
export const FIRST_REWARD = 'first_reward';
|
||||||
export const AUTHENTICATION_FAILURE = "auth_failure";
|
export const AUTHENTICATION_FAILURE = 'auth_failure';
|
||||||
export const TRANSACTION_FAILED = "transaction_failed";
|
export const TRANSACTION_FAILED = 'transaction_failed';
|
||||||
export const REWARD_APPROVAL_REQUIRED = "reward_approval_required";
|
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
|
||||||
export const AFFIRM_PURCHASE = "affirm_purchase";
|
export const AFFIRM_PURCHASE = 'affirm_purchase';
|
||||||
export const CONFIRM_CLAIM_REVOKE = "confirmClaimRevoke";
|
export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke';
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/* 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';
|
||||||
export const LANGUAGE = "language";
|
export const LANGUAGE = 'language';
|
||||||
export const SHOW_NSFW = "showNsfw";
|
export const SHOW_NSFW = 'showNsfw';
|
||||||
export const SHOW_UNAVAILABLE = "showUnavailable";
|
export const SHOW_UNAVAILABLE = 'showUnavailable';
|
||||||
export const INSTANT_PURCHASE_ENABLED = "instantPurchaseEnabled";
|
export const INSTANT_PURCHASE_ENABLED = 'instantPurchaseEnabled';
|
||||||
export const INSTANT_PURCHASE_MAX = "instantPurchaseMax";
|
export const INSTANT_PURCHASE_MAX = 'instantPurchaseMax';
|
||||||
export const THEME = "theme";
|
export const THEME = 'theme';
|
||||||
export const THEMES = "themes";
|
export const THEMES = 'themes';
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export const NO_DEPOSITS = "no_deposits";
|
export const NO_DEPOSITS = 'no_deposits';
|
||||||
export const RECEIVED = "received";
|
export const RECEIVED = 'received';
|
||||||
export const COMPLETE = "complete";
|
export const COMPLETE = 'complete';
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export const TIP = "tip";
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export const TIP = 'tip';
|
||||||
|
|
2
src/renderer/flow-typed/reselect.js
vendored
2
src/renderer/flow-typed/reselect.js
vendored
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
declare module 'reselect' {
|
declare module 'reselect' {
|
||||||
declare module.exports: any;
|
declare module.exports: any;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,87 +1,71 @@
|
||||||
import React from "react";
|
/* eslint-disable react/jsx-filename-extension */
|
||||||
import ReactDOM from "react-dom";
|
import React from 'react';
|
||||||
import App from "component/app/index.js";
|
import ReactDOM from 'react-dom';
|
||||||
import SnackBar from "component/snackBar";
|
import App from 'component/app';
|
||||||
import { Provider } from "react-redux";
|
import SnackBar from 'component/snackBar';
|
||||||
import store from "store.js";
|
import { Provider } from 'react-redux';
|
||||||
import SplashScreen from "component/splash";
|
import store from 'store';
|
||||||
import { doDaemonReady } from "redux/actions/app";
|
import SplashScreen from 'component/splash';
|
||||||
import { doNavigate } from "redux/actions/navigation";
|
import { doDaemonReady } from 'redux/actions/app';
|
||||||
import { doDownloadLanguages } from "redux/actions/settings";
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import * as types from "constants/action_types";
|
import { doDownloadLanguages } from 'redux/actions/settings';
|
||||||
import amplitude from "amplitude-js";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbry from "lbry";
|
import amplitude from 'amplitude-js';
|
||||||
import "scss/all.scss";
|
import lbry from 'lbry';
|
||||||
|
import 'scss/all.scss';
|
||||||
|
import { ipcRenderer, remote, shell } from 'electron';
|
||||||
|
|
||||||
const env = process.env.NODE_ENV || "production";
|
const { contextMenu } = remote.require('./main.js');
|
||||||
const { remote, ipcRenderer, shell } = require("electron");
|
|
||||||
|
|
||||||
const contextMenu = remote.require("./main.js").contextMenu;
|
window.addEventListener('contextmenu', event => {
|
||||||
const app = require("./app");
|
|
||||||
|
|
||||||
// Workaround for https://github.com/electron-userland/electron-webpack/issues/52
|
|
||||||
if (process.env.NODE_ENV !== "development") {
|
|
||||||
window.staticResourcesPath = require("path")
|
|
||||||
.join(remote.app.getAppPath(), "../static")
|
|
||||||
.replace(/\\/g, "\\\\");
|
|
||||||
} else {
|
|
||||||
window.staticResourcesPath = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("contextmenu", event => {
|
|
||||||
contextMenu.showContextMenu(
|
contextMenu.showContextMenu(
|
||||||
remote.getCurrentWindow(),
|
remote.getCurrentWindow(),
|
||||||
event.x,
|
event.x,
|
||||||
event.y,
|
event.y,
|
||||||
env === "development"
|
app.env === 'development'
|
||||||
);
|
);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on("open-uri-requested", (event, uri) => {
|
ipcRenderer.on('open-uri-requested', (event, uri) => {
|
||||||
if (uri && uri.startsWith("lbry://")) {
|
if (uri && uri.startsWith('lbry://')) {
|
||||||
app.store.dispatch(doNavigate("/show", { uri }));
|
app.store.dispatch(doNavigate('/show', { uri }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on("open-menu", (event, uri) => {
|
ipcRenderer.on('open-menu', (event, uri) => {
|
||||||
if (uri && uri.startsWith("/help")) {
|
if (uri && uri.startsWith('/help')) {
|
||||||
app.store.dispatch(doNavigate("/help"));
|
app.store.dispatch(doNavigate('/help'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const dock = remote.app.dock;
|
const { dock } = remote.app;
|
||||||
|
|
||||||
ipcRenderer.on("window-is-focused", (event, data) => {
|
ipcRenderer.on('window-is-focused', () => {
|
||||||
if (!dock) return;
|
if (!dock) return;
|
||||||
app.store.dispatch({ type: types.WINDOW_FOCUSED });
|
app.store.dispatch({ type: ACTIONS.WINDOW_FOCUSED });
|
||||||
dock.setBadge("");
|
dock.setBadge('');
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("click", event => {
|
document.addEventListener('click', event => {
|
||||||
let target = event.target;
|
let { target } = event;
|
||||||
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)
|
||||||
const hrefParts = window.location.href.split("#");
|
const hrefParts = window.location.href.split('#');
|
||||||
const 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,
|
||||||
location:
|
location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/',
|
||||||
hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : "/",
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
amplitude.getInstance().logEvent("UNMARKED_CLICK", {
|
amplitude.getInstance().logEvent('UNMARKED_CLICK', {
|
||||||
location:
|
location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/',
|
||||||
hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : "/",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (target.matches('a[href^="http"]') || target.matches('a[href^="mailto"]')) {
|
||||||
target.matches('a[href^="http"]') ||
|
|
||||||
target.matches('a[href^="mailto"]')
|
|
||||||
) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
shell.openExternal(target.href);
|
shell.openExternal(target.href);
|
||||||
return;
|
return;
|
||||||
|
@ -90,20 +74,18 @@ document.addEventListener("click", event => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState = app.store.getState();
|
const init = function initializeReactApp() {
|
||||||
|
|
||||||
const init = function() {
|
|
||||||
app.store.dispatch(doDownloadLanguages());
|
app.store.dispatch(doDownloadLanguages());
|
||||||
|
|
||||||
function onDaemonReady() {
|
function onDaemonReady() {
|
||||||
lbry.status().then(info => {
|
lbry.status().then(info => {
|
||||||
amplitude.getInstance().init(
|
amplitude.getInstance().init(
|
||||||
// Amplitude API Key
|
// Amplitude API Key
|
||||||
"0b130efdcbdbf86ec2f7f9eff354033e",
|
'0b130efdcbdbf86ec2f7f9eff354033e',
|
||||||
info.lbry_id,
|
info.lbry_id,
|
||||||
null,
|
null,
|
||||||
() => {
|
() => {
|
||||||
window.sessionStorage.setItem("loaded", "y"); // once we've made it here once per session, we don't need to show splash again
|
window.sessionStorage.setItem('loaded', 'y'); // once we've made it here once per session, we don't need to show splash again
|
||||||
app.store.dispatch(doDaemonReady());
|
app.store.dispatch(doDaemonReady());
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
|
@ -113,21 +95,21 @@ const init = function() {
|
||||||
<SnackBar />
|
<SnackBar />
|
||||||
</div>
|
</div>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.getElementById("app")
|
document.getElementById('app')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.sessionStorage.getItem("loaded") == "y") {
|
if (window.sessionStorage.getItem('loaded') === 'y') {
|
||||||
onDaemonReady();
|
onDaemonReady();
|
||||||
} else {
|
} else {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<SplashScreen onReadyToLaunch={onDaemonReady} />
|
<SplashScreen onReadyToLaunch={onDaemonReady} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.getElementById("app")
|
document.getElementById('app')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,76 +1,56 @@
|
||||||
const jsonrpc = {};
|
const jsonrpc = {};
|
||||||
|
|
||||||
jsonrpc.call = function(
|
jsonrpc.call = function callJsonRpc(
|
||||||
connectionString,
|
connectionString,
|
||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
callback,
|
callback,
|
||||||
errorCallback,
|
errorCallback,
|
||||||
connectFailedCallback,
|
connectFailedCallback
|
||||||
timeout
|
|
||||||
) {
|
) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
return response
|
return response.json().then(json => {
|
||||||
.json()
|
let error;
|
||||||
.then(json => {
|
if (json.error) {
|
||||||
let error;
|
error = new Error(json.error);
|
||||||
if (json.error) {
|
} else {
|
||||||
error = new Error(json.error);
|
error = new Error('Protocol error with unknown response signature');
|
||||||
} else {
|
|
||||||
error = new Error("Protocol error with unknown response signature");
|
|
||||||
}
|
|
||||||
return Promise.reject(error);
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
console.error(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeRequest(url, options) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fetch(url, options)
|
|
||||||
.then(resolve)
|
|
||||||
.catch(reject);
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
const e = new Error(__("Protocol request timed out"));
|
|
||||||
setTimeout(() => reject(e), timeout);
|
|
||||||
}
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const counter = parseInt(sessionStorage.getItem("JSONRPCCounter") || 0);
|
const counter = parseInt(sessionStorage.getItem('JSONRPCCounter') || 0, 10);
|
||||||
const url = connectionString;
|
const url = connectionString;
|
||||||
const options = {
|
const options = {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
jsonrpc: "2.0",
|
jsonrpc: '2.0',
|
||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
id: counter,
|
id: counter,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
sessionStorage.setItem("JSONRPCCounter", counter + 1);
|
sessionStorage.setItem('JSONRPCCounter', counter + 1);
|
||||||
|
|
||||||
return fetch(url, options)
|
return fetch(url, options)
|
||||||
.then(checkAndParse)
|
.then(checkAndParse)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const error =
|
const error = response.error || (response.result && response.result.error);
|
||||||
response.error || (response.result && response.result.error);
|
|
||||||
|
|
||||||
if (!error && typeof callback === "function") {
|
if (!error && typeof callback === 'function') {
|
||||||
return callback(response.result);
|
return callback(response.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error && typeof errorCallback === "function") {
|
if (error && typeof errorCallback === 'function') {
|
||||||
return errorCallback(error);
|
return errorCallback(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorEvent = new CustomEvent("unhandledError", {
|
const errorEvent = new CustomEvent('unhandledError', {
|
||||||
detail: {
|
detail: {
|
||||||
connectionString,
|
connectionString,
|
||||||
method,
|
method,
|
||||||
|
@ -81,22 +61,25 @@ jsonrpc.call = function(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
document.dispatchEvent(errorEvent);
|
document.dispatchEvent(errorEvent);
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(error => {
|
||||||
if (connectFailedCallback) {
|
if (connectFailedCallback) {
|
||||||
return connectFailedCallback(e);
|
return connectFailedCallback(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorEvent = new CustomEvent("unhandledError", {
|
const errorEvent = new CustomEvent('unhandledError', {
|
||||||
detail: {
|
detail: {
|
||||||
connectionString,
|
connectionString,
|
||||||
method,
|
method,
|
||||||
params,
|
params,
|
||||||
code: e.response && e.response.status,
|
code: error.response && error.response.status,
|
||||||
message: __("Connection to API server failed"),
|
message: __('Connection to API server failed'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
document.dispatchEvent(errorEvent);
|
document.dispatchEvent(errorEvent);
|
||||||
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,31 @@
|
||||||
import jsonrpc from "./jsonrpc.js";
|
import jsonrpc from 'jsonrpc';
|
||||||
import lbryuri from "./lbryuri.js";
|
import { ipcRenderer } from 'electron';
|
||||||
|
|
||||||
|
const CHECK_DAEMON_STARTED_TRY_NUMBER = 200;
|
||||||
|
|
||||||
|
const Lbry = {
|
||||||
|
isConnected: false,
|
||||||
|
daemonConnectionString: 'http://localhost:5279',
|
||||||
|
pendingPublishTimeout: 20 * 60 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
function apiCall(method, params, resolve, reject) {
|
||||||
|
return jsonrpc.call(Lbry.daemonConnectionString, method, params, resolve, reject, reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lbryProxy = new Proxy(Lbry, {
|
||||||
|
get(target, name) {
|
||||||
|
if (name in target) {
|
||||||
|
return target[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(params = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
apiCall(name, params, resolve, reject);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
function getLocal(key, fallback = undefined) {
|
function getLocal(key, fallback = undefined) {
|
||||||
const itemRaw = localStorage.getItem(key);
|
const itemRaw = localStorage.getItem(key);
|
||||||
|
@ -10,49 +36,24 @@ function setLocal(key, value) {
|
||||||
localStorage.setItem(key, JSON.stringify(value));
|
localStorage.setItem(key, JSON.stringify(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
const { remote, ipcRenderer } = require("electron");
|
|
||||||
|
|
||||||
let lbry = {
|
|
||||||
isConnected: false,
|
|
||||||
daemonConnectionString: "http://localhost:5279",
|
|
||||||
pendingPublishTimeout: 20 * 60 * 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
function apiCall(method, params, resolve, reject) {
|
|
||||||
return jsonrpc.call(
|
|
||||||
lbry.daemonConnectionString,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
resolve,
|
|
||||||
reject,
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records a publish attempt in local storage. Returns a dictionary with all the data needed to
|
* Records a publish attempt in local storage. Returns a dictionary with all the data needed to
|
||||||
* needed to make a dummy claim or file info object.
|
* needed to make a dummy claim or file info object.
|
||||||
*/
|
*/
|
||||||
let pendingId = 0;
|
let pendingId = 0;
|
||||||
function savePendingPublish({ name, channel_name }) {
|
function savePendingPublish({ name, channelName }) {
|
||||||
let uri;
|
pendingId += 1;
|
||||||
if (channel_name) {
|
const pendingPublishes = getLocal('pendingPublishes') || [];
|
||||||
uri = lbryuri.build({ name: channel_name, path: name }, false);
|
|
||||||
} else {
|
|
||||||
uri = lbryuri.build({ name }, false);
|
|
||||||
}
|
|
||||||
++pendingId;
|
|
||||||
const pendingPublishes = getLocal("pendingPublishes") || [];
|
|
||||||
const newPendingPublish = {
|
const newPendingPublish = {
|
||||||
name,
|
name,
|
||||||
channel_name,
|
channelName,
|
||||||
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]);
|
||||||
return newPendingPublish;
|
return newPendingPublish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,31 +61,27 @@ function savePendingPublish({ name, channel_name }) {
|
||||||
* If there is a pending publish with the given name or outpoint, remove it.
|
* If there is a pending publish with the given name or outpoint, remove it.
|
||||||
* A channel name may also be provided along with name.
|
* A channel name may also be provided along with name.
|
||||||
*/
|
*/
|
||||||
function removePendingPublishIfNeeded({ name, channel_name, outpoint }) {
|
function removePendingPublishIfNeeded({ name, channelName, outpoint }) {
|
||||||
function pubMatches(pub) {
|
function pubMatches(pub) {
|
||||||
return (
|
return (
|
||||||
pub.outpoint === outpoint ||
|
pub.outpoint === outpoint ||
|
||||||
(pub.name === name &&
|
(pub.name === name && (!channelName || pub.channel_name === channelName))
|
||||||
(!channel_name || pub.channel_name === channel_name))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLocal(
|
setLocal('pendingPublishes', Lbry.getPendingPublishes().filter(pub => !pubMatches(pub)));
|
||||||
"pendingPublishes",
|
|
||||||
lbry.getPendingPublishes().filter(pub => !pubMatches(pub))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current list of pending publish attempts. Filters out any that have timed out and
|
* Gets the current list of pending publish attempts. Filters out any that have timed out and
|
||||||
* removes them from the list.
|
* removes them from the list.
|
||||||
*/
|
*/
|
||||||
lbry.getPendingPublishes = function() {
|
Lbry.getPendingPublishes = function() {
|
||||||
const pendingPublishes = getLocal("pendingPublishes") || [];
|
const pendingPublishes = getLocal('pendingPublishes') || [];
|
||||||
const newPendingPublishes = pendingPublishes.filter(
|
const newPendingPublishes = pendingPublishes.filter(
|
||||||
pub => Date.now() - pub.time <= lbry.pendingPublishTimeout
|
pub => Date.now() - pub.time <= Lbry.pendingPublishTimeout
|
||||||
);
|
);
|
||||||
setLocal("pendingPublishes", newPendingPublishes);
|
setLocal('pendingPublishes', newPendingPublishes);
|
||||||
return newPendingPublishes;
|
return newPendingPublishes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,65 +89,52 @@ lbry.getPendingPublishes = function() {
|
||||||
* Gets a pending publish attempt by its name or (fake) outpoint. A channel name can also be
|
* Gets a pending publish attempt by its name or (fake) outpoint. A channel name can also be
|
||||||
* provided along withe the name. If no pending publish is found, returns null.
|
* provided along withe the name. If no pending publish is found, returns null.
|
||||||
*/
|
*/
|
||||||
function getPendingPublish({ name, channel_name, outpoint }) {
|
function getPendingPublish({ name, channelName, outpoint }) {
|
||||||
const pendingPublishes = lbry.getPendingPublishes();
|
const pendingPublishes = Lbry.getPendingPublishes();
|
||||||
return (
|
return (
|
||||||
pendingPublishes.find(
|
pendingPublishes.find(
|
||||||
pub =>
|
pub =>
|
||||||
pub.outpoint === outpoint ||
|
pub.outpoint === outpoint ||
|
||||||
(pub.name === name &&
|
(pub.name === name && (!channelName || pub.channel_name === channelName))
|
||||||
(!channel_name || pub.channel_name === channel_name))
|
|
||||||
) || null
|
) || null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pendingPublishToDummyClaim({
|
function pendingPublishToDummyClaim({ channelName, name, outpoint, claimId, txid, nout }) {
|
||||||
channel_name,
|
return { name, outpoint, claimId, txid, nout, channelName };
|
||||||
name,
|
|
||||||
outpoint,
|
|
||||||
claim_id,
|
|
||||||
txid,
|
|
||||||
nout,
|
|
||||||
}) {
|
|
||||||
return { name, outpoint, claim_id, txid, nout, channel_name };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pendingPublishToDummyFileInfo({ name, outpoint, claim_id }) {
|
function pendingPublishToDummyFileInfo({ name, outpoint, claimId }) {
|
||||||
return { name, outpoint, claim_id, metadata: null };
|
return { name, outpoint, claimId, metadata: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
// core
|
// core
|
||||||
lbry._connectPromise = null;
|
Lbry.connectPromise = null;
|
||||||
lbry.connect = function() {
|
Lbry.connect = function() {
|
||||||
if (lbry._connectPromise === null) {
|
if (Lbry.connectPromise === null) {
|
||||||
lbry._connectPromise = new Promise((resolve, reject) => {
|
Lbry.connectPromise = new Promise((resolve, reject) => {
|
||||||
let tryNum = 0;
|
let tryNum = 0;
|
||||||
|
|
||||||
function checkDaemonStartedFailed() {
|
|
||||||
if (tryNum <= 200) {
|
|
||||||
// Move # of tries into constant or config option
|
|
||||||
setTimeout(() => {
|
|
||||||
tryNum++;
|
|
||||||
checkDaemonStarted();
|
|
||||||
}, tryNum < 50 ? 400 : 1000);
|
|
||||||
} else {
|
|
||||||
reject(new Error("Unable to connect to LBRY"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check every half second to see if the daemon is accepting connections
|
// Check every half second to see if the daemon is accepting connections
|
||||||
function checkDaemonStarted() {
|
function checkDaemonStarted() {
|
||||||
lbry
|
tryNum += 1;
|
||||||
|
lbryProxy
|
||||||
.status()
|
.status()
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(checkDaemonStartedFailed);
|
.catch(() => {
|
||||||
|
if (tryNum <= CHECK_DAEMON_STARTED_TRY_NUMBER) {
|
||||||
|
setTimeout(checkDaemonStarted, tryNum < 50 ? 400 : 1000);
|
||||||
|
} else {
|
||||||
|
reject(new Error('Unable to connect to LBRY'));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDaemonStarted();
|
checkDaemonStarted();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return lbry._connectPromise;
|
return Lbry.connectPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,13 +144,24 @@ lbry.connect = function() {
|
||||||
* This currently includes a work-around to cache the file in local storage so that the pending
|
* This currently includes a work-around to cache the file in local storage so that the pending
|
||||||
* publish can appear in the UI immediately.
|
* publish can appear in the UI immediately.
|
||||||
*/
|
*/
|
||||||
lbry.publishDeprecated = function(
|
Lbry.publishDeprecated = function(params, fileListedCallback, publishedCallback, errorCallback) {
|
||||||
params,
|
// Give a short grace period in case publish() returns right away or (more likely) gives an error
|
||||||
fileListedCallback,
|
const returnPendingTimeout = setTimeout(
|
||||||
publishedCallback,
|
() => {
|
||||||
errorCallback
|
const { name, channel_name: channelName } = params;
|
||||||
) {
|
if (publishedCallback || fileListedCallback) {
|
||||||
lbry.publish(params).then(
|
savePendingPublish({
|
||||||
|
name,
|
||||||
|
channelName,
|
||||||
|
});
|
||||||
|
publishedCallback(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
2000,
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
lbryProxy.publish(params).then(
|
||||||
result => {
|
result => {
|
||||||
if (returnPendingTimeout) clearTimeout(returnPendingTimeout);
|
if (returnPendingTimeout) clearTimeout(returnPendingTimeout);
|
||||||
publishedCallback(result);
|
publishedCallback(result);
|
||||||
|
@ -176,66 +171,40 @@ lbry.publishDeprecated = function(
|
||||||
errorCallback(err);
|
errorCallback(err);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Give a short grace period in case publish() returns right away or (more likely) gives an error
|
|
||||||
const returnPendingTimeout = setTimeout(
|
|
||||||
() => {
|
|
||||||
if (publishedCallback) {
|
|
||||||
savePendingPublish({
|
|
||||||
name: params.name,
|
|
||||||
channel_name: params.channel_name,
|
|
||||||
});
|
|
||||||
publishedCallback(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileListedCallback) {
|
|
||||||
const { name, channel_name } = params;
|
|
||||||
savePendingPublish({
|
|
||||||
name: params.name,
|
|
||||||
channel_name: params.channel_name,
|
|
||||||
});
|
|
||||||
fileListedCallback(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
2000,
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry.imagePath = function(file) {
|
Lbry.imagePath = function(file) {
|
||||||
return `${staticResourcesPath}/img/${file}`;
|
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) {
|
||||||
const dotIndex = fileName.lastIndexOf(".");
|
const dotIndex = fileName.lastIndexOf('.');
|
||||||
if (dotIndex == -1) {
|
if (dotIndex === -1) {
|
||||||
return "unknown";
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
const 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)) {
|
||||||
return "audio";
|
return 'audio';
|
||||||
} else if (
|
} else if (/^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";
|
|
||||||
}
|
}
|
||||||
return "unknown";
|
return 'unknown';
|
||||||
}
|
}
|
||||||
return "unknown";
|
return 'unknown';
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry.getAppVersionInfo = function() {
|
Lbry.getAppVersionInfo = function() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(resolve => {
|
||||||
ipcRenderer.once("version-info-received", (event, versionInfo) => {
|
ipcRenderer.once('version-info-received', (event, versionInfo) => {
|
||||||
resolve(versionInfo);
|
resolve(versionInfo);
|
||||||
});
|
});
|
||||||
ipcRenderer.send("version-info-requested");
|
ipcRenderer.send('version-info-requested');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,9 +217,9 @@ lbry.getAppVersionInfo = function() {
|
||||||
* Returns results from the file_list API method, plus dummy entries for pending publishes.
|
* Returns results from the file_list API method, plus dummy entries for pending publishes.
|
||||||
* (If a real publish with the same name is found, the pending publish will be ignored and removed.)
|
* (If a real publish with the same name is found, the pending publish will be ignored and removed.)
|
||||||
*/
|
*/
|
||||||
lbry.file_list = function(params = {}) {
|
Lbry.file_list = function(params = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const { name, channel_name, outpoint } = params;
|
const { name, channel_name: channelName, outpoint } = params;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we're searching by outpoint, check first to see if there's a matching pending publish.
|
* If we're searching by outpoint, check first to see if there's a matching pending publish.
|
||||||
|
@ -266,16 +235,14 @@ lbry.file_list = function(params = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
apiCall(
|
apiCall(
|
||||||
"file_list",
|
'file_list',
|
||||||
params,
|
params,
|
||||||
fileInfos => {
|
fileInfos => {
|
||||||
removePendingPublishIfNeeded({ name, channel_name, outpoint });
|
removePendingPublishIfNeeded({ name, channelName, 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 && !channelName && !outpoint) {
|
||||||
const dummyFileInfos = lbry
|
const dummyFileInfos = Lbry.getPendingPublishes().map(pendingPublishToDummyFileInfo);
|
||||||
.getPendingPublishes()
|
|
||||||
.map(pendingPublishToDummyFileInfo);
|
|
||||||
|
|
||||||
resolve([...fileInfos, ...dummyFileInfos]);
|
resolve([...fileInfos, ...dummyFileInfos]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,23 +254,21 @@ lbry.file_list = function(params = {}) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry.claim_list_mine = function(params = {}) {
|
Lbry.claim_list_mine = function(params = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
apiCall(
|
apiCall(
|
||||||
"claim_list_mine",
|
'claim_list_mine',
|
||||||
params,
|
params,
|
||||||
claims => {
|
claims => {
|
||||||
for (const { name, channel_name, txid, nout } of claims) {
|
claims.forEach(({ name, channel_name: channelName, txid, nout }) => {
|
||||||
removePendingPublishIfNeeded({
|
removePendingPublishIfNeeded({
|
||||||
name,
|
name,
|
||||||
channel_name,
|
channelName,
|
||||||
outpoint: `${txid}:${nout}`,
|
outpoint: `${txid}:${nout}`,
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
const dummyClaims = lbry
|
const dummyClaims = Lbry.getPendingPublishes().map(pendingPublishToDummyClaim);
|
||||||
.getPendingPublishes()
|
|
||||||
.map(pendingPublishToDummyClaim);
|
|
||||||
resolve([...claims, ...dummyClaims]);
|
resolve([...claims, ...dummyClaims]);
|
||||||
},
|
},
|
||||||
reject
|
reject
|
||||||
|
@ -311,13 +276,13 @@ lbry.claim_list_mine = function(params = {}) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry.resolve = function(params = {}) {
|
Lbry.resolve = function(params = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
apiCall(
|
apiCall(
|
||||||
"resolve",
|
'resolve',
|
||||||
params,
|
params,
|
||||||
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] : {});
|
||||||
} else {
|
} else {
|
||||||
|
@ -329,18 +294,4 @@ lbry.resolve = function(params = {}) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry = new Proxy(lbry, {
|
export default lbryProxy;
|
||||||
get(target, name) {
|
|
||||||
if (name in target) {
|
|
||||||
return target[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(params = {}) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
apiCall(name, params, resolve, reject);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default lbry;
|
|
||||||
|
|
|
@ -1,48 +1,46 @@
|
||||||
import lbry from "./lbry.js";
|
import Lbry from 'lbry';
|
||||||
|
import querystring from 'querystring';
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
|
||||||
const querystring = require("querystring");
|
const Lbryio = {
|
||||||
const { ipcRenderer } = require("electron");
|
|
||||||
|
|
||||||
const lbryio = {
|
|
||||||
enabled: true,
|
enabled: true,
|
||||||
_authenticationPromise: null,
|
authenticationPromise: null,
|
||||||
_exchangePromise: null,
|
exchangePromise: null,
|
||||||
_exchangeLastFetched: null,
|
exchangeLastFetched: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
|
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
|
||||||
? process.env.LBRY_APP_API_URL.replace(/\/*$/, "/") // exactly one slash at the end
|
? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end
|
||||||
: "https://api.lbry.io/";
|
: 'https://api.lbry.io/';
|
||||||
|
|
||||||
const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
|
const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
|
||||||
|
|
||||||
lbryio.getExchangeRates = function() {
|
Lbryio.getExchangeRates = function() {
|
||||||
if (
|
if (
|
||||||
!lbryio._exchangeLastFetched ||
|
!Lbryio.exchangeLastFetched ||
|
||||||
Date.now() - lbryio._exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
|
Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
|
||||||
) {
|
) {
|
||||||
lbryio._exchangePromise = new Promise((resolve, reject) => {
|
Lbryio.exchangePromise = new Promise((resolve, reject) => {
|
||||||
lbryio
|
Lbryio.call('lbc', 'exchange_rate', {}, 'get', true)
|
||||||
.call("lbc", "exchange_rate", {}, "get", true)
|
.then(({ lbc_usd: LBC_USD, lbc_btc: LBC_BTC, btc_usd: BTC_USD }) => {
|
||||||
.then(({ lbc_usd, lbc_btc, btc_usd }) => {
|
const rates = { LBC_USD, LBC_BTC, BTC_USD };
|
||||||
const rates = { lbc_usd, lbc_btc, btc_usd };
|
|
||||||
resolve(rates);
|
resolve(rates);
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
lbryio._exchangeLastFetched = Date.now();
|
Lbryio.exchangeLastFetched = Date.now();
|
||||||
}
|
}
|
||||||
return lbryio._exchangePromise;
|
return Lbryio.exchangePromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryio.call = function(resource, action, params = {}, method = "get") {
|
Lbryio.call = function(resource, action, params = {}, method = 'get') {
|
||||||
if (!lbryio.enabled) {
|
if (!Lbryio.enabled) {
|
||||||
console.log(__("Internal API disabled"));
|
console.log(__('Internal API disabled'));
|
||||||
return Promise.reject(new Error(__("LBRY internal API is disabled")));
|
return Promise.reject(new Error(__('LBRY internal API is disabled')));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(method == "get" || method == "post")) {
|
if (!(method === 'get' || method === 'post')) {
|
||||||
return Promise.reject(new Error(__("Invalid method")));
|
return Promise.reject(new Error(__('Invalid method')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAndParse(response) {
|
function checkAndParse(response) {
|
||||||
|
@ -54,7 +52,7 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
|
||||||
if (json.error) {
|
if (json.error) {
|
||||||
error = new Error(json.error);
|
error = new Error(json.error);
|
||||||
} else {
|
} else {
|
||||||
error = new Error("Unknown API error signature");
|
error = new Error('Unknown API error signature');
|
||||||
}
|
}
|
||||||
error.response = response; // this is primarily a hack used in actions/user.js
|
error.response = response; // this is primarily a hack used in actions/user.js
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
@ -65,20 +63,20 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
|
||||||
return fetch(url, options).then(checkAndParse);
|
return fetch(url, options).then(checkAndParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lbryio.getAuthToken().then(token => {
|
return Lbryio.getAuthToken().then(token => {
|
||||||
const fullParams = { auth_token: token, ...params };
|
const fullParams = { auth_token: token, ...params };
|
||||||
const qs = querystring.stringify(fullParams);
|
const qs = querystring.stringify(fullParams);
|
||||||
let url = `${CONNECTION_STRING}${resource}/${action}?${qs}`;
|
let url = `${CONNECTION_STRING}${resource}/${action}?${qs}`;
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (method == "post") {
|
if (method === 'post') {
|
||||||
options = {
|
options = {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
},
|
},
|
||||||
body: qs,
|
body: qs,
|
||||||
};
|
};
|
||||||
|
@ -89,35 +87,35 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryio._authToken = null;
|
Lbryio.authToken = null;
|
||||||
|
|
||||||
lbryio.getAuthToken = () =>
|
Lbryio.getAuthToken = () =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise(resolve => {
|
||||||
if (lbryio._authToken) {
|
if (Lbryio.authToken) {
|
||||||
resolve(lbryio._authToken);
|
resolve(Lbryio.authToken);
|
||||||
} else {
|
} else {
|
||||||
ipcRenderer.once("auth-token-response", (event, token) => {
|
ipcRenderer.once('auth-token-response', (event, token) => {
|
||||||
lbryio._authToken = token;
|
Lbryio.authToken = token;
|
||||||
return resolve(token);
|
return resolve(token);
|
||||||
});
|
});
|
||||||
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.call("user", "me");
|
Lbryio.getCurrentUser = () => Lbryio.call('user', 'me');
|
||||||
|
|
||||||
lbryio.authenticate = function() {
|
Lbryio.authenticate = function() {
|
||||||
if (!lbryio.enabled) {
|
if (!Lbryio.enabled) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(resolve => {
|
||||||
resolve({
|
resolve({
|
||||||
id: 1,
|
id: 1,
|
||||||
language: "en",
|
language: 'en',
|
||||||
primary_email: "disabled@lbry.io",
|
primary_email: 'disabled@lbry.io',
|
||||||
has_verified_email: true,
|
has_verified_email: true,
|
||||||
is_identity_verified: true,
|
is_identity_verified: true,
|
||||||
is_reward_approved: false,
|
is_reward_approved: false,
|
||||||
|
@ -125,58 +123,55 @@ lbryio.authenticate = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lbryio._authenticationPromise === null) {
|
if (Lbryio.authenticationPromise === null) {
|
||||||
lbryio._authenticationPromise = new Promise((resolve, reject) => {
|
Lbryio.authenticationPromise = new Promise((resolve, reject) => {
|
||||||
lbryio
|
Lbryio.getAuthToken()
|
||||||
.getAuthToken()
|
|
||||||
.then(token => {
|
.then(token => {
|
||||||
if (!token || token.length > 60) {
|
if (!token || token.length > 60) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that token works
|
// check that token works
|
||||||
return lbryio
|
return Lbryio.getCurrentUser()
|
||||||
.getCurrentUser()
|
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch(() => false);
|
.catch(() => false);
|
||||||
})
|
})
|
||||||
.then(isTokenValid => {
|
.then(isTokenValid => {
|
||||||
if (isTokenValid) {
|
if (isTokenValid) {
|
||||||
return;
|
return reject;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lbry
|
return Lbry.status()
|
||||||
.status()
|
|
||||||
.then(status =>
|
.then(status =>
|
||||||
lbryio.call(
|
Lbryio.call(
|
||||||
"user",
|
'user',
|
||||||
"new",
|
'new',
|
||||||
{
|
{
|
||||||
auth_token: "",
|
auth_token: '',
|
||||||
language: "en",
|
language: 'en',
|
||||||
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'));
|
||||||
}
|
}
|
||||||
return lbryio.setAuthToken(response.auth_token);
|
return Lbryio.setAuthToken(response.auth_token);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(lbryio.getCurrentUser)
|
.then(Lbryio.getCurrentUser)
|
||||||
.then(resolve, reject);
|
.then(resolve, reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return lbryio._authenticationPromise;
|
return Lbryio.authenticationPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryio.getStripeToken = () =>
|
Lbryio.getStripeToken = () =>
|
||||||
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;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
const CHANNEL_NAME_MIN_LEN = 1;
|
const CHANNEL_NAME_MIN_LEN = 1;
|
||||||
const CLAIM_ID_MAX_LEN = 40;
|
const CLAIM_ID_MAX_LEN = 40;
|
||||||
|
|
||||||
const lbryuri = {};
|
const Lbryuri = {};
|
||||||
|
|
||||||
lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g;
|
Lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g;
|
||||||
lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
Lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
||||||
|
@ -28,13 +28,13 @@ lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
||||||
* - contentName (string): For anon claims, the name; for channel claims, the path
|
* - contentName (string): For anon claims, the name; for channel claims, the path
|
||||||
* - channelName (string, if present): Channel name without @
|
* - channelName (string, if present): Channel name without @
|
||||||
*/
|
*/
|
||||||
lbryuri.parse = function(uri, requireProto = false) {
|
Lbryuri.parse = function(uri, requireProto = false) {
|
||||||
// Break into components. Empty sub-matches are converted to null
|
// Break into components. Empty sub-matches are converted to null
|
||||||
const componentsRegex = new RegExp(
|
const componentsRegex = new RegExp(
|
||||||
"^((?:lbry://)?)" + // protocol
|
'^((?:lbry://)?)' + // protocol
|
||||||
"([^:$#/]*)" + // name (stops at the first separator or end)
|
'([^:$#/]*)' + // name (stops at the first separator or end)
|
||||||
"([:$#]?)([^/]*)" + // modifier separator, modifier (stops at the first path separator or end)
|
'([:$#]?)([^/]*)' + // modifier separator, modifier (stops at the first path separator or end)
|
||||||
"(/?)(.*)" // path separator, path
|
'(/?)(.*)' // path separator, path
|
||||||
);
|
);
|
||||||
const [proto, name, modSep, modVal, pathSep, path] = componentsRegex
|
const [proto, name, modSep, modVal, pathSep, path] = componentsRegex
|
||||||
.exec(uri)
|
.exec(uri)
|
||||||
|
@ -45,57 +45,54 @@ lbryuri.parse = function(uri, requireProto = false) {
|
||||||
|
|
||||||
// Validate protocol
|
// Validate protocol
|
||||||
if (requireProto && !proto) {
|
if (requireProto && !proto) {
|
||||||
throw new Error(__("LBRY URIs must include a protocol prefix (lbry://)."));
|
throw new Error(__('LBRY URIs must include a protocol prefix (lbry://).'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and process name
|
// Validate and process name
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new Error(__("URI does not include name."));
|
throw new Error(__('URI does not include name.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const isChannel = name.startsWith("@");
|
const isChannel = name.startsWith('@');
|
||||||
const channelName = isChannel ? name.slice(1) : name;
|
const channelName = isChannel ? name.slice(1) : name;
|
||||||
|
|
||||||
if (isChannel) {
|
if (isChannel) {
|
||||||
if (!channelName) {
|
if (!channelName) {
|
||||||
throw new Error(__("No channel name after @."));
|
throw new Error(__('No channel name after @.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channelName.length < CHANNEL_NAME_MIN_LEN) {
|
if (channelName.length < CHANNEL_NAME_MIN_LEN) {
|
||||||
throw new Error(
|
throw new Error(__(`Channel names must be at least %s characters.`, CHANNEL_NAME_MIN_LEN));
|
||||||
__(
|
|
||||||
`Channel names must be at least %s characters.`,
|
|
||||||
CHANNEL_NAME_MIN_LEN
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
contentName = path;
|
contentName = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nameBadChars = (channelName || name).match(lbryuri.REGEXP_INVALID_URI);
|
const nameBadChars = (channelName || name).match(Lbryuri.REGEXP_INVALID_URI);
|
||||||
if (nameBadChars) {
|
if (nameBadChars) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
__(
|
__(
|
||||||
`Invalid character %s in name: %s.`,
|
`Invalid character %s in name: %s.`,
|
||||||
nameBadChars.length == 1 ? "" : "s",
|
nameBadChars.length === 1 ? '' : 's',
|
||||||
nameBadChars.join(", ")
|
nameBadChars.join(', ')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and process modifier (claim ID, bid position or claim sequence)
|
// Validate and process modifier (claim ID, bid position or claim sequence)
|
||||||
let claimId, claimSequence, bidPosition;
|
let claimId;
|
||||||
|
let claimSequence;
|
||||||
|
let bidPosition;
|
||||||
if (modSep) {
|
if (modSep) {
|
||||||
if (!modVal) {
|
if (!modVal) {
|
||||||
throw new Error(__(`No modifier provided after separator %s.`, modSep));
|
throw new Error(__(`No modifier provided after separator %s.`, modSep));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modSep == "#") {
|
if (modSep === '#') {
|
||||||
claimId = modVal;
|
claimId = modVal;
|
||||||
} else if (modSep == ":") {
|
} else if (modSep === ':') {
|
||||||
claimSequence = modVal;
|
claimSequence = modVal;
|
||||||
} else if (modSep == "$") {
|
} else if (modSep === '$') {
|
||||||
bidPosition = modVal;
|
bidPosition = modVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,29 +106,27 @@ lbryuri.parse = function(uri, requireProto = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
|
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
|
||||||
throw new Error(__("Claim sequence must be a number."));
|
throw new Error(__('Claim sequence must be a number.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
|
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
|
||||||
throw new Error(__("Bid position must be a number."));
|
throw new Error(__('Bid position must be a number.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and process path
|
// Validate and process path
|
||||||
if (path) {
|
if (path) {
|
||||||
if (!isChannel) {
|
if (!isChannel) {
|
||||||
throw new Error(__("Only channel URIs may have a path."));
|
throw new Error(__('Only channel URIs may have a path.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathBadChars = path.match(lbryuri.REGEXP_INVALID_URI);
|
const pathBadChars = path.match(Lbryuri.REGEXP_INVALID_URI);
|
||||||
if (pathBadChars) {
|
if (pathBadChars) {
|
||||||
throw new Error(
|
throw new Error(__(`Invalid character in path: %s`, pathBadChars.join(', ')));
|
||||||
__(`Invalid character in path: %s`, pathBadChars.join(", "))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
contentName = path;
|
contentName = path;
|
||||||
} else if (pathSep) {
|
} else if (pathSep) {
|
||||||
throw new Error(__("No path provided after /"));
|
throw new Error(__('No path provided after /'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -140,8 +135,8 @@ lbryuri.parse = function(uri, requireProto = false) {
|
||||||
isChannel,
|
isChannel,
|
||||||
...(contentName ? { contentName } : {}),
|
...(contentName ? { contentName } : {}),
|
||||||
...(channelName ? { channelName } : {}),
|
...(channelName ? { channelName } : {}),
|
||||||
...(claimSequence ? { claimSequence: parseInt(claimSequence) } : {}),
|
...(claimSequence ? { claimSequence: parseInt(claimSequence, 10) } : {}),
|
||||||
...(bidPosition ? { bidPosition: parseInt(bidPosition) } : {}),
|
...(bidPosition ? { bidPosition: parseInt(bidPosition, 10) } : {}),
|
||||||
...(claimId ? { claimId } : {}),
|
...(claimId ? { claimId } : {}),
|
||||||
...(path ? { path } : {}),
|
...(path ? { path } : {}),
|
||||||
};
|
};
|
||||||
|
@ -152,21 +147,13 @@ lbryuri.parse = function(uri, requireProto = false) {
|
||||||
*
|
*
|
||||||
* The channelName key will accept names with or without the @ prefix.
|
* The channelName key will accept names with or without the @ prefix.
|
||||||
*/
|
*/
|
||||||
lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) {
|
Lbryuri.build = function(uriObj, includeProto = true) {
|
||||||
let {
|
const { claimId, claimSequence, bidPosition, contentName, channelName } = uriObj;
|
||||||
name,
|
|
||||||
claimId,
|
let { name, path } = uriObj;
|
||||||
claimSequence,
|
|
||||||
bidPosition,
|
|
||||||
path,
|
|
||||||
contentName,
|
|
||||||
channelName,
|
|
||||||
} = uriObj;
|
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -187,52 +174,50 @@ lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) {
|
||||||
if (path && path !== contentName) {
|
if (path && path !== contentName) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
__(
|
__(
|
||||||
"Path and contentName do not match. Only one is required; most likely you wanted contentName."
|
'Path and contentName do not match. Only one is required; most likely you wanted contentName.'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(includeProto ? "lbry://" : "") +
|
(includeProto ? 'lbry://' : '') +
|
||||||
name +
|
name +
|
||||||
(claimId ? `#${claimId}` : "") +
|
(claimId ? `#${claimId}` : '') +
|
||||||
(claimSequence ? `:${claimSequence}` : "") +
|
(claimSequence ? `:${claimSequence}` : '') +
|
||||||
(bidPosition ? `\$${bidPosition}` : "") +
|
(bidPosition ? `${bidPosition}` : '') +
|
||||||
(path ? `/${path}` : "")
|
(path ? `/${path}` : '')
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Takes a parseable LBRY URI and converts it to standard, canonical format (currently this just
|
/* Takes a parseable LBRY URI and converts it to standard, canonical format (currently this just
|
||||||
* consists of adding the lbry:// prefix if needed) */
|
* consists of adding the lbry:// prefix if needed) */
|
||||||
lbryuri.normalize = function(uri) {
|
Lbryuri.normalize = function(uri) {
|
||||||
if (uri.match(/pending_claim/)) return uri;
|
if (uri.match(/pending_claim/)) return uri;
|
||||||
|
|
||||||
const { name, path, bidPosition, claimSequence, claimId } = lbryuri.parse(
|
const { name, path, bidPosition, claimSequence, claimId } = Lbryuri.parse(uri);
|
||||||
uri
|
return Lbryuri.build({ name, path, claimSequence, bidPosition, claimId });
|
||||||
);
|
|
||||||
return lbryuri.build({ name, path, claimSequence, bidPosition, claimId });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryuri.isValid = function(uri) {
|
Lbryuri.isValid = function(uri) {
|
||||||
let parts;
|
let parts;
|
||||||
try {
|
try {
|
||||||
parts = lbryuri.parse(lbryuri.normalize(uri));
|
parts = Lbryuri.parse(Lbryuri.normalize(uri));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return parts && parts.name;
|
return parts && parts.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryuri.isValidName = function(name, checkCase = true) {
|
Lbryuri.isValidName = function(name, checkCase = true) {
|
||||||
const regexp = new RegExp("^[a-z0-9-]+$", checkCase ? "" : "i");
|
const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i');
|
||||||
return regexp.test(name);
|
return regexp.test(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryuri.isClaimable = function(uri) {
|
Lbryuri.isClaimable = function(uri) {
|
||||||
let parts;
|
let parts;
|
||||||
try {
|
try {
|
||||||
parts = lbryuri.parse(lbryuri.normalize(uri));
|
parts = Lbryuri.parse(Lbryuri.normalize(uri));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -247,5 +232,5 @@ lbryuri.isClaimable = function(uri) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.lbryuri = lbryuri;
|
window.lbryuri = Lbryuri;
|
||||||
export default lbryuri;
|
export default Lbryuri;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbry from "lbry";
|
import Lbry from 'lbry';
|
||||||
import {
|
import {
|
||||||
selectUpdateUrl,
|
selectUpdateUrl,
|
||||||
selectUpgradeDownloadPath,
|
selectUpgradeDownloadPath,
|
||||||
|
@ -7,27 +7,26 @@ import {
|
||||||
selectUpgradeFilename,
|
selectUpgradeFilename,
|
||||||
selectIsUpgradeSkipped,
|
selectIsUpgradeSkipped,
|
||||||
selectRemoteVersion,
|
selectRemoteVersion,
|
||||||
} from "redux/selectors/app";
|
selectCurrentModal,
|
||||||
import { doFetchDaemonSettings } from "redux/actions/settings";
|
} from 'redux/selectors/app';
|
||||||
import { doBalanceSubscribe, doFetchTransactions } from "redux/actions/wallet";
|
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
||||||
import { doAuthenticate } from "redux/actions/user";
|
import { doBalanceSubscribe, doFetchTransactions } from 'redux/actions/wallet';
|
||||||
import { doFetchFileInfosAndPublishedClaims } from "redux/actions/file_info";
|
import { doAuthenticate } from 'redux/actions/user';
|
||||||
import * as modals from "constants/modal_types";
|
import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info';
|
||||||
import { doFetchRewardedContent } from "redux/actions/content";
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { selectCurrentModal } from "redux/selectors/app";
|
import { doFetchRewardedContent } from 'redux/actions/content';
|
||||||
|
import { ipcRenderer, remote } from 'electron';
|
||||||
|
import Path from 'path';
|
||||||
|
|
||||||
const { remote, ipcRenderer, shell } = require("electron");
|
const { download } = remote.require('electron-dl');
|
||||||
const path = require("path");
|
const Fs = remote.require('fs');
|
||||||
|
const { lbrySettings: config } = require('package.json');
|
||||||
const { download } = remote.require("electron-dl");
|
|
||||||
const fs = remote.require("fs");
|
|
||||||
const { lbrySettings: config } = require("package.json");
|
|
||||||
|
|
||||||
const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000;
|
const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000;
|
||||||
|
|
||||||
export function doOpenModal(modal, modalProps = {}) {
|
export function doOpenModal(modal, modalProps = {}) {
|
||||||
return {
|
return {
|
||||||
type: types.OPEN_MODAL,
|
type: ACTIONS.OPEN_MODAL,
|
||||||
data: {
|
data: {
|
||||||
modal,
|
modal,
|
||||||
modalProps,
|
modalProps,
|
||||||
|
@ -37,13 +36,13 @@ export function doOpenModal(modal, modalProps = {}) {
|
||||||
|
|
||||||
export function doCloseModal() {
|
export function doCloseModal() {
|
||||||
return {
|
return {
|
||||||
type: types.CLOSE_MODAL,
|
type: ACTIONS.CLOSE_MODAL,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUpdateDownloadProgress(percent) {
|
export function doUpdateDownloadProgress(percent) {
|
||||||
return {
|
return {
|
||||||
type: types.UPGRADE_DOWNLOAD_PROGRESSED,
|
type: ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED,
|
||||||
data: {
|
data: {
|
||||||
percent,
|
percent,
|
||||||
},
|
},
|
||||||
|
@ -52,7 +51,7 @@ export function doUpdateDownloadProgress(percent) {
|
||||||
|
|
||||||
export function doSkipUpgrade() {
|
export function doSkipUpgrade() {
|
||||||
return {
|
return {
|
||||||
type: types.SKIP_UPGRADE,
|
type: ACTIONS.SKIP_UPGRADE,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +60,7 @@ export function doStartUpgrade() {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const upgradeDownloadPath = selectUpgradeDownloadPath(state);
|
const upgradeDownloadPath = selectUpgradeDownloadPath(state);
|
||||||
|
|
||||||
ipcRenderer.send("upgrade", upgradeDownloadPath);
|
ipcRenderer.send('upgrade', upgradeDownloadPath);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,40 +68,36 @@ export function doDownloadUpgrade() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
// Make a new directory within temp directory so the filename is guaranteed to be available
|
// Make a new directory within temp directory so the filename is guaranteed to be available
|
||||||
const dir = fs.mkdtempSync(
|
const dir = Fs.mkdtempSync(remote.app.getPath('temp') + Path.sep);
|
||||||
remote.app.getPath("temp") + require("path").sep
|
const upgradeFilename = selectUpgradeFilename(state);
|
||||||
),
|
|
||||||
upgradeFilename = selectUpgradeFilename(state);
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))),
|
onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))),
|
||||||
directory: dir,
|
directory: dir,
|
||||||
};
|
};
|
||||||
download(remote.getCurrentWindow(), selectUpdateUrl(state), options).then(
|
download(remote.getCurrentWindow(), selectUpdateUrl(state), options).then(downloadItem => {
|
||||||
downloadItem => {
|
/**
|
||||||
/**
|
* TODO: get the download path directly from the download object. It should just be
|
||||||
* TODO: get the download path directly from the download object. It should just be
|
* downloadItem.getSavePath(), but the copy on the main process is being garbage collected
|
||||||
* downloadItem.getSavePath(), but the copy on the main process is being garbage collected
|
* too soon.
|
||||||
* too soon.
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.UPGRADE_DOWNLOAD_COMPLETED,
|
type: ACTIONS.UPGRADE_DOWNLOAD_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
downloadItem,
|
downloadItem,
|
||||||
path: path.join(dir, upgradeFilename),
|
path: Path.join(dir, upgradeFilename),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.UPGRADE_DOWNLOAD_STARTED,
|
type: ACTIONS.UPGRADE_DOWNLOAD_STARTED,
|
||||||
});
|
});
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.OPEN_MODAL,
|
type: ACTIONS.OPEN_MODAL,
|
||||||
data: {
|
data: {
|
||||||
modal: modals.DOWNLOADING,
|
modal: MODALS.DOWNLOADING,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -127,7 +122,7 @@ export function doCancelUpgrade() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ type: types.UPGRADE_CANCELLED });
|
dispatch({ type: ACTIONS.UPGRADE_CANCELLED });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,12 +130,12 @@ export function doCheckUpgradeAvailable() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHECK_UPGRADE_START,
|
type: ACTIONS.CHECK_UPGRADE_START,
|
||||||
});
|
});
|
||||||
|
|
||||||
const success = ({ remoteVersion, upgradeAvailable }) => {
|
const success = ({ remoteVersion, upgradeAvailable }) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHECK_UPGRADE_SUCCESS,
|
type: ACTIONS.CHECK_UPGRADE_SUCCESS,
|
||||||
data: {
|
data: {
|
||||||
upgradeAvailable,
|
upgradeAvailable,
|
||||||
remoteVersion,
|
remoteVersion,
|
||||||
|
@ -150,13 +145,12 @@ export function doCheckUpgradeAvailable() {
|
||||||
if (
|
if (
|
||||||
upgradeAvailable &&
|
upgradeAvailable &&
|
||||||
!selectCurrentModal(state) &&
|
!selectCurrentModal(state) &&
|
||||||
(!selectIsUpgradeSkipped(state) ||
|
(!selectIsUpgradeSkipped(state) || remoteVersion !== selectRemoteVersion(state))
|
||||||
remoteVersion !== selectRemoteVersion(state))
|
|
||||||
) {
|
) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.OPEN_MODAL,
|
type: ACTIONS.OPEN_MODAL,
|
||||||
data: {
|
data: {
|
||||||
modal: modals.UPGRADE,
|
modal: MODALS.UPGRADE,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -164,11 +158,11 @@ export function doCheckUpgradeAvailable() {
|
||||||
|
|
||||||
const fail = () => {
|
const fail = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHECK_UPGRADE_FAIL,
|
type: ACTIONS.CHECK_UPGRADE_FAIL,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry.getAppVersionInfo().then(success, fail);
|
Lbry.getAppVersionInfo().then(success, fail);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,32 +176,31 @@ export function doCheckUpgradeSubscribe() {
|
||||||
CHECK_UPGRADE_INTERVAL
|
CHECK_UPGRADE_INTERVAL
|
||||||
);
|
);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHECK_UPGRADE_SUBSCRIBE,
|
type: ACTIONS.CHECK_UPGRADE_SUBSCRIBE,
|
||||||
data: { checkUpgradeTimer },
|
data: { checkUpgradeTimer },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doCheckDaemonVersion() {
|
export function doCheckDaemonVersion() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
lbry.version().then(({ lbrynet_version }) => {
|
Lbry.version().then(({ lbrynet_version: lbrynetVersion }) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type:
|
type:
|
||||||
config.lbrynetDaemonVersion == lbrynet_version
|
config.lbrynetDaemonVersion === lbrynetVersion
|
||||||
? types.DAEMON_VERSION_MATCH
|
? ACTIONS.DAEMON_VERSION_MATCH
|
||||||
: types.DAEMON_VERSION_MISMATCH,
|
: ACTIONS.DAEMON_VERSION_MISMATCH,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doAlertError(errorList) {
|
export function doAlertError(errorList) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const state = getState();
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.OPEN_MODAL,
|
type: ACTIONS.OPEN_MODAL,
|
||||||
data: {
|
data: {
|
||||||
modal: modals.ERROR,
|
modal: MODALS.ERROR,
|
||||||
modalProps: { error: errorList },
|
modalProps: { error: errorList },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -219,7 +212,7 @@ export function doDaemonReady() {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
dispatch(doAuthenticate());
|
dispatch(doAuthenticate());
|
||||||
dispatch({ type: types.DAEMON_READY });
|
dispatch({ type: ACTIONS.DAEMON_READY });
|
||||||
dispatch(doFetchDaemonSettings());
|
dispatch(doFetchDaemonSettings());
|
||||||
dispatch(doBalanceSubscribe());
|
dispatch(doBalanceSubscribe());
|
||||||
dispatch(doFetchFileInfosAndPublishedClaims());
|
dispatch(doFetchFileInfosAndPublishedClaims());
|
||||||
|
@ -234,19 +227,19 @@ export function doDaemonReady() {
|
||||||
|
|
||||||
export function doShowSnackBar(data) {
|
export function doShowSnackBar(data) {
|
||||||
return {
|
return {
|
||||||
type: types.SHOW_SNACKBAR,
|
type: ACTIONS.SHOW_SNACKBAR,
|
||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doRemoveSnackBarSnack() {
|
export function doRemoveSnackBarSnack() {
|
||||||
return {
|
return {
|
||||||
type: types.REMOVE_SNACKBAR_SNACK,
|
type: ACTIONS.REMOVE_SNACKBAR_SNACK,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doClearCache() {
|
export function doClearCache() {
|
||||||
return function(dispatch, getState) {
|
return function() {
|
||||||
window.cacheStore.purge();
|
window.cacheStore.purge();
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
@ -254,15 +247,15 @@ export function doClearCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doQuit() {
|
export function doQuit() {
|
||||||
return function(dispatch, getState) {
|
return function() {
|
||||||
remote.app.quit();
|
remote.app.quit();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doChangeVolume(volume) {
|
export function doChangeVolume(volume) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.VOLUME_CHANGED,
|
type: ACTIONS.VOLUME_CHANGED,
|
||||||
data: {
|
data: {
|
||||||
volume,
|
volume,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,32 +1,27 @@
|
||||||
import * as types from "constants/action_types";
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
import lbry from "lbry";
|
export function doFetchAvailability() {
|
||||||
import { selectFetchingAvailability } from "redux/selectors/availability";
|
return function() {
|
||||||
|
|
||||||
export function doFetchAvailability(uri) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
/*
|
/*
|
||||||
this is disabled atm - Jeremy
|
this is disabled atm - Jeremy
|
||||||
*/
|
*/
|
||||||
return;
|
// const state = getState();
|
||||||
|
// const alreadyFetching = !!selectFetchingAvailability(state)[uri];
|
||||||
const state = getState();
|
//
|
||||||
const alreadyFetching = !!selectFetchingAvailability(state)[uri];
|
// if (!alreadyFetching) {
|
||||||
|
// dispatch({
|
||||||
if (!alreadyFetching) {
|
// type: ACTIONS.FETCH_AVAILABILITY_STARTED,
|
||||||
dispatch({
|
// data: { uri },
|
||||||
type: types.FETCH_AVAILABILITY_STARTED,
|
// });
|
||||||
data: { uri },
|
//
|
||||||
});
|
// lbry.get_availability({ uri }).then(availability => {
|
||||||
|
// dispatch({
|
||||||
lbry.get_availability({ uri }).then(availability => {
|
// type: ACTIONS.FETCH_AVAILABILITY_COMPLETED,
|
||||||
dispatch({
|
// data: {
|
||||||
type: types.FETCH_AVAILABILITY_COMPLETED,
|
// availability,
|
||||||
data: {
|
// uri,
|
||||||
availability,
|
// },
|
||||||
uri,
|
// });
|
||||||
},
|
// });
|
||||||
});
|
// }
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +1,63 @@
|
||||||
import * as types from "constants/action_types";
|
import { ipcRenderer } from 'electron';
|
||||||
import * as settings from "constants/settings";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbry from "lbry";
|
import * as SETTINGS from 'constants/settings';
|
||||||
import lbryio from "lbryio";
|
import Lbry from 'lbry';
|
||||||
import lbryuri from "lbryuri";
|
import Lbryio from 'lbryio';
|
||||||
import { makeSelectClientSetting } from "redux/selectors/settings";
|
import Lbryuri from 'lbryuri';
|
||||||
import { selectBalance, selectTransactionItems } from "redux/selectors/wallet";
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
|
import { selectBalance, selectTransactionItems } from 'redux/selectors/wallet';
|
||||||
import {
|
import {
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
selectDownloadingByOutpoint,
|
selectDownloadingByOutpoint,
|
||||||
} from "redux/selectors/file_info";
|
selectTotalDownloadProgress,
|
||||||
import { selectResolvingUris } from "redux/selectors/content";
|
} from 'redux/selectors/file_info';
|
||||||
import { makeSelectCostInfoForUri } from "redux/selectors/cost_info";
|
import { selectResolvingUris } from 'redux/selectors/content';
|
||||||
import { doAlertError, doOpenModal } from "redux/actions/app";
|
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
||||||
import { doClaimEligiblePurchaseRewards } from "redux/actions/rewards";
|
import { doAlertError, doOpenModal } from 'redux/actions/app';
|
||||||
import { selectBadgeNumber } from "redux/selectors/app";
|
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
||||||
import { selectTotalDownloadProgress } from "redux/selectors/file_info";
|
import { selectBadgeNumber } from 'redux/selectors/app';
|
||||||
import setBadge from "util/setBadge";
|
import setBadge from 'util/setBadge';
|
||||||
import setProgressBar from "util/setProgressBar";
|
import setProgressBar from 'util/setProgressBar';
|
||||||
import batchActions from "util/batchActions";
|
import batchActions from 'util/batchActions';
|
||||||
import * as modals from "constants/modal_types";
|
import * as MODALS from 'constants/modal_types';
|
||||||
|
|
||||||
const { ipcRenderer } = require("electron");
|
|
||||||
|
|
||||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||||
|
|
||||||
export function doResolveUris(uris) {
|
export function doResolveUris(uris) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
uris = uris.map(lbryuri.normalize);
|
const normalizedUris = uris.map(Lbryuri.normalize);
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
// Filter out URIs that are already resolving
|
// Filter out URIs that are already resolving
|
||||||
const resolvingUris = selectResolvingUris(state);
|
const resolvingUris = selectResolvingUris(state);
|
||||||
const urisToResolve = uris.filter(uri => !resolvingUris.includes(uri));
|
const urisToResolve = normalizedUris.filter(uri => !resolvingUris.includes(uri));
|
||||||
|
|
||||||
if (urisToResolve.length === 0) {
|
if (urisToResolve.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.RESOLVE_URIS_STARTED,
|
type: ACTIONS.RESOLVE_URIS_STARTED,
|
||||||
data: { uris },
|
data: { uris: normalizedUris },
|
||||||
});
|
});
|
||||||
|
|
||||||
const resolveInfo = {};
|
const resolveInfo = {};
|
||||||
lbry.resolve({ uris: urisToResolve }).then(result => {
|
Lbry.resolve({ uris: urisToResolve }).then(result => {
|
||||||
for (const [uri, uriResolveInfo] of Object.entries(result)) {
|
Object.entries(result).forEach(([uri, uriResolveInfo]) => {
|
||||||
const fallbackResolveInfo = {
|
const fallbackResolveInfo = {
|
||||||
claim: null,
|
claim: null,
|
||||||
claims_in_channel: null,
|
claimsInChannel: null,
|
||||||
certificate: null,
|
certificate: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { claim, certificate, claims_in_channel } =
|
const { claim, certificate, claims_in_channel: claimsInChannel } =
|
||||||
uriResolveInfo && !uriResolveInfo.error
|
uriResolveInfo && !uriResolveInfo.error ? uriResolveInfo : fallbackResolveInfo;
|
||||||
? uriResolveInfo
|
|
||||||
: fallbackResolveInfo;
|
resolveInfo[uri] = { claim, certificate, claimsInChannel };
|
||||||
resolveInfo[uri] = { claim, certificate, claims_in_channel };
|
});
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.RESOLVE_URIS_COMPLETED,
|
type: ACTIONS.RESOLVE_URIS_COMPLETED,
|
||||||
data: { resolveInfo },
|
data: { resolveInfo },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -71,23 +69,21 @@ export function doResolveUri(uri) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchFeaturedUris() {
|
export function doFetchFeaturedUris() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_FEATURED_CONTENT_STARTED,
|
type: ACTIONS.FETCH_FEATURED_CONTENT_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
const success = ({ Uris }) => {
|
const success = ({ Uris }) => {
|
||||||
let urisToResolve = [];
|
let urisToResolve = [];
|
||||||
for (const category in Uris) {
|
Object.keys(Uris).forEach(category => {
|
||||||
urisToResolve = [...urisToResolve, ...Uris[category]];
|
urisToResolve = [...urisToResolve, ...Uris[category]];
|
||||||
}
|
});
|
||||||
|
|
||||||
const actions = [
|
const actions = [
|
||||||
doResolveUris(urisToResolve),
|
doResolveUris(urisToResolve),
|
||||||
{
|
{
|
||||||
type: types.FETCH_FEATURED_CONTENT_COMPLETED,
|
type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
uris: Uris,
|
uris: Uris,
|
||||||
success: true,
|
success: true,
|
||||||
|
@ -99,24 +95,22 @@ export function doFetchFeaturedUris() {
|
||||||
|
|
||||||
const failure = () => {
|
const failure = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_FEATURED_CONTENT_COMPLETED,
|
type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
uris: {},
|
uris: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryio.call("file", "list_homepage").then(success, failure);
|
Lbryio.call('file', 'list_homepage').then(success, failure);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchRewardedContent() {
|
export function doFetchRewardedContent() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
const success = nameToClaimId => {
|
const success = nameToClaimId => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_REWARD_CONTENT_COMPLETED,
|
type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
claimIds: Object.values(nameToClaimId),
|
claimIds: Object.values(nameToClaimId),
|
||||||
success: true,
|
success: true,
|
||||||
|
@ -126,7 +120,7 @@ export function doFetchRewardedContent() {
|
||||||
|
|
||||||
const failure = () => {
|
const failure = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_REWARD_CONTENT_COMPLETED,
|
type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
claimIds: [],
|
claimIds: [],
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -134,73 +128,69 @@ export function doFetchRewardedContent() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryio.call("reward", "list_featured").then(success, failure);
|
Lbryio.call('reward', 'list_featured').then(success, failure);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUpdateLoadStatus(uri, outpoint) {
|
export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
Lbry.file_list({
|
||||||
|
outpoint,
|
||||||
|
full_status: true,
|
||||||
|
}).then(([fileInfo]) => {
|
||||||
|
if (!fileInfo || fileInfo.written_bytes === 0) {
|
||||||
|
// download hasn't started yet
|
||||||
|
setTimeout(() => {
|
||||||
|
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||||
|
}, DOWNLOAD_POLL_INTERVAL);
|
||||||
|
} else if (fileInfo.completed) {
|
||||||
|
// TODO this isn't going to get called if they reload the client before
|
||||||
|
// the download finished
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.DOWNLOADING_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uri,
|
||||||
|
outpoint,
|
||||||
|
fileInfo,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
lbry
|
const badgeNumber = selectBadgeNumber(getState());
|
||||||
.file_list({
|
setBadge(badgeNumber === 0 ? '' : `${badgeNumber}`);
|
||||||
outpoint,
|
|
||||||
full_status: true,
|
|
||||||
})
|
|
||||||
.then(([fileInfo]) => {
|
|
||||||
if (!fileInfo || fileInfo.written_bytes == 0) {
|
|
||||||
// download hasn't started yet
|
|
||||||
setTimeout(() => {
|
|
||||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
|
||||||
}, DOWNLOAD_POLL_INTERVAL);
|
|
||||||
} else if (fileInfo.completed) {
|
|
||||||
// TODO this isn't going to get called if they reload the client before
|
|
||||||
// the download finished
|
|
||||||
dispatch({
|
|
||||||
type: types.DOWNLOADING_COMPLETED,
|
|
||||||
data: {
|
|
||||||
uri,
|
|
||||||
outpoint,
|
|
||||||
fileInfo,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const badgeNumber = selectBadgeNumber(getState());
|
const totalProgress = selectTotalDownloadProgress(getState());
|
||||||
setBadge(badgeNumber === 0 ? "" : `${badgeNumber}`);
|
setProgressBar(totalProgress);
|
||||||
|
|
||||||
const totalProgress = selectTotalDownloadProgress(getState());
|
const notif = new window.Notification('LBRY Download Complete', {
|
||||||
setProgressBar(totalProgress);
|
body: fileInfo.metadata.stream.metadata.title,
|
||||||
|
silent: false,
|
||||||
|
});
|
||||||
|
notif.onclick = () => {
|
||||||
|
ipcRenderer.send('focusWindow', 'main');
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// ready to play
|
||||||
|
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
||||||
|
const progress = writtenBytes / totalBytes * 100;
|
||||||
|
|
||||||
const notif = new window.Notification("LBRY Download Complete", {
|
dispatch({
|
||||||
body: fileInfo.metadata.stream.metadata.title,
|
type: ACTIONS.DOWNLOADING_PROGRESSED,
|
||||||
silent: false,
|
data: {
|
||||||
});
|
uri,
|
||||||
notif.onclick = () => {
|
outpoint,
|
||||||
ipcRenderer.send("focusWindow", "main");
|
fileInfo,
|
||||||
};
|
progress,
|
||||||
} else {
|
},
|
||||||
// ready to play
|
});
|
||||||
const { total_bytes, written_bytes } = fileInfo;
|
|
||||||
const progress = written_bytes / total_bytes * 100;
|
|
||||||
|
|
||||||
dispatch({
|
const totalProgress = selectTotalDownloadProgress(getState());
|
||||||
type: types.DOWNLOADING_PROGRESSED,
|
setProgressBar(totalProgress);
|
||||||
data: {
|
|
||||||
uri,
|
|
||||||
outpoint,
|
|
||||||
fileInfo,
|
|
||||||
progress,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const totalProgress = selectTotalDownloadProgress(getState());
|
setTimeout(() => {
|
||||||
setProgressBar(totalProgress);
|
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||||
|
}, DOWNLOAD_POLL_INTERVAL);
|
||||||
setTimeout(() => {
|
}
|
||||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
});
|
||||||
}, DOWNLOAD_POLL_INTERVAL);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,16 +199,16 @@ export function doStartDownload(uri, outpoint) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
if (!outpoint) {
|
if (!outpoint) {
|
||||||
throw new Error("outpoint is required to begin a download");
|
throw new Error('outpoint is required to begin a download');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { downloadingByOutpoint = {} } = state.fileInfo;
|
const { downloadingByOutpoint = {} } = state.fileInfo;
|
||||||
|
|
||||||
if (downloadingByOutpoint[outpoint]) return;
|
if (downloadingByOutpoint[outpoint]) return;
|
||||||
|
|
||||||
lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => {
|
Lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DOWNLOADING_STARTED,
|
type: ACTIONS.DOWNLOADING_STARTED,
|
||||||
data: {
|
data: {
|
||||||
uri,
|
uri,
|
||||||
outpoint,
|
outpoint,
|
||||||
|
@ -232,50 +222,50 @@ export function doStartDownload(uri, outpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doDownloadFile(uri, streamInfo) {
|
export function doDownloadFile(uri, streamInfo) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
dispatch(doStartDownload(uri, streamInfo.outpoint));
|
dispatch(doStartDownload(uri, streamInfo.outpoint));
|
||||||
|
|
||||||
lbryio
|
Lbryio.call('file', 'view', {
|
||||||
.call("file", "view", {
|
uri,
|
||||||
uri,
|
outpoint: streamInfo.outpoint,
|
||||||
outpoint: streamInfo.outpoint,
|
claim_id: streamInfo.claim_id,
|
||||||
claim_id: streamInfo.claim_id,
|
}).catch(() => {});
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
|
|
||||||
dispatch(doClaimEligiblePurchaseRewards());
|
dispatch(doClaimEligiblePurchaseRewards());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doLoadVideo(uri) {
|
export function doSetPlayingUri(uri) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.LOADING_VIDEO_STARTED,
|
type: ACTIONS.SET_PLAYING_URI,
|
||||||
|
data: { uri },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doLoadVideo(uri) {
|
||||||
|
return function(dispatch) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.LOADING_VIDEO_STARTED,
|
||||||
data: {
|
data: {
|
||||||
uri,
|
uri,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry
|
Lbry.get({ uri })
|
||||||
.get({ uri })
|
|
||||||
.then(streamInfo => {
|
.then(streamInfo => {
|
||||||
const timeout =
|
const timeout =
|
||||||
streamInfo === null ||
|
streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
|
||||||
typeof streamInfo !== "object" ||
|
|
||||||
streamInfo.error == "Timeout";
|
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
dispatch(doSetPlayingUri(null));
|
dispatch(doSetPlayingUri(null));
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.LOADING_VIDEO_FAILED,
|
type: ACTIONS.LOADING_VIDEO_FAILED,
|
||||||
data: { uri },
|
data: { uri },
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(doOpenModal(modals.FILE_TIMEOUT, { uri }));
|
dispatch(doOpenModal(MODALS.FILE_TIMEOUT, { uri }));
|
||||||
} else {
|
} else {
|
||||||
dispatch(doDownloadFile(uri, streamInfo));
|
dispatch(doDownloadFile(uri, streamInfo));
|
||||||
}
|
}
|
||||||
|
@ -283,7 +273,7 @@ export function doLoadVideo(uri) {
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
dispatch(doSetPlayingUri(null));
|
dispatch(doSetPlayingUri(null));
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.LOADING_VIDEO_FAILED,
|
type: ACTIONS.LOADING_VIDEO_FAILED,
|
||||||
data: { uri },
|
data: { uri },
|
||||||
});
|
});
|
||||||
dispatch(
|
dispatch(
|
||||||
|
@ -303,12 +293,11 @@ export function doPurchaseUri(uri) {
|
||||||
const balance = selectBalance(state);
|
const balance = selectBalance(state);
|
||||||
const fileInfo = makeSelectFileInfoForUri(uri)(state);
|
const fileInfo = makeSelectFileInfoForUri(uri)(state);
|
||||||
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
|
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
|
||||||
const alreadyDownloading =
|
const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
|
||||||
fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
|
|
||||||
|
|
||||||
function attemptPlay(cost, instantPurchaseMax = null) {
|
function attemptPlay(cost, instantPurchaseMax = null) {
|
||||||
if (cost > 0 && (!instantPurchaseMax || cost > instantPurchaseMax)) {
|
if (cost > 0 && (!instantPurchaseMax || cost > instantPurchaseMax)) {
|
||||||
dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri }));
|
dispatch(doOpenModal(MODALS.AFFIRM_PURCHASE, { uri }));
|
||||||
} else {
|
} else {
|
||||||
dispatch(doLoadVideo(uri));
|
dispatch(doLoadVideo(uri));
|
||||||
}
|
}
|
||||||
|
@ -321,12 +310,14 @@ export function doPurchaseUri(uri) {
|
||||||
// doLoadVideo action to reconstruct the file from the blobs
|
// doLoadVideo action to reconstruct the file from the blobs
|
||||||
if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri));
|
if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri));
|
||||||
|
|
||||||
return Promise.resolve();
|
Promise.resolve();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we are already downloading the file
|
// we are already downloading the file
|
||||||
if (alreadyDownloading) {
|
if (alreadyDownloading) {
|
||||||
return Promise.resolve();
|
Promise.resolve();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const costInfo = makeSelectCostInfoForUri(uri)(state);
|
const costInfo = makeSelectCostInfoForUri(uri)(state);
|
||||||
|
@ -334,25 +325,21 @@ export function doPurchaseUri(uri) {
|
||||||
|
|
||||||
if (cost > balance) {
|
if (cost > balance) {
|
||||||
dispatch(doSetPlayingUri(null));
|
dispatch(doSetPlayingUri(null));
|
||||||
dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
|
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||||
return Promise.resolve();
|
Promise.resolve();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (cost === 0 || !makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED)(state)) {
|
||||||
cost == 0 ||
|
|
||||||
!makeSelectClientSetting(settings.INSTANT_PURCHASE_ENABLED)(state)
|
|
||||||
) {
|
|
||||||
attemptPlay(cost);
|
attemptPlay(cost);
|
||||||
} else {
|
} else {
|
||||||
const instantPurchaseMax = makeSelectClientSetting(
|
const instantPurchaseMax = makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_MAX)(state);
|
||||||
settings.INSTANT_PURCHASE_MAX
|
if (instantPurchaseMax.currency === 'LBC') {
|
||||||
)(state);
|
|
||||||
if (instantPurchaseMax.currency == "LBC") {
|
|
||||||
attemptPlay(cost, instantPurchaseMax.amount);
|
attemptPlay(cost, instantPurchaseMax.amount);
|
||||||
} else {
|
} else {
|
||||||
// Need to convert currency of instant purchase maximum before trying to play
|
// Need to convert currency of instant purchase maximum before trying to play
|
||||||
lbryio.getExchangeRates().then(({ lbc_usd }) => {
|
Lbryio.getExchangeRates().then(({ LBC_USD }) => {
|
||||||
attemptPlay(cost, instantPurchaseMax.amount / lbc_usd);
|
attemptPlay(cost, instantPurchaseMax.amount / LBC_USD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,22 +347,22 @@ export function doPurchaseUri(uri) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchClaimsByChannel(uri, page) {
|
export function doFetchClaimsByChannel(uri, page) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CHANNEL_CLAIMS_STARTED,
|
type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED,
|
||||||
data: { uri, page },
|
data: { uri, page },
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => {
|
Lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => {
|
||||||
const claimResult = result[uri] || {};
|
const claimResult = result[uri] || {};
|
||||||
const { claims_in_channel, returned_page } = claimResult;
|
const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CHANNEL_CLAIMS_COMPLETED,
|
type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
uri,
|
uri,
|
||||||
claims: claims_in_channel || [],
|
claims: claimsInChannel || [],
|
||||||
page: returned_page || undefined,
|
page: returnedPage || undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -383,18 +370,18 @@ export function doFetchClaimsByChannel(uri, page) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchClaimCountByChannel(uri) {
|
export function doFetchClaimCountByChannel(uri) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CHANNEL_CLAIM_COUNT_STARTED,
|
type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_STARTED,
|
||||||
data: { uri },
|
data: { uri },
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.claim_list_by_channel({ uri }).then(result => {
|
Lbry.claim_list_by_channel({ uri }).then(result => {
|
||||||
const claimResult = result[uri],
|
const claimResult = result[uri];
|
||||||
totalClaims = claimResult ? claimResult.claims_in_channel : 0;
|
const totalClaims = claimResult ? claimResult.claims_in_channel : 0;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED,
|
type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
uri,
|
uri,
|
||||||
totalClaims,
|
totalClaims,
|
||||||
|
@ -405,14 +392,14 @@ export function doFetchClaimCountByChannel(uri) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchClaimListMine() {
|
export function doFetchClaimListMine() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CLAIM_LIST_MINE_STARTED,
|
type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.claim_list_mine().then(claims => {
|
Lbry.claim_list_mine().then(claims => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
claims,
|
claims,
|
||||||
},
|
},
|
||||||
|
@ -422,69 +409,59 @@ export function doFetchClaimListMine() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doPlayUri(uri) {
|
export function doPlayUri(uri) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch(doSetPlayingUri(uri));
|
dispatch(doSetPlayingUri(uri));
|
||||||
dispatch(doPurchaseUri(uri));
|
dispatch(doPurchaseUri(uri));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doSetPlayingUri(uri) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch({
|
|
||||||
type: types.SET_PLAYING_URI,
|
|
||||||
data: { uri },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doFetchChannelListMine() {
|
export function doFetchChannelListMine() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CHANNEL_LIST_MINE_STARTED,
|
type: ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
const callback = channels => {
|
const callback = channels => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_CHANNEL_LIST_MINE_COMPLETED,
|
type: ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED,
|
||||||
data: { claims: channels },
|
data: { claims: channels },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry.channel_list_mine().then(callback);
|
Lbry.channel_list_mine().then(callback);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doCreateChannel(name, amount) {
|
export function doCreateChannel(name, amount) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CREATE_CHANNEL_STARTED,
|
type: ACTIONS.CREATE_CHANNEL_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
lbry
|
Lbry.channel_new({
|
||||||
.channel_new({
|
channel_name: name,
|
||||||
channel_name: name,
|
amount: parseFloat(amount),
|
||||||
amount: parseFloat(amount),
|
}).then(
|
||||||
})
|
channelClaim => {
|
||||||
.then(
|
const newChannelClaim = channelClaim;
|
||||||
channelClaim => {
|
newChannelClaim.name = name;
|
||||||
channelClaim.name = name;
|
dispatch({
|
||||||
dispatch({
|
type: ACTIONS.CREATE_CHANNEL_COMPLETED,
|
||||||
type: types.CREATE_CHANNEL_COMPLETED,
|
data: { newChannelClaim },
|
||||||
data: { channelClaim },
|
});
|
||||||
});
|
resolve(newChannelClaim);
|
||||||
resolve(channelClaim);
|
},
|
||||||
},
|
error => {
|
||||||
err => {
|
reject(error);
|
||||||
reject(err);
|
}
|
||||||
}
|
);
|
||||||
);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doPublish(params) {
|
export function doPublish(params) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const success = claim => {
|
const success = claim => {
|
||||||
resolve(claim);
|
resolve(claim);
|
||||||
|
@ -497,7 +474,7 @@ export function doPublish(params) {
|
||||||
};
|
};
|
||||||
const failure = err => reject(err);
|
const failure = err => reject(err);
|
||||||
|
|
||||||
lbry.publishDeprecated(params, null, success, failure);
|
Lbry.publishDeprecated(params, null, success, failure);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -507,40 +484,38 @@ export function doAbandonClaim(txid, nout) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const transactionItems = selectTransactionItems(state);
|
const transactionItems = selectTransactionItems(state);
|
||||||
const { claim_id: claimId, claim_name: name } = transactionItems.find(
|
const { claim_id: claimId, claim_name: name } = transactionItems.find(
|
||||||
claim => claim.txid == txid && claim.nout == nout
|
claim => claim.txid === txid && claim.nout === nout
|
||||||
);
|
);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.ABANDON_CLAIM_STARTED,
|
type: ACTIONS.ABANDON_CLAIM_STARTED,
|
||||||
data: {
|
data: {
|
||||||
claimId,
|
claimId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorCallback = error => {
|
const errorCallback = () => {
|
||||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||||
};
|
};
|
||||||
|
|
||||||
const successCallback = results => {
|
const successCallback = results => {
|
||||||
if (results.txid) {
|
if (results.txid) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.ABANDON_CLAIM_SUCCEEDED,
|
type: ACTIONS.ABANDON_CLAIM_SUCCEEDED,
|
||||||
data: {
|
data: {
|
||||||
claimId,
|
claimId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
dispatch(doResolveUri(lbryuri.build({ name, claimId })));
|
dispatch(doResolveUri(Lbryuri.build({ name, claimId })));
|
||||||
dispatch(doFetchClaimListMine());
|
dispatch(doFetchClaimListMine());
|
||||||
} else {
|
} else {
|
||||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry
|
Lbry.claim_abandon({
|
||||||
.claim_abandon({
|
txid,
|
||||||
txid,
|
nout,
|
||||||
nout,
|
}).then(successCallback, errorCallback);
|
||||||
})
|
|
||||||
.then(successCallback, errorCallback);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,18 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbry from "lbry";
|
import Lbryio from 'lbryio';
|
||||||
import lbryio from "lbryio";
|
import { selectClaimsByUri } from 'redux/selectors/claims';
|
||||||
import { doResolveUri } from "redux/actions/content";
|
|
||||||
import { selectResolvingUris } from "redux/selectors/content";
|
|
||||||
import { selectClaimsByUri } from "redux/selectors/claims";
|
|
||||||
import { selectSettingsIsGenerous } from "redux/selectors/settings";
|
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export function doFetchCostInfoForUri(uri) {
|
export function doFetchCostInfoForUri(uri) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState(),
|
const state = getState();
|
||||||
claim = selectClaimsByUri(state)[uri],
|
const claim = selectClaimsByUri(state)[uri];
|
||||||
isGenerous = selectSettingsIsGenerous(state);
|
|
||||||
|
|
||||||
if (!claim) return null;
|
if (!claim) return;
|
||||||
|
|
||||||
function begin() {
|
|
||||||
dispatch({
|
|
||||||
type: types.FETCH_COST_INFO_STARTED,
|
|
||||||
data: {
|
|
||||||
uri,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolve(costInfo) {
|
function resolve(costInfo) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_COST_INFO_COMPLETED,
|
type: ACTIONS.FETCH_COST_INFO_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
uri,
|
uri,
|
||||||
costInfo,
|
costInfo,
|
||||||
|
@ -33,18 +20,6 @@ export function doFetchCostInfoForUri(uri) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* "Generous" check below is disabled. We're no longer attempting to include or estimate data fees regardless of settings.
|
|
||||||
*
|
|
||||||
* This should be modified when lbry.stream_cost_estimate is reliable and performant.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
lbry.stream_cost_estimate({ uri }).then(cost => {
|
|
||||||
cacheAndResolve(cost);
|
|
||||||
}, reject);
|
|
||||||
*/
|
|
||||||
|
|
||||||
const fee =
|
const fee =
|
||||||
claim.value && claim.value.stream && claim.value.stream.metadata
|
claim.value && claim.value.stream && claim.value.stream.metadata
|
||||||
? claim.value.stream.metadata.fee
|
? claim.value.stream.metadata.fee
|
||||||
|
@ -52,35 +27,12 @@ export function doFetchCostInfoForUri(uri) {
|
||||||
|
|
||||||
if (fee === undefined) {
|
if (fee === undefined) {
|
||||||
resolve({ cost: 0, includesData: true });
|
resolve({ cost: 0, includesData: true });
|
||||||
} else if (fee.currency == "LBC") {
|
} else if (fee.currency === 'LBC') {
|
||||||
resolve({ cost: fee.amount, includesData: true });
|
resolve({ cost: fee.amount, includesData: true });
|
||||||
} else {
|
} else {
|
||||||
// begin();
|
Lbryio.getExchangeRates().then(({ LBC_USD }) => {
|
||||||
lbryio.getExchangeRates().then(({ lbc_usd }) => {
|
resolve({ cost: fee.amount / LBC_USD, includesData: true });
|
||||||
resolve({ cost: fee.amount / lbc_usd, includesData: true });
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (isGenerous && claim) {
|
|
||||||
// let cost;
|
|
||||||
// const fee = claim.value &&
|
|
||||||
// claim.value.stream &&
|
|
||||||
// claim.value.stream.metadata
|
|
||||||
// ? claim.value.stream.metadata.fee
|
|
||||||
// : undefined;
|
|
||||||
// if (fee === undefined) {
|
|
||||||
// resolve({ cost: 0, includesData: true });
|
|
||||||
// } else if (fee.currency == "LBC") {
|
|
||||||
// resolve({ cost: fee.amount, includesData: true });
|
|
||||||
// } else {
|
|
||||||
// // begin();
|
|
||||||
// lbryio.getExchangeRates().then(({ lbc_usd }) => {
|
|
||||||
// resolve({ cost: fee.amount / lbc_usd, includesData: true });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// begin();
|
|
||||||
// lbry.getCostInfo(uri).then(resolve);
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbry from "lbry";
|
import Lbry from 'lbry';
|
||||||
import { doFetchClaimListMine, doAbandonClaim } from "redux/actions/content";
|
import { doFetchClaimListMine, doAbandonClaim } from 'redux/actions/content';
|
||||||
import {
|
import {
|
||||||
selectClaimsByUri,
|
selectClaimsByUri,
|
||||||
selectIsFetchingClaimListMine,
|
selectIsFetchingClaimListMine,
|
||||||
selectMyClaimsOutpoints,
|
selectMyClaimsOutpoints,
|
||||||
} from "redux/selectors/claims";
|
} from 'redux/selectors/claims';
|
||||||
import {
|
import {
|
||||||
selectIsFetchingFileList,
|
selectIsFetchingFileList,
|
||||||
selectFileInfosByOutpoint,
|
selectFileInfosByOutpoint,
|
||||||
selectUrisLoading,
|
selectUrisLoading,
|
||||||
selectTotalDownloadProgress,
|
selectTotalDownloadProgress,
|
||||||
} from "redux/selectors/file_info";
|
} from 'redux/selectors/file_info';
|
||||||
import { doCloseModal } from "redux/actions/app";
|
import { doCloseModal } from 'redux/actions/app';
|
||||||
import { doNavigate, doHistoryBack } from "redux/actions/navigation";
|
import { doHistoryBack } from 'redux/actions/navigation';
|
||||||
import setProgressBar from "util/setProgressBar";
|
import setProgressBar from 'util/setProgressBar';
|
||||||
import batchActions from "util/batchActions";
|
import batchActions from 'util/batchActions';
|
||||||
|
import { shell } from 'electron';
|
||||||
const { shell } = require("electron");
|
|
||||||
|
|
||||||
export function doFetchFileInfo(uri) {
|
export function doFetchFileInfo(uri) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
|
@ -28,15 +27,15 @@ export function doFetchFileInfo(uri) {
|
||||||
|
|
||||||
if (!alreadyFetching) {
|
if (!alreadyFetching) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_FILE_INFO_STARTED,
|
type: ACTIONS.FETCH_FILE_INFO_STARTED,
|
||||||
data: {
|
data: {
|
||||||
outpoint,
|
outpoint,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.file_list({ outpoint, full_status: true }).then(fileInfos => {
|
Lbry.file_list({ outpoint, full_status: true }).then(fileInfos => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_FILE_INFO_COMPLETED,
|
type: ACTIONS.FETCH_FILE_INFO_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
outpoint,
|
outpoint,
|
||||||
fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null,
|
fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null,
|
||||||
|
@ -54,12 +53,12 @@ export function doFileList() {
|
||||||
|
|
||||||
if (!isFetching) {
|
if (!isFetching) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FILE_LIST_STARTED,
|
type: ACTIONS.FILE_LIST_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.file_list().then(fileInfos => {
|
Lbry.file_list().then(fileInfos => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FILE_LIST_SUCCEEDED,
|
type: ACTIONS.FILE_LIST_SUCCEEDED,
|
||||||
data: {
|
data: {
|
||||||
fileInfos,
|
fileInfos,
|
||||||
},
|
},
|
||||||
|
@ -69,8 +68,14 @@ export function doFileList() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doOpenFileInFolder(path) {
|
||||||
|
return function() {
|
||||||
|
shell.showItemInFolder(path);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function doOpenFileInShell(path) {
|
export function doOpenFileInShell(path) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const success = shell.openItem(path);
|
const success = shell.openItem(path);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dispatch(doOpenFileInFolder(path));
|
dispatch(doOpenFileInFolder(path));
|
||||||
|
@ -78,17 +83,11 @@ export function doOpenFileInShell(path) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doOpenFileInFolder(path) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
shell.showItemInFolder(path);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
lbry.file_delete({
|
Lbry.file_delete({
|
||||||
outpoint,
|
outpoint,
|
||||||
delete_from_download_dir: deleteFromComputer,
|
delete_from_download_dir: deleteFromComputer,
|
||||||
});
|
});
|
||||||
|
@ -108,7 +107,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FILE_DELETE,
|
type: ACTIONS.FILE_DELETE,
|
||||||
data: {
|
data: {
|
||||||
outpoint,
|
outpoint,
|
||||||
},
|
},
|
||||||
|
@ -119,12 +118,8 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doDeleteFileAndGoBack(
|
export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim) {
|
||||||
fileInfo,
|
return function(dispatch) {
|
||||||
deleteFromComputer,
|
|
||||||
abandonClaim
|
|
||||||
) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const actions = [];
|
const actions = [];
|
||||||
actions.push(doCloseModal());
|
actions.push(doCloseModal());
|
||||||
actions.push(doHistoryBack());
|
actions.push(doHistoryBack());
|
||||||
|
@ -135,9 +130,9 @@ export function doDeleteFileAndGoBack(
|
||||||
|
|
||||||
export function doFetchFileInfosAndPublishedClaims() {
|
export function doFetchFileInfosAndPublishedClaims() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState(),
|
const state = getState();
|
||||||
isFetchingClaimListMine = selectIsFetchingClaimListMine(state),
|
const isFetchingClaimListMine = selectIsFetchingClaimListMine(state);
|
||||||
isFetchingFileInfo = selectIsFetchingFileList(state);
|
const isFetchingFileInfo = selectIsFetchingFileList(state);
|
||||||
|
|
||||||
if (!isFetchingClaimListMine) dispatch(doFetchClaimListMine());
|
if (!isFetchingClaimListMine) dispatch(doFetchClaimListMine());
|
||||||
if (!isFetchingFileInfo) dispatch(doFileList());
|
if (!isFetchingFileInfo) dispatch(doFileList());
|
||||||
|
|
|
@ -1,18 +1,10 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import {
|
import { selectHistoryStack, selectHistoryIndex } from 'redux/selectors/navigation';
|
||||||
computePageFromPath,
|
import { toQueryString } from 'util/query_params';
|
||||||
selectPageTitle,
|
import amplitude from 'amplitude-js';
|
||||||
selectCurrentPage,
|
|
||||||
selectCurrentParams,
|
|
||||||
selectHistoryStack,
|
|
||||||
selectHistoryIndex,
|
|
||||||
} from "redux/selectors/navigation";
|
|
||||||
import { doSearch } from "redux/actions/search";
|
|
||||||
import { toQueryString } from "util/query_params";
|
|
||||||
import amplitude from "amplitude-js";
|
|
||||||
|
|
||||||
export function doNavigate(path, params = {}, options = {}) {
|
export function doNavigate(path, params = {}, options = {}) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -22,40 +14,38 @@ export function doNavigate(path, params = {}, options = {}) {
|
||||||
url += `?${toQueryString(params)}`;
|
url += `?${toQueryString(params)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollY = options.scrollY;
|
const { scrollY } = options;
|
||||||
|
|
||||||
amplitude.getInstance().logEvent("NAVIGATION", { destination: url });
|
amplitude.getInstance().logEvent('NAVIGATION', { destination: url });
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.HISTORY_NAVIGATE,
|
type: ACTIONS.HISTORY_NAVIGATE,
|
||||||
data: { url, index: options.index, scrollY },
|
data: { url, index: options.index, scrollY },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doAuthNavigate(pathAfterAuth = null, params = {}) {
|
export function doAuthNavigate(pathAfterAuth = null, params = {}) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
if (pathAfterAuth) {
|
if (pathAfterAuth) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHANGE_AFTER_AUTH_PATH,
|
type: ACTIONS.CHANGE_AFTER_AUTH_PATH,
|
||||||
data: {
|
data: {
|
||||||
path: `${pathAfterAuth}?${toQueryString(params)}`,
|
path: `${pathAfterAuth}?${toQueryString(params)}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dispatch(doNavigate("/auth"));
|
dispatch(doNavigate('/auth'));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doHistoryTraverse(dispatch, state, modifier) {
|
export function doHistoryTraverse(dispatch, state, modifier) {
|
||||||
const stack = selectHistoryStack(state),
|
const stack = selectHistoryStack(state);
|
||||||
index = selectHistoryIndex(state) + modifier;
|
const index = selectHistoryIndex(state) + modifier;
|
||||||
|
|
||||||
if (index >= 0 && index < stack.length) {
|
if (index >= 0 && index < stack.length) {
|
||||||
const historyItem = stack[index];
|
const historyItem = stack[index];
|
||||||
return dispatch(
|
dispatch(doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index }));
|
||||||
doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +62,9 @@ export function doHistoryForward() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doRecordScroll(scroll) {
|
export function doRecordScroll(scroll) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.WINDOW_SCROLLED,
|
type: ACTIONS.WINDOW_SCROLLED,
|
||||||
data: { scrollY: scroll },
|
data: { scrollY: scroll },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,30 +1,26 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as modals from "constants/modal_types";
|
import * as MODALS from 'constants/modal_types';
|
||||||
import lbryio from "lbryio";
|
import Lbryio from 'lbryio';
|
||||||
import rewards from "rewards";
|
import rewards from 'rewards';
|
||||||
import { selectUnclaimedRewardsByType } from "redux/selectors/rewards";
|
import { selectUnclaimedRewardsByType } from 'redux/selectors/rewards';
|
||||||
import { selectUserIsRewardApproved } from "redux/selectors/user";
|
import { selectUserIsRewardApproved } from 'redux/selectors/user';
|
||||||
import { selectClaimedRewardsById } from "../selectors/rewards";
|
|
||||||
|
|
||||||
export function doRewardList() {
|
export function doRewardList() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_REWARDS_STARTED,
|
type: ACTIONS.FETCH_REWARDS_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbryio
|
Lbryio.call('reward', 'list', { multiple_rewards_per_type: true })
|
||||||
.call("reward", "list", { multiple_rewards_per_type: true })
|
|
||||||
.then(userRewards => {
|
.then(userRewards => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_REWARDS_COMPLETED,
|
type: ACTIONS.FETCH_REWARDS_COMPLETED,
|
||||||
data: { userRewards },
|
data: { userRewards },
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_REWARDS_COMPLETED,
|
type: ACTIONS.FETCH_REWARDS_COMPLETED,
|
||||||
data: { userRewards: [] },
|
data: { userRewards: [] },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -33,10 +29,10 @@ export function doRewardList() {
|
||||||
|
|
||||||
export function doClaimRewardType(rewardType) {
|
export function doClaimRewardType(rewardType) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState(),
|
const state = getState();
|
||||||
rewardsByType = selectUnclaimedRewardsByType(state),
|
const rewardsByType = selectUnclaimedRewardsByType(state);
|
||||||
reward = rewardsByType[rewardType],
|
const reward = rewardsByType[rewardType];
|
||||||
userIsRewardApproved = selectUserIsRewardApproved(state);
|
const 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
|
||||||
|
@ -44,35 +40,37 @@ export function doClaimRewardType(rewardType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) {
|
if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) {
|
||||||
return dispatch({
|
dispatch({
|
||||||
type: types.OPEN_MODAL,
|
type: ACTIONS.OPEN_MODAL,
|
||||||
data: { modal: modals.REWARD_APPROVAL_REQUIRED },
|
data: { modal: MODALS.REWARD_APPROVAL_REQUIRED },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CLAIM_REWARD_STARTED,
|
type: ACTIONS.CLAIM_REWARD_STARTED,
|
||||||
data: { reward },
|
data: { reward },
|
||||||
});
|
});
|
||||||
|
|
||||||
const success = reward => {
|
const success = successReward => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CLAIM_REWARD_SUCCESS,
|
type: ACTIONS.CLAIM_REWARD_SUCCESS,
|
||||||
data: {
|
data: {
|
||||||
reward,
|
reward: successReward,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (reward.reward_type == rewards.TYPE_CONFIRM_EMAIL) {
|
if (successReward.reward_type === rewards.TYPE_CONFIRM_EMAIL) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.OPEN_MODAL,
|
type: ACTIONS.OPEN_MODAL,
|
||||||
data: { modal: modals.FIRST_REWARD },
|
data: { modal: MODALS.FIRST_REWARD },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const failure = error => {
|
const failure = error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CLAIM_REWARD_FAILURE,
|
type: ACTIONS.CLAIM_REWARD_FAILURE,
|
||||||
data: { reward, error },
|
data: { reward, error },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -83,30 +81,28 @@ export function doClaimRewardType(rewardType) {
|
||||||
|
|
||||||
export function doClaimEligiblePurchaseRewards() {
|
export function doClaimEligiblePurchaseRewards() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState(),
|
const state = getState();
|
||||||
rewardsByType = selectUnclaimedRewardsByType(state),
|
const rewardsByType = selectUnclaimedRewardsByType(state);
|
||||||
userIsRewardApproved = selectUserIsRewardApproved(state);
|
const userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||||
|
|
||||||
if (!userIsRewardApproved || !lbryio.enabled) {
|
if (!userIsRewardApproved || !Lbryio.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rewardsByType[rewards.TYPE_FIRST_STREAM]) {
|
if (rewardsByType[rewards.TYPE_FIRST_STREAM]) {
|
||||||
dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
|
dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
|
||||||
} else {
|
} else {
|
||||||
[rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(
|
[rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => {
|
||||||
type => {
|
dispatch(doClaimRewardType(type));
|
||||||
dispatch(doClaimRewardType(type));
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doClaimRewardClearError(reward) {
|
export function doClaimRewardClearError(reward) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CLAIM_REWARD_CLEAR_ERROR,
|
type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR,
|
||||||
data: { reward },
|
data: { reward },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,30 +1,32 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbryuri from "lbryuri";
|
import Lbryuri from 'lbryuri';
|
||||||
import { doResolveUri } from "redux/actions/content";
|
import { doResolveUri } from 'redux/actions/content';
|
||||||
import { doNavigate } from "redux/actions/navigation";
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { selectCurrentPage } from "redux/selectors/navigation";
|
import { selectCurrentPage } from 'redux/selectors/navigation';
|
||||||
import batchActions from "util/batchActions";
|
import batchActions from 'util/batchActions';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export function doSearch(rawQuery) {
|
export function doSearch(rawQuery) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const page = selectCurrentPage(state);
|
const page = selectCurrentPage(state);
|
||||||
|
|
||||||
const query = rawQuery.replace(/^lbry:\/\//i, "");
|
const query = rawQuery.replace(/^lbry:\/\//i, '');
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return dispatch({
|
dispatch({
|
||||||
type: types.SEARCH_CANCELLED,
|
type: ACTIONS.SEARCH_CANCELLED,
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEARCH_STARTED,
|
type: ACTIONS.SEARCH_STARTED,
|
||||||
data: { query },
|
data: { query },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (page != "search") {
|
if (page !== 'search') {
|
||||||
dispatch(doNavigate("search", { query }));
|
dispatch(doNavigate('search', { query }));
|
||||||
} else {
|
} else {
|
||||||
fetch(`https://lighthouse.lbry.io/search?s=${query}`)
|
fetch(`https://lighthouse.lbry.io/search?s=${query}`)
|
||||||
.then(
|
.then(
|
||||||
|
@ -38,7 +40,7 @@ export function doSearch(rawQuery) {
|
||||||
const actions = [];
|
const actions = [];
|
||||||
|
|
||||||
data.forEach(result => {
|
data.forEach(result => {
|
||||||
const uri = lbryuri.build({
|
const uri = Lbryuri.build({
|
||||||
name: result.name,
|
name: result.name,
|
||||||
claimId: result.claimId,
|
claimId: result.claimId,
|
||||||
});
|
});
|
||||||
|
@ -47,7 +49,7 @@ export function doSearch(rawQuery) {
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
type: types.SEARCH_COMPLETED,
|
type: ACTIONS.SEARCH_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
query,
|
query,
|
||||||
uris,
|
uris,
|
||||||
|
@ -55,9 +57,9 @@ export function doSearch(rawQuery) {
|
||||||
});
|
});
|
||||||
dispatch(batchActions(...actions));
|
dispatch(batchActions(...actions));
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEARCH_CANCELLED,
|
type: ACTIONS.SEARCH_CANCELLED,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as settings from "constants/settings";
|
import * as SETTINGS from 'constants/settings';
|
||||||
import { doAlertError } from "redux/actions/app";
|
|
||||||
import batchActions from "util/batchActions";
|
|
||||||
|
|
||||||
import lbry from "lbry";
|
import Lbry from 'lbry';
|
||||||
import fs from "fs";
|
import Fs from 'fs';
|
||||||
import http from "http";
|
import Http from 'http';
|
||||||
|
|
||||||
export function doFetchDaemonSettings() {
|
export function doFetchDaemonSettings() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
lbry.settings_get().then(settings => {
|
Lbry.settings_get().then(settings => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DAEMON_SETTINGS_RECEIVED,
|
type: ACTIONS.DAEMON_SETTINGS_RECEIVED,
|
||||||
data: {
|
data: {
|
||||||
settings,
|
settings,
|
||||||
},
|
},
|
||||||
|
@ -21,15 +19,15 @@ export function doFetchDaemonSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doSetDaemonSetting(key, value) {
|
export function doSetDaemonSetting(key, value) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const 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(remoteSettings => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DAEMON_SETTINGS_RECEIVED,
|
type: ACTIONS.DAEMON_SETTINGS_RECEIVED,
|
||||||
data: {
|
data: {
|
||||||
settings,
|
remoteSettings,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -38,7 +36,7 @@ export function doSetDaemonSetting(key, value) {
|
||||||
|
|
||||||
export function doSetClientSetting(key, value) {
|
export function doSetClientSetting(key, value) {
|
||||||
return {
|
return {
|
||||||
type: types.CLIENT_SETTING_CHANGED,
|
type: ACTIONS.CLIENT_SETTING_CHANGED,
|
||||||
data: {
|
data: {
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
|
@ -47,100 +45,98 @@ export function doSetClientSetting(key, value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doGetThemes() {
|
export function doGetThemes() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const themes = ["light", "dark"];
|
const themes = ['light', 'dark'];
|
||||||
dispatch(doSetClientSetting(settings.THEMES, themes));
|
dispatch(doSetClientSetting(SETTINGS.THEMES, themes));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doDownloadLanguage(langFile) {
|
export function doDownloadLanguage(langFile) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
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 errorHandler = () => {
|
||||||
|
Fs.unlink(destinationPath, () => {}); // Delete the file async. (But we don't check the result)
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.DOWNLOAD_LANGUAGE_FAILED,
|
||||||
|
data: { language },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const req = Http.get(
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "text/html",
|
'Content-Type': 'text/html',
|
||||||
},
|
},
|
||||||
host: "i18n.lbry.io",
|
host: 'i18n.lbry.io',
|
||||||
path: `/langs/${langFile}`,
|
path: `/langs/${langFile}`,
|
||||||
},
|
},
|
||||||
response => {
|
response => {
|
||||||
if (response.statusCode === 200) {
|
if (response.statusCode === 200) {
|
||||||
const file = fs.createWriteStream(destinationPath);
|
const file = Fs.createWriteStream(destinationPath);
|
||||||
|
|
||||||
file.on("error", errorHandler);
|
file.on('error', errorHandler);
|
||||||
file.on("finish", () => {
|
file.on('finish', () => {
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// push to our local list
|
// push to our local list
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DOWNLOAD_LANGUAGE_SUCCEEDED,
|
type: ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED,
|
||||||
data: { language },
|
data: { language },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
response.pipe(file);
|
response.pipe(file);
|
||||||
} else {
|
} else {
|
||||||
errorHandler(new Error("Language request failed."));
|
errorHandler(new Error('Language request failed.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const errorHandler = err => {
|
|
||||||
fs.unlink(destinationPath, () => {}); // Delete the file async. (But we don't check the result)
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: types.DOWNLOAD_LANGUAGE_FAILED,
|
|
||||||
data: { language },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
req.setTimeout(30000, () => {
|
req.setTimeout(30000, () => {
|
||||||
req.abort();
|
req.abort();
|
||||||
});
|
});
|
||||||
|
|
||||||
req.on("error", errorHandler);
|
req.on('error', errorHandler);
|
||||||
|
|
||||||
req.end();
|
req.end();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doDownloadLanguages() {
|
export function doDownloadLanguages() {
|
||||||
return function(dispatch, getState) {
|
return function() {
|
||||||
// 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;
|
// if (!Fs.existsSync(app.i18n.directory)) {
|
||||||
|
// Fs.mkdirSync(app.i18n.directory);
|
||||||
if (!fs.existsSync(app.i18n.directory)) {
|
// }
|
||||||
fs.mkdirSync(app.i18n.directory);
|
//
|
||||||
}
|
// function checkStatus(response) {
|
||||||
|
// if (response.status >= 200 && response.status < 300) {
|
||||||
function checkStatus(response) {
|
// return response;
|
||||||
if (response.status >= 200 && response.status < 300) {
|
// }
|
||||||
return response;
|
// 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) {
|
||||||
|
// return response.json();
|
||||||
function parseJSON(response) {
|
// }
|
||||||
return response.json();
|
//
|
||||||
}
|
// return fetch("http://i18n.lbry.io")
|
||||||
|
// .then(checkStatus)
|
||||||
return fetch("http://i18n.lbry.io")
|
// .then(parseJSON)
|
||||||
.then(checkStatus)
|
// .then(files => {
|
||||||
.then(parseJSON)
|
// const actions = files.map(doDownloadLanguage);
|
||||||
.then(files => {
|
// dispatch(batchActions(...actions));
|
||||||
const actions = files.map(doDownloadLanguage);
|
// });
|
||||||
dispatch(batchActions(...actions));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doChangeLanguage(language) {
|
export function doChangeLanguage(language) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch(doSetClientSetting(settings.LANGUAGE, language));
|
dispatch(doSetClientSetting(SETTINGS.LANGUAGE, language));
|
||||||
app.i18n.setLocale(language);
|
app.i18n.setLocale(language);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import Promise from "bluebird";
|
import Promise from 'bluebird';
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { coinRegexPatterns } from "util/shape_shift";
|
import { coinRegexPatterns } from 'util/shape_shift';
|
||||||
import type {
|
import type {
|
||||||
GetSupportedCoinsSuccess,
|
GetSupportedCoinsSuccess,
|
||||||
GetCoinStatsStart,
|
GetCoinStatsStart,
|
||||||
|
@ -11,26 +11,26 @@ import type {
|
||||||
PrepareShapeShiftFail,
|
PrepareShapeShiftFail,
|
||||||
GetActiveShiftSuccess,
|
GetActiveShiftSuccess,
|
||||||
GetActiveShiftFail,
|
GetActiveShiftFail,
|
||||||
} from "redux/reducers/shape_shift";
|
} from 'redux/reducers/shape_shift';
|
||||||
import type { FormikActions } from "types/common";
|
import type { FormikActions } from 'types/common';
|
||||||
|
|
||||||
// use promise chains instead of callbacks for shapeshift api
|
// use promise chains instead of callbacks for shapeshift api
|
||||||
const shapeShift = Promise.promisifyAll(require("shapeshift.io"));
|
const shapeShift = Promise.promisifyAll(require('shapeshift.io'));
|
||||||
|
|
||||||
// All ShapeShift actions
|
// All ShapeShift actions
|
||||||
// Action types defined in the reducer will contain some payload
|
// Action types defined in the reducer will contain some payload
|
||||||
export type Action =
|
export type Action =
|
||||||
| { type: types.GET_SUPPORTED_COINS_START }
|
| { type: ACTIONS.GET_SUPPORTED_COINS_START }
|
||||||
| { type: types.GET_SUPPORTED_COINS_FAIL }
|
| { type: ACTIONS.GET_SUPPORTED_COINS_FAIL }
|
||||||
| GetSupportedCoinsSuccess
|
| GetSupportedCoinsSuccess
|
||||||
| GetCoinStatsStart
|
| GetCoinStatsStart
|
||||||
| { type: types.GET_COIN_STATS_START }
|
| { type: ACTIONS.GET_COIN_STATS_START }
|
||||||
| GetCoinStatsFail
|
| GetCoinStatsFail
|
||||||
| GetCoinStatsSuccess
|
| GetCoinStatsSuccess
|
||||||
| { type: types.PREPARE_SHAPE_SHIFT_START }
|
| { type: ACTIONS.PREPARE_SHAPE_SHIFT_START }
|
||||||
| PrepareShapeShiftFail
|
| PrepareShapeShiftFail
|
||||||
| PrepareShapeShiftSuccess
|
| PrepareShapeShiftSuccess
|
||||||
| { type: types.GET_ACTIVE_SHIFT_START }
|
| { type: ACTIONS.GET_ACTIVE_SHIFT_START }
|
||||||
| GetActiveShiftFail
|
| GetActiveShiftFail
|
||||||
| GetActiveShiftSuccess;
|
| GetActiveShiftSuccess;
|
||||||
|
|
||||||
|
@ -38,10 +38,8 @@ export type Action =
|
||||||
// It would be nice to import these from types/common
|
// It would be nice to import these from types/common
|
||||||
// Not sure how that would work since they rely on the Action type
|
// Not sure how that would work since they rely on the Action type
|
||||||
type PromiseAction = Promise<Action>;
|
type PromiseAction = Promise<Action>;
|
||||||
|
export type Dispatch = (action: Action | PromiseAction | Array<Action>) => any;
|
||||||
type ThunkAction = (dispatch: Dispatch) => any;
|
type ThunkAction = (dispatch: Dispatch) => any;
|
||||||
export type Dispatch = (
|
|
||||||
action: Action | ThunkAction | PromiseAction | Array<Action>
|
|
||||||
) => any;
|
|
||||||
|
|
||||||
// ShapeShift form values
|
// ShapeShift form values
|
||||||
export type ShapeShiftFormValues = {
|
export type ShapeShiftFormValues = {
|
||||||
|
@ -50,15 +48,26 @@ export type ShapeShiftFormValues = {
|
||||||
receiveAddress: string,
|
receiveAddress: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCoinStats = (coin: string) => (dispatch: Dispatch): ThunkAction => {
|
||||||
|
const pair = `${coin.toLowerCase()}_lbc`;
|
||||||
|
|
||||||
|
dispatch({ type: ACTIONS.GET_COIN_STATS_START, data: coin });
|
||||||
|
|
||||||
|
return shapeShift
|
||||||
|
.marketInfoAsync(pair)
|
||||||
|
.then(marketInfo => dispatch({ type: ACTIONS.GET_COIN_STATS_SUCCESS, data: marketInfo }))
|
||||||
|
.catch(err => dispatch({ type: ACTIONS.GET_COIN_STATS_FAIL, data: err }));
|
||||||
|
};
|
||||||
|
|
||||||
export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
|
export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
|
||||||
dispatch({ type: types.GET_SUPPORTED_COINS_START });
|
dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_START });
|
||||||
|
|
||||||
return shapeShift
|
return shapeShift
|
||||||
.coinsAsync()
|
.coinsAsync()
|
||||||
.then(coinData => {
|
.then(coinData => {
|
||||||
let supportedCoins = [];
|
let supportedCoins = [];
|
||||||
Object.keys(coinData).forEach(symbol => {
|
Object.keys(coinData).forEach(symbol => {
|
||||||
if (coinData[symbol].status === "available") {
|
if (coinData[symbol].status === 'available') {
|
||||||
supportedCoins.push(coinData[symbol]);
|
supportedCoins.push(coinData[symbol]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -69,69 +78,43 @@ export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
|
||||||
.map(coin => coin.symbol);
|
.map(coin => coin.symbol);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.GET_SUPPORTED_COINS_SUCCESS,
|
type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS,
|
||||||
data: supportedCoins,
|
data: supportedCoins,
|
||||||
});
|
});
|
||||||
dispatch(getCoinStats(supportedCoins[0]));
|
dispatch(getCoinStats(supportedCoins[0]));
|
||||||
})
|
})
|
||||||
.catch(err =>
|
.catch(err => dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_FAIL, data: err }));
|
||||||
dispatch({ type: types.GET_SUPPORTED_COINS_FAIL, data: err })
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCoinStats = (coin: string) => (
|
export const createShapeShift = (values: ShapeShiftFormValues, actions: FormikActions) => (
|
||||||
dispatch: Dispatch
|
dispatch: Dispatch
|
||||||
): ThunkAction => {
|
): ThunkAction => {
|
||||||
const pair = `${coin.toLowerCase()}_lbc`;
|
const { originCoin, returnAddress, receiveAddress: withdrawalAddress } = values;
|
||||||
|
|
||||||
dispatch({ type: types.GET_COIN_STATS_START, data: coin });
|
|
||||||
|
|
||||||
return shapeShift
|
|
||||||
.marketInfoAsync(pair)
|
|
||||||
.then(marketInfo =>
|
|
||||||
dispatch({ type: types.GET_COIN_STATS_SUCCESS, data: marketInfo })
|
|
||||||
)
|
|
||||||
.catch(err => dispatch({ type: types.GET_COIN_STATS_FAIL, data: err }));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createShapeShift = (
|
|
||||||
values: ShapeShiftFormValues,
|
|
||||||
actions: FormikActions
|
|
||||||
) => (dispatch: Dispatch): ThunkAction => {
|
|
||||||
const {
|
|
||||||
originCoin,
|
|
||||||
returnAddress,
|
|
||||||
receiveAddress: withdrawalAddress,
|
|
||||||
} = values;
|
|
||||||
|
|
||||||
const pair = `${originCoin.toLowerCase()}_lbc`;
|
const pair = `${originCoin.toLowerCase()}_lbc`;
|
||||||
const options = {
|
const options = {
|
||||||
returnAddress,
|
returnAddress,
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch({ type: types.PREPARE_SHAPE_SHIFT_START });
|
dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_START });
|
||||||
return shapeShift
|
return shapeShift
|
||||||
.shiftAsync(withdrawalAddress, pair, options)
|
.shiftAsync(withdrawalAddress, pair, options)
|
||||||
.then(res =>
|
.then(res => dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS, data: res }))
|
||||||
dispatch({ type: types.PREPARE_SHAPE_SHIFT_SUCCESS, data: res })
|
|
||||||
)
|
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
dispatch({ type: types.PREPARE_SHAPE_SHIFT_FAIL, data: err });
|
dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_FAIL, data: err });
|
||||||
// for formik to stop the submit
|
// for formik to stop the submit
|
||||||
actions.setSubmitting(false);
|
actions.setSubmitting(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getActiveShift = (depositAddress: string) => (
|
export const getActiveShift = (depositAddress: string) => (dispatch: Dispatch): ThunkAction => {
|
||||||
dispatch: Dispatch
|
dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_START });
|
||||||
): ThunkAction => {
|
|
||||||
dispatch({ type: types.GET_ACTIVE_SHIFT_START });
|
|
||||||
|
|
||||||
return shapeShift
|
return shapeShift
|
||||||
.statusAsync(depositAddress)
|
.statusAsync(depositAddress)
|
||||||
.then(res => dispatch({ type: types.GET_ACTIVE_SHIFT_SUCCESS, data: res }))
|
.then(res => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_SUCCESS, data: res }))
|
||||||
.catch(err => dispatch({ type: types.GET_ACTIVE_SHIFT_FAIL, data: err }));
|
.catch(err => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_FAIL, data: err }));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clearShapeShift = () => (dispatch: Dispatch): Action =>
|
export const clearShapeShift = () => (dispatch: Dispatch): Action =>
|
||||||
dispatch({ type: types.CLEAR_SHAPE_SHIFT });
|
dispatch({ type: ACTIONS.CLEAR_SHAPE_SHIFT });
|
||||||
|
|
|
@ -1,27 +1,18 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as actions from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import type {
|
import type { Subscription, Dispatch } from 'redux/reducers/subscriptions';
|
||||||
Subscription,
|
|
||||||
Action,
|
|
||||||
Dispatch,
|
|
||||||
} from "redux/reducers/subscriptions";
|
|
||||||
import lbry from "lbry";
|
|
||||||
|
|
||||||
export const doChannelSubscribe = (subscription: Subscription) => (
|
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) =>
|
||||||
dispatch: Dispatch
|
|
||||||
) =>
|
|
||||||
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
|
|
||||||
) =>
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: actions.CHANNEL_UNSUBSCRIBE,
|
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||||
data: subscription,
|
data: subscription,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) =>
|
export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) =>
|
||||||
dispatch({ type: actions.HAS_FETCHED_SUBSCRIPTIONS });
|
dispatch({ type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS });
|
||||||
|
|
|
@ -1,30 +1,54 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as modals from "constants/modal_types";
|
import * as MODALS from 'constants/modal_types';
|
||||||
import lbryio from "lbryio";
|
import Lbryio from 'lbryio';
|
||||||
import { doOpenModal, doShowSnackBar } from "redux/actions/app";
|
import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
||||||
import { doRewardList, doClaimRewardType } from "redux/actions/rewards";
|
import { doRewardList, doClaimRewardType } from 'redux/actions/rewards';
|
||||||
import { selectEmailToVerify, selectUser } from "redux/selectors/user";
|
import { selectEmailToVerify } from 'redux/selectors/user';
|
||||||
import rewards from "rewards";
|
import rewards from 'rewards';
|
||||||
|
|
||||||
|
export function doFetchInviteStatus() {
|
||||||
|
return function(dispatch) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.USER_INVITE_STATUS_FETCH_STARTED,
|
||||||
|
});
|
||||||
|
|
||||||
|
Lbryio.call('user', 'invite_status')
|
||||||
|
.then(status => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS,
|
||||||
|
data: {
|
||||||
|
invitesRemaining: status.invites_remaining ? status.invites_remaining : 0,
|
||||||
|
invitees: status.invitees,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE,
|
||||||
|
data: { error },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function doAuthenticate() {
|
export function doAuthenticate() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.AUTHENTICATION_STARTED,
|
type: ACTIONS.AUTHENTICATION_STARTED,
|
||||||
});
|
});
|
||||||
lbryio
|
Lbryio.authenticate()
|
||||||
.authenticate()
|
|
||||||
.then(user => {
|
.then(user => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.AUTHENTICATION_SUCCESS,
|
type: ACTIONS.AUTHENTICATION_SUCCESS,
|
||||||
data: { user },
|
data: { user },
|
||||||
});
|
});
|
||||||
dispatch(doRewardList());
|
dispatch(doRewardList());
|
||||||
dispatch(doFetchInviteStatus());
|
dispatch(doFetchInviteStatus());
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch(doOpenModal(modals.AUTHENTICATION_FAILURE));
|
dispatch(doOpenModal(MODALS.AUTHENTICATION_FAILURE));
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.AUTHENTICATION_FAILURE,
|
type: ACTIONS.AUTHENTICATION_FAILURE,
|
||||||
data: { error },
|
data: { error },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -32,23 +56,22 @@ export function doAuthenticate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUserFetch() {
|
export function doUserFetch() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_FETCH_STARTED,
|
type: ACTIONS.USER_FETCH_STARTED,
|
||||||
});
|
});
|
||||||
lbryio
|
Lbryio.getCurrentUser()
|
||||||
.getCurrentUser()
|
|
||||||
.then(user => {
|
.then(user => {
|
||||||
dispatch(doRewardList());
|
dispatch(doRewardList());
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_FETCH_SUCCESS,
|
type: ACTIONS.USER_FETCH_SUCCESS,
|
||||||
data: { user },
|
data: { user },
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_FETCH_FAILURE,
|
type: ACTIONS.USER_FETCH_FAILURE,
|
||||||
data: { error },
|
data: { error },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -56,15 +79,15 @@ export function doUserFetch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUserEmailNew(email) {
|
export function doUserEmailNew(email) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_EMAIL_NEW_STARTED,
|
type: ACTIONS.USER_EMAIL_NEW_STARTED,
|
||||||
email,
|
email,
|
||||||
});
|
});
|
||||||
|
|
||||||
const success = () => {
|
const success = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_EMAIL_NEW_SUCCESS,
|
type: ACTIONS.USER_EMAIL_NEW_SUCCESS,
|
||||||
data: { email },
|
data: { email },
|
||||||
});
|
});
|
||||||
dispatch(doUserFetch());
|
dispatch(doUserFetch());
|
||||||
|
@ -72,28 +95,20 @@ export function doUserEmailNew(email) {
|
||||||
|
|
||||||
const failure = error => {
|
const failure = error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_EMAIL_NEW_FAILURE,
|
type: ACTIONS.USER_EMAIL_NEW_FAILURE,
|
||||||
data: { error },
|
data: { error },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbryio
|
Lbryio.call('user_email', 'new', { email, send_verification_email: true }, 'post')
|
||||||
.call(
|
|
||||||
"user_email",
|
|
||||||
"new",
|
|
||||||
{ email, send_verification_email: true },
|
|
||||||
"post"
|
|
||||||
)
|
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (error.response && error.response.status == 409) {
|
if (error.response && error.response.status === 409) {
|
||||||
return lbryio
|
return Lbryio.call(
|
||||||
.call(
|
'user_email',
|
||||||
"user_email",
|
'resend_token',
|
||||||
"resend_token",
|
{ email, only_if_expired: true },
|
||||||
{ email, only_if_expired: true },
|
'post'
|
||||||
"post"
|
).then(success, failure);
|
||||||
)
|
|
||||||
.then(success, failure);
|
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
})
|
})
|
||||||
|
@ -104,35 +119,34 @@ export function doUserEmailNew(email) {
|
||||||
export function doUserEmailVerify(verificationToken) {
|
export function doUserEmailVerify(verificationToken) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const email = selectEmailToVerify(getState());
|
const email = selectEmailToVerify(getState());
|
||||||
verificationToken = verificationToken.toString().trim();
|
const trimmedVerificationToken = verificationToken.toString().trim();
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_EMAIL_VERIFY_STARTED,
|
type: ACTIONS.USER_EMAIL_VERIFY_STARTED,
|
||||||
code: verificationToken,
|
code: trimmedVerificationToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbryio
|
Lbryio.call(
|
||||||
.call(
|
'user_email',
|
||||||
"user_email",
|
'confirm',
|
||||||
"confirm",
|
{ verification_token: trimmedVerificationToken, email },
|
||||||
{ verification_token: verificationToken, email },
|
'post'
|
||||||
"post"
|
)
|
||||||
)
|
|
||||||
.then(userEmail => {
|
.then(userEmail => {
|
||||||
if (userEmail.is_verified) {
|
if (userEmail.is_verified) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_EMAIL_VERIFY_SUCCESS,
|
type: ACTIONS.USER_EMAIL_VERIFY_SUCCESS,
|
||||||
data: { email },
|
data: { email },
|
||||||
});
|
});
|
||||||
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 => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_EMAIL_VERIFY_FAILURE,
|
type: ACTIONS.USER_EMAIL_VERIFY_FAILURE,
|
||||||
data: { error },
|
data: { error },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -140,30 +154,27 @@ export function doUserEmailVerify(verificationToken) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUserIdentityVerify(stripeToken) {
|
export function doUserIdentityVerify(stripeToken) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_IDENTITY_VERIFY_STARTED,
|
type: ACTIONS.USER_IDENTITY_VERIFY_STARTED,
|
||||||
token: stripeToken,
|
token: stripeToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbryio
|
Lbryio.call('user', 'verify_identity', { stripe_token: stripeToken }, 'post')
|
||||||
.call("user", "verify_identity", { stripe_token: stripeToken }, "post")
|
|
||||||
.then(user => {
|
.then(user => {
|
||||||
if (user.is_identity_verified) {
|
if (user.is_identity_verified) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_IDENTITY_VERIFY_SUCCESS,
|
type: ACTIONS.USER_IDENTITY_VERIFY_SUCCESS,
|
||||||
data: { user },
|
data: { user },
|
||||||
});
|
});
|
||||||
dispatch(doClaimRewardType(rewards.TYPE_NEW_USER));
|
dispatch(doClaimRewardType(rewards.TYPE_NEW_USER));
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error('Your identity is still not verified. This should not happen.'); // shouldn't happen
|
||||||
"Your identity is still not verified. This should not happen."
|
|
||||||
); // shouldn't happen
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_IDENTITY_VERIFY_FAILURE,
|
type: ACTIONS.USER_IDENTITY_VERIFY_FAILURE,
|
||||||
data: { error: error.toString() },
|
data: { error: error.toString() },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -171,61 +182,32 @@ export function doUserIdentityVerify(stripeToken) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchAccessToken() {
|
export function doFetchAccessToken() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
const success = token =>
|
const success = token =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_ACCESS_TOKEN_SUCCESS,
|
type: ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS,
|
||||||
data: { token },
|
data: { token },
|
||||||
});
|
});
|
||||||
lbryio.getAuthToken().then(success);
|
Lbryio.getAuthToken().then(success);
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doFetchInviteStatus() {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch({
|
|
||||||
type: types.USER_INVITE_STATUS_FETCH_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
lbryio
|
|
||||||
.call("user", "invite_status")
|
|
||||||
.then(status => {
|
|
||||||
dispatch({
|
|
||||||
type: types.USER_INVITE_STATUS_FETCH_SUCCESS,
|
|
||||||
data: {
|
|
||||||
invitesRemaining: status.invites_remaining
|
|
||||||
? status.invites_remaining
|
|
||||||
: 0,
|
|
||||||
invitees: status.invitees,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
dispatch({
|
|
||||||
type: types.USER_INVITE_STATUS_FETCH_FAILURE,
|
|
||||||
data: { error },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUserInviteNew(email) {
|
export function doUserInviteNew(email) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_INVITE_NEW_STARTED,
|
type: ACTIONS.USER_INVITE_NEW_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbryio
|
Lbryio.call('user', 'invite', { email }, 'post')
|
||||||
.call("user", "invite", { email }, "post")
|
.then(() => {
|
||||||
.then(invite => {
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_INVITE_NEW_SUCCESS,
|
type: ACTIONS.USER_INVITE_NEW_SUCCESS,
|
||||||
data: { email },
|
data: { email },
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
doShowSnackBar({
|
doShowSnackBar({
|
||||||
message: __("Invite sent to %s", email),
|
message: __('Invite sent to %s', email),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -233,7 +215,7 @@ export function doUserInviteNew(email) {
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.USER_INVITE_NEW_FAILURE,
|
type: ACTIONS.USER_INVITE_NEW_FAILURE,
|
||||||
data: { error },
|
data: { error },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbry from "lbry";
|
import Lbry from 'lbry';
|
||||||
import {
|
import {
|
||||||
selectDraftTransaction,
|
selectDraftTransaction,
|
||||||
selectDraftTransactionAmount,
|
selectDraftTransactionAmount,
|
||||||
selectBalance,
|
selectBalance,
|
||||||
} from "redux/selectors/wallet";
|
} from 'redux/selectors/wallet';
|
||||||
import { doOpenModal, doShowSnackBar } from "redux/actions/app";
|
import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
||||||
import { doNavigate } from "redux/actions/navigation";
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import * as modals from "constants/modal_types";
|
import * as MODALS from 'constants/modal_types';
|
||||||
|
|
||||||
export function doUpdateBalance() {
|
export function doUpdateBalance() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
lbry.wallet_balance().then(balance =>
|
Lbry.wallet_balance().then(balance =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.UPDATE_BALANCE,
|
type: ACTIONS.UPDATE_BALANCE,
|
||||||
data: {
|
data: {
|
||||||
balance,
|
balance,
|
||||||
},
|
},
|
||||||
|
@ -23,36 +23,34 @@ export function doUpdateBalance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doBalanceSubscribe() {
|
export function doBalanceSubscribe() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch(doUpdateBalance());
|
dispatch(doUpdateBalance());
|
||||||
setInterval(() => dispatch(doUpdateBalance()), 5000);
|
setInterval(() => dispatch(doUpdateBalance()), 5000);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchTransactions(fetch_tip_info = true) {
|
export function doFetchTransactions(fetch_tip_info = true) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_TRANSACTIONS_STARTED,
|
type: ACTIONS.FETCH_TRANSACTIONS_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry
|
Lbry.transaction_list({ include_tip_info: fetch_tip_info }).then(results => {
|
||||||
.transaction_list({ include_tip_info: fetch_tip_info })
|
dispatch({
|
||||||
.then(results => {
|
type: ACTIONS.FETCH_TRANSACTIONS_COMPLETED,
|
||||||
dispatch({
|
data: {
|
||||||
type: types.FETCH_TRANSACTIONS_COMPLETED,
|
transactions: results,
|
||||||
data: {
|
},
|
||||||
transactions: results,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchBlock(height) {
|
export function doFetchBlock(height) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
lbry.block_show({ height }).then(block => {
|
Lbry.block_show({ height }).then(block => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_BLOCK_SUCCESS,
|
type: ACTIONS.FETCH_BLOCK_SUCCESS,
|
||||||
data: { block },
|
data: { block },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -60,15 +58,15 @@ export function doFetchBlock(height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doGetNewAddress() {
|
export function doGetNewAddress() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.GET_NEW_ADDRESS_STARTED,
|
type: ACTIONS.GET_NEW_ADDRESS_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.wallet_new_address().then(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: ACTIONS.GET_NEW_ADDRESS_COMPLETED,
|
||||||
data: { address },
|
data: { address },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -76,16 +74,16 @@ export function doGetNewAddress() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doCheckAddressIsMine(address) {
|
export function doCheckAddressIsMine(address) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHECK_ADDRESS_IS_MINE_STARTED,
|
type: ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.wallet_is_address_mine({ address }).then(isMine => {
|
Lbry.wallet_is_address_mine({ address }).then(isMine => {
|
||||||
if (!isMine) dispatch(doGetNewAddress());
|
if (!isMine) dispatch(doGetNewAddress());
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CHECK_ADDRESS_IS_MINE_COMPLETED,
|
type: ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -99,113 +97,111 @@ export function doSendDraftTransaction() {
|
||||||
const amount = selectDraftTransactionAmount(state);
|
const amount = selectDraftTransactionAmount(state);
|
||||||
|
|
||||||
if (balance - amount <= 0) {
|
if (balance - amount <= 0) {
|
||||||
return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
|
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEND_TRANSACTION_STARTED,
|
type: ACTIONS.SEND_TRANSACTION_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
const successCallback = results => {
|
const successCallback = results => {
|
||||||
if (results === true) {
|
if (results === true) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEND_TRANSACTION_COMPLETED,
|
type: ACTIONS.SEND_TRANSACTION_COMPLETED,
|
||||||
});
|
});
|
||||||
dispatch(
|
dispatch(
|
||||||
doShowSnackBar({
|
doShowSnackBar({
|
||||||
message: __(`You sent ${amount} LBC`),
|
message: __(`You sent ${amount} LBC`),
|
||||||
linkText: __("History"),
|
linkText: __('History'),
|
||||||
linkTarget: __("/wallet"),
|
linkTarget: __('/wallet'),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEND_TRANSACTION_FAILED,
|
type: ACTIONS.SEND_TRANSACTION_FAILED,
|
||||||
data: { error: results },
|
data: { error: results },
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const errorCallback = error => {
|
const errorCallback = error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEND_TRANSACTION_FAILED,
|
type: ACTIONS.SEND_TRANSACTION_FAILED,
|
||||||
data: { error: error.message },
|
data: { error: error.message },
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry
|
Lbry.wallet_send({
|
||||||
.wallet_send({
|
amount: draftTx.amount,
|
||||||
amount: draftTx.amount,
|
address: draftTx.address,
|
||||||
address: draftTx.address,
|
}).then(successCallback, errorCallback);
|
||||||
})
|
|
||||||
.then(successCallback, errorCallback);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doSetDraftTransactionAmount(amount) {
|
export function doSetDraftTransactionAmount(amount) {
|
||||||
return {
|
return {
|
||||||
type: types.SET_DRAFT_TRANSACTION_AMOUNT,
|
type: ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT,
|
||||||
data: { amount },
|
data: { amount },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doSetDraftTransactionAddress(address) {
|
export function doSetDraftTransactionAddress(address) {
|
||||||
return {
|
return {
|
||||||
type: types.SET_DRAFT_TRANSACTION_ADDRESS,
|
type: ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS,
|
||||||
data: { address },
|
data: { address },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doSendSupport(amount, claim_id, uri) {
|
export function doSendSupport(amount, claimId, uri) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const balance = selectBalance(state);
|
const balance = selectBalance(state);
|
||||||
|
|
||||||
if (balance - amount <= 0) {
|
if (balance - amount <= 0) {
|
||||||
return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
|
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SUPPORT_TRANSACTION_STARTED,
|
type: ACTIONS.SUPPORT_TRANSACTION_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
const successCallback = results => {
|
const successCallback = results => {
|
||||||
if (results.txid) {
|
if (results.txid) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SUPPORT_TRANSACTION_COMPLETED,
|
type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED,
|
||||||
});
|
});
|
||||||
dispatch(
|
dispatch(
|
||||||
doShowSnackBar({
|
doShowSnackBar({
|
||||||
message: __(`You sent ${amount} LBC as support, Mahalo!`),
|
message: __(`You sent ${amount} LBC as support, Mahalo!`),
|
||||||
linkText: __("History"),
|
linkText: __('History'),
|
||||||
linkTarget: __("/wallet"),
|
linkTarget: __('/wallet'),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
dispatch(doNavigate("/show", { uri }));
|
dispatch(doNavigate('/show', { uri }));
|
||||||
} else {
|
} else {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SUPPORT_TRANSACTION_FAILED,
|
type: ACTIONS.SUPPORT_TRANSACTION_FAILED,
|
||||||
data: { error: results.code },
|
data: { error: results.code },
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const errorCallback = error => {
|
const errorCallback = error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SUPPORT_TRANSACTION_FAILED,
|
type: ACTIONS.SUPPORT_TRANSACTION_FAILED,
|
||||||
data: { error: error.code },
|
data: { error: error.code },
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry
|
Lbry.wallet_send({
|
||||||
.wallet_send({
|
claimId,
|
||||||
claim_id,
|
amount,
|
||||||
amount,
|
}).then(successCallback, errorCallback);
|
||||||
})
|
|
||||||
.then(successCallback, errorCallback);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as modalTypes from "constants/modal_types";
|
import * as MODALS from 'constants/modal_types';
|
||||||
|
|
||||||
const { remote } = require("electron");
|
const { remote } = require('electron');
|
||||||
|
|
||||||
const application = remote.app;
|
|
||||||
const win = remote.BrowserWindow.getFocusedWindow();
|
const win = remote.BrowserWindow.getFocusedWindow();
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
|
@ -41,12 +40,12 @@ const defaultState: AppState = {
|
||||||
modal: null,
|
modal: null,
|
||||||
modalProps: {},
|
modalProps: {},
|
||||||
platform: process.platform,
|
platform: process.platform,
|
||||||
upgradeSkipped: sessionStorage.getItem("upgradeSkipped") === "true",
|
upgradeSkipped: sessionStorage.getItem('upgradeSkipped') === 'true',
|
||||||
daemonVersionMatched: null,
|
daemonVersionMatched: null,
|
||||||
daemonReady: false,
|
daemonReady: false,
|
||||||
hasSignature: false,
|
hasSignature: false,
|
||||||
badgeNumber: 0,
|
badgeNumber: 0,
|
||||||
volume: Number(sessionStorage.getItem("volume")) || 1,
|
volume: Number(sessionStorage.getItem('volume')) || 1,
|
||||||
|
|
||||||
downloadProgress: undefined,
|
downloadProgress: undefined,
|
||||||
upgradeDownloading: undefined,
|
upgradeDownloading: undefined,
|
||||||
|
@ -57,26 +56,26 @@ const defaultState: AppState = {
|
||||||
snackBar: undefined,
|
snackBar: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DAEMON_READY] = function(state, action) {
|
reducers[ACTIONS.DAEMON_READY] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
daemonReady: true,
|
daemonReady: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DAEMON_VERSION_MATCH] = function(state, action) {
|
reducers[ACTIONS.DAEMON_VERSION_MATCH] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
daemonVersionMatched: true,
|
daemonVersionMatched: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DAEMON_VERSION_MISMATCH] = function(state, action) {
|
reducers[ACTIONS.DAEMON_VERSION_MISMATCH] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
daemonVersionMatched: false,
|
daemonVersionMatched: false,
|
||||||
modal: modalTypes.INCOMPATIBLE_DAEMON,
|
modal: MODALS.INCOMPATIBLE_DAEMON,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.UPGRADE_CANCELLED] = function(state, action) {
|
reducers[ACTIONS.UPGRADE_CANCELLED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
downloadProgress: null,
|
downloadProgress: null,
|
||||||
upgradeDownloadComplete: false,
|
upgradeDownloadComplete: false,
|
||||||
|
@ -84,7 +83,7 @@ reducers[types.UPGRADE_CANCELLED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
downloadPath: action.data.path,
|
downloadPath: action.data.path,
|
||||||
upgradeDownloading: false,
|
upgradeDownloading: false,
|
||||||
|
@ -92,14 +91,14 @@ reducers[types.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.UPGRADE_DOWNLOAD_STARTED] = function(state, action) {
|
reducers[ACTIONS.UPGRADE_DOWNLOAD_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
upgradeDownloading: true,
|
upgradeDownloading: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SKIP_UPGRADE] = function(state, action) {
|
reducers[ACTIONS.SKIP_UPGRADE] = function(state) {
|
||||||
sessionStorage.setItem("upgradeSkipped", "true");
|
sessionStorage.setItem('upgradeSkipped', 'true');
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
isUpgradeSkipped: true,
|
isUpgradeSkipped: true,
|
||||||
|
@ -107,46 +106,46 @@ reducers[types.SKIP_UPGRADE] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.UPDATE_VERSION] = function(state, action) {
|
reducers[ACTIONS.UPDATE_VERSION] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
version: action.data.version,
|
version: action.data.version,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CHECK_UPGRADE_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.CHECK_UPGRADE_SUCCESS] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
isUpgradeAvailable: action.data.upgradeAvailable,
|
isUpgradeAvailable: action.data.upgradeAvailable,
|
||||||
remoteVersion: action.data.remoteVersion,
|
remoteVersion: action.data.remoteVersion,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) {
|
reducers[ACTIONS.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
checkUpgradeTimer: action.data.checkUpgradeTimer,
|
checkUpgradeTimer: action.data.checkUpgradeTimer,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.OPEN_MODAL] = function(state, action) {
|
reducers[ACTIONS.OPEN_MODAL] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
modal: action.data.modal,
|
modal: action.data.modal,
|
||||||
modalProps: action.data.modalProps || {},
|
modalProps: action.data.modalProps || {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CLOSE_MODAL] = function(state, action) {
|
reducers[ACTIONS.CLOSE_MODAL] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
modal: undefined,
|
modal: undefined,
|
||||||
modalProps: {},
|
modalProps: {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) {
|
reducers[ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
downloadProgress: action.data.percent,
|
downloadProgress: action.data.percent,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SHOW_SNACKBAR] = function(state, action) {
|
reducers[ACTIONS.SHOW_SNACKBAR] = function(state, action) {
|
||||||
const { message, linkText, linkTarget, isError } = action.data;
|
const { message, linkText, linkTarget, isError } = action.data;
|
||||||
const snackBar = Object.assign({}, state.snackBar);
|
const snackBar = Object.assign({}, state.snackBar);
|
||||||
const snacks = Object.assign([], snackBar.snacks);
|
const snacks = Object.assign([], snackBar.snacks);
|
||||||
|
@ -165,7 +164,7 @@ reducers[types.SHOW_SNACKBAR] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) {
|
reducers[ACTIONS.REMOVE_SNACKBAR_SNACK] = function(state) {
|
||||||
const snackBar = Object.assign({}, state.snackBar);
|
const snackBar = Object.assign({}, state.snackBar);
|
||||||
const snacks = Object.assign([], snackBar.snacks);
|
const snacks = Object.assign([], snackBar.snacks);
|
||||||
snacks.shift();
|
snacks.shift();
|
||||||
|
@ -179,8 +178,8 @@ reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state) {
|
||||||
const badgeNumber = state.badgeNumber;
|
const { badgeNumber } = state;
|
||||||
|
|
||||||
// Don't update the badge number if the window is focused
|
// Don't update the badge number if the window is focused
|
||||||
if (win && win.isFocused()) return Object.assign({}, state);
|
if (win && win.isFocused()) return Object.assign({}, state);
|
||||||
|
@ -190,13 +189,13 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.WINDOW_FOCUSED] = function(state, action) {
|
reducers[ACTIONS.WINDOW_FOCUSED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
badgeNumber: 0,
|
badgeNumber: 0,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.VOLUME_CHANGED] = function(state, action) {
|
reducers[ACTIONS.VOLUME_CHANGED] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
volume: action.data.volume,
|
volume: action.data.volume,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {};
|
const defaultState = {};
|
||||||
|
|
||||||
reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_AVAILABILITY_STARTED] = function(state, action) {
|
||||||
const { uri } = action.data;
|
const { uri } = action.data;
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
const newFetching = Object.assign({}, state.fetching);
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_AVAILABILITY_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_AVAILABILITY_COMPLETED] = function(state, action) {
|
||||||
const { uri, availability } = action.data;
|
const { uri, availability } = action.data;
|
||||||
|
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
const newFetching = Object.assign({}, state.fetching);
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
|
|
||||||
const defaultState = {};
|
const defaultState = {};
|
||||||
|
|
||||||
reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||||
const { resolveInfo } = action.data;
|
const { resolveInfo } = action.data;
|
||||||
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 (const [uri, { certificate, claim }] of Object.entries(resolveInfo)) {
|
Object.entries(resolveInfo).forEach(([uri, { certificate, claim }]) => {
|
||||||
if (claim) {
|
if (claim) {
|
||||||
byId[claim.claim_id] = claim;
|
byId[claim.claim_id] = claim;
|
||||||
byUri[uri] = claim.claim_id;
|
byUri[uri] = claim.claim_id;
|
||||||
|
@ -25,7 +25,7 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||||
} else {
|
} else {
|
||||||
byUri[uri] = null;
|
byUri[uri] = null;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
byId,
|
byId,
|
||||||
|
@ -33,37 +33,32 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_CLAIM_LIST_MINE_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
isFetchingClaimListMine: true,
|
isFetchingClaimListMine: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
|
||||||
const { claims } = action.data;
|
const { claims } = action.data;
|
||||||
const byUri = Object.assign({}, state.claimsByUri);
|
|
||||||
const byId = Object.assign({}, state.byId);
|
const byId = Object.assign({}, state.byId);
|
||||||
const pendingById = Object.assign({}, state.pendingById);
|
const pendingById = Object.assign({}, state.pendingById);
|
||||||
const abandoningById = Object.assign({}, state.abandoningById);
|
|
||||||
|
|
||||||
claims
|
claims.filter(claim => claim.category && claim.category.match(/claim/)).forEach(claim => {
|
||||||
.filter(claim => claim.category && claim.category.match(/claim/))
|
byId[claim.claim_id] = claim;
|
||||||
.forEach(claim => {
|
|
||||||
byId[claim.claim_id] = claim;
|
|
||||||
|
|
||||||
const pending = Object.values(pendingById).find(
|
const pending = Object.values(pendingById).find(
|
||||||
pendingClaim =>
|
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];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove old timed out pending publishes
|
// Remove old timed out pending publishes
|
||||||
const old = Object.values(pendingById)
|
Object.values(pendingById)
|
||||||
.filter(pendingClaim => Date.now() - pendingClaim.time >= 20 * 60 * 1000)
|
.filter(pendingClaim => Date.now() - pendingClaim.time >= 20 * 60 * 1000)
|
||||||
.forEach(pendingClaim => {
|
.forEach(pendingClaim => {
|
||||||
delete pendingById[pendingClaim.claim_id];
|
delete pendingById[pendingClaim.claim_id];
|
||||||
|
@ -77,11 +72,11 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, { fetchingMyChannels: true });
|
return Object.assign({}, state, { fetchingMyChannels: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) {
|
||||||
const { claims } = action.data;
|
const { claims } = action.data;
|
||||||
const myChannelClaims = new Set(state.myChannelClaims);
|
const myChannelClaims = new Set(state.myChannelClaims);
|
||||||
const byId = Object.assign({}, state.byId);
|
const byId = Object.assign({}, state.byId);
|
||||||
|
@ -98,7 +93,7 @@ reducers[types.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
|
||||||
const { uri, page } = action.data;
|
const { uri, page } = action.data;
|
||||||
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
|
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
|
||||||
|
|
||||||
|
@ -109,7 +104,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
||||||
const { uri, claims, page } = action.data;
|
const { uri, claims, page } = action.data;
|
||||||
|
|
||||||
const claimsByChannel = Object.assign({}, state.claimsByChannel);
|
const claimsByChannel = Object.assign({}, state.claimsByChannel);
|
||||||
|
@ -139,7 +134,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) {
|
reducers[ACTIONS.ABANDON_CLAIM_STARTED] = function(state, action) {
|
||||||
const { claimId } = action.data;
|
const { claimId } = action.data;
|
||||||
const abandoningById = Object.assign({}, state.abandoningById);
|
const abandoningById = Object.assign({}, state.abandoningById);
|
||||||
|
|
||||||
|
@ -150,7 +145,7 @@ reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
|
reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
|
||||||
const { claimId } = action.data;
|
const { claimId } = action.data;
|
||||||
const byId = Object.assign({}, state.byId);
|
const byId = Object.assign({}, state.byId);
|
||||||
const claimsByUri = Object.assign({}, state.claimsByUri);
|
const claimsByUri = Object.assign({}, state.claimsByUri);
|
||||||
|
@ -169,7 +164,7 @@ reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = function(state, action) {
|
||||||
const { channelClaim } = action.data;
|
const { channelClaim } = action.data;
|
||||||
const byId = Object.assign({}, state.byId);
|
const byId = Object.assign({}, state.byId);
|
||||||
const myChannelClaims = new Set(state.myChannelClaims);
|
const myChannelClaims = new Set(state.myChannelClaims);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
@ -7,13 +7,13 @@ const defaultState = {
|
||||||
channelClaimCounts: {},
|
channelClaimCounts: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_FEATURED_CONTENT_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_FEATURED_CONTENT_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
fetchingFeaturedContent: true,
|
fetchingFeaturedContent: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
||||||
const { uris, success } = action.data;
|
const { uris, success } = action.data;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
|
@ -23,42 +23,40 @@ reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) {
|
||||||
const { claimIds, success } = action.data;
|
const { claimIds } = action.data;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
rewardedContentClaimIds: claimIds,
|
rewardedContentClaimIds: claimIds,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.RESOLVE_URIS_STARTED] = function(state, action) {
|
reducers[ACTIONS.RESOLVE_URIS_STARTED] = function(state, action) {
|
||||||
const { 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 (const uri of uris) {
|
uris.forEach(uri => {
|
||||||
if (!newResolving.includes(uri)) {
|
if (!newResolving.includes(uri)) {
|
||||||
newResolving.push(uri);
|
newResolving.push(uri);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
resolvingUris: newResolving,
|
resolvingUris: newResolving,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.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 (const [uri, { certificate, claims_in_channel }] of Object.entries(
|
Object.entries(resolveInfo).forEach(([uri, { certificate, claimsInChannel }]) => {
|
||||||
resolveInfo
|
if (certificate && !Number.isNaN(claimsInChannel)) {
|
||||||
)) {
|
channelClaimCounts[uri] = claimsInChannel;
|
||||||
if (certificate && !isNaN(claims_in_channel)) {
|
|
||||||
channelClaimCounts[uri] = claims_in_channel;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
channelClaimCounts,
|
channelClaimCounts,
|
||||||
|
@ -66,12 +64,12 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SET_PLAYING_URI] = (state, action) =>
|
reducers[ACTIONS.SET_PLAYING_URI] = (state, action) =>
|
||||||
Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
playingUri: action.data.uri,
|
playingUri: action.data.uri,
|
||||||
});
|
});
|
||||||
|
|
||||||
reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
|
||||||
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
|
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
|
||||||
const { uri, totalClaims } = action.data;
|
const { uri, totalClaims } = action.data;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {};
|
const defaultState = {};
|
||||||
|
|
||||||
reducers[types.FETCH_COST_INFO_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_COST_INFO_STARTED] = function(state, action) {
|
||||||
const { uri } = action.data;
|
const { uri } = action.data;
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
const newFetching = Object.assign({}, state.fetching);
|
||||||
newFetching[uri] = true;
|
newFetching[uri] = true;
|
||||||
|
@ -13,7 +13,7 @@ reducers[types.FETCH_COST_INFO_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_COST_INFO_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_COST_INFO_COMPLETED] = function(state, action) {
|
||||||
const { uri, costInfo } = action.data;
|
const { uri, costInfo } = action.data;
|
||||||
const newByUri = Object.assign({}, state.byUri);
|
const newByUri = Object.assign({}, state.byUri);
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
const newFetching = Object.assign({}, state.fetching);
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import lbryuri from "lbryuri";
|
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {};
|
const defaultState = {};
|
||||||
|
|
||||||
reducers[types.FILE_LIST_STARTED] = function(state, action) {
|
reducers[ACTIONS.FILE_LIST_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
isFetchingFileList: true,
|
isFetchingFileList: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FILE_LIST_SUCCEEDED] = function(state, action) {
|
reducers[ACTIONS.FILE_LIST_SUCCEEDED] = function(state, action) {
|
||||||
const { fileInfos } = action.data;
|
const { fileInfos } = action.data;
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint);
|
const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint);
|
||||||
|
@ -28,7 +27,7 @@ reducers[types.FILE_LIST_SUCCEEDED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_FILE_INFO_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_FILE_INFO_STARTED] = function(state, action) {
|
||||||
const { outpoint } = action.data;
|
const { outpoint } = action.data;
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
const newFetching = Object.assign({}, state.fetching);
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ reducers[types.FETCH_FILE_INFO_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_FILE_INFO_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = function(state, action) {
|
||||||
const { fileInfo, outpoint } = action.data;
|
const { fileInfo, outpoint } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
|
@ -54,7 +53,7 @@ reducers[types.FETCH_FILE_INFO_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DOWNLOADING_STARTED] = function(state, action) {
|
reducers[ACTIONS.DOWNLOADING_STARTED] = function(state, action) {
|
||||||
const { uri, outpoint, fileInfo } = action.data;
|
const { uri, outpoint, fileInfo } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
|
@ -72,8 +71,8 @@ reducers[types.DOWNLOADING_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) {
|
reducers[ACTIONS.DOWNLOADING_PROGRESSED] = function(state, action) {
|
||||||
const { uri, outpoint, fileInfo } = action.data;
|
const { outpoint, fileInfo } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||||
|
@ -87,8 +86,8 @@ reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||||
const { uri, outpoint, fileInfo } = action.data;
|
const { outpoint, fileInfo } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||||
|
@ -102,7 +101,7 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FILE_DELETE] = function(state, action) {
|
reducers[ACTIONS.FILE_DELETE] = function(state, action) {
|
||||||
const { outpoint } = action.data;
|
const { outpoint } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
|
@ -117,7 +116,7 @@ reducers[types.FILE_DELETE] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.LOADING_VIDEO_STARTED] = function(state, action) {
|
reducers[ACTIONS.LOADING_VIDEO_STARTED] = function(state, action) {
|
||||||
const { uri } = action.data;
|
const { uri } = action.data;
|
||||||
|
|
||||||
const newLoading = Object.assign({}, state.urisLoading);
|
const newLoading = Object.assign({}, state.urisLoading);
|
||||||
|
@ -129,7 +128,7 @@ reducers[types.LOADING_VIDEO_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.LOADING_VIDEO_FAILED] = function(state, action) {
|
reducers[ACTIONS.LOADING_VIDEO_FAILED] = function(state, action) {
|
||||||
const { uri } = action.data;
|
const { uri } = action.data;
|
||||||
|
|
||||||
const newLoading = Object.assign({}, state.urisLoading);
|
const newLoading = Object.assign({}, state.urisLoading);
|
||||||
|
@ -141,13 +140,14 @@ reducers[types.LOADING_VIDEO_FAILED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_DATE] = function(state, action) {
|
reducers[ACTIONS.FETCH_DATE] = function(state, action) {
|
||||||
const { time } = action.data;
|
const { time } = action.data;
|
||||||
if (time) {
|
if (time) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
publishedDate: time,
|
publishedDate: time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
export default function reducer(state = defaultState, action) {
|
||||||
|
|
|
@ -1,38 +1,36 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { parseQueryParams } from "util/query_params";
|
|
||||||
|
|
||||||
const currentPath = () => {
|
const getCurrentPath = () => {
|
||||||
const hash = document.location.hash;
|
const { hash } = document.location;
|
||||||
if (hash !== "") return hash.replace(/^#/, "");
|
if (hash !== '') return hash.replace(/^#/, '');
|
||||||
return "/discover";
|
return '/discover';
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
currentPath: currentPath(),
|
currentPath: getCurrentPath(),
|
||||||
pathAfterAuth: "/discover",
|
pathAfterAuth: '/discover',
|
||||||
index: 0,
|
index: 0,
|
||||||
stack: [],
|
stack: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DAEMON_READY] = function(state, action) {
|
reducers[ACTIONS.DAEMON_READY] = function(state) {
|
||||||
const { currentPath } = state;
|
const { currentPath } = state;
|
||||||
const params = parseQueryParams(currentPath.split("?")[1] || "");
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
stack: [{ path: currentPath, scrollY: 0 }],
|
stack: [{ path: currentPath, scrollY: 0 }],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CHANGE_AFTER_AUTH_PATH] = function(state, action) {
|
reducers[ACTIONS.CHANGE_AFTER_AUTH_PATH] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
pathAfterAuth: action.data.path,
|
pathAfterAuth: action.data.path,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.HISTORY_NAVIGATE] = (state, action) => {
|
reducers[ACTIONS.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 } = action.data;
|
||||||
|
|
||||||
const newState = {
|
const newState = {
|
||||||
currentPath: path,
|
currentPath: path,
|
||||||
|
@ -46,12 +44,11 @@ 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
|
|
||||||
return Object.assign({}, state, newState);
|
return Object.assign({}, state, newState);
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.WINDOW_SCROLLED] = (state, action) => {
|
reducers[ACTIONS.WINDOW_SCROLLED] = (state, action) => {
|
||||||
const { stack, index } = state;
|
const { index } = state;
|
||||||
const { scrollY } = action.data;
|
const { scrollY } = action.data;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
@ -9,17 +9,17 @@ const defaultState = {
|
||||||
claimErrorsByType: {},
|
claimErrorsByType: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_REWARDS_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_REWARDS_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
fetching: true,
|
fetching: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = function(state, action) {
|
||||||
const { userRewards } = action.data;
|
const { userRewards } = action.data;
|
||||||
|
|
||||||
let unclaimedRewards = {},
|
const unclaimedRewards = {};
|
||||||
claimedRewards = {};
|
const claimedRewards = {};
|
||||||
userRewards.forEach(reward => {
|
userRewards.forEach(reward => {
|
||||||
if (reward.transaction_id) {
|
if (reward.transaction_id) {
|
||||||
claimedRewards[reward.id] = reward;
|
claimedRewards[reward.id] = reward;
|
||||||
|
@ -35,7 +35,7 @@ reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function setClaimRewardState(state, reward, isClaiming, errorMessage = "") {
|
function setClaimRewardState(state, reward, isClaiming, errorMessage = '') {
|
||||||
const newClaimPendingByType = Object.assign({}, state.claimPendingByType);
|
const newClaimPendingByType = Object.assign({}, state.claimPendingByType);
|
||||||
const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType);
|
const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType);
|
||||||
if (isClaiming) {
|
if (isClaiming) {
|
||||||
|
@ -55,21 +55,17 @@ function setClaimRewardState(state, reward, isClaiming, errorMessage = "") {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reducers[types.CLAIM_REWARD_STARTED] = function(state, action) {
|
reducers[ACTIONS.CLAIM_REWARD_STARTED] = function(state, action) {
|
||||||
const { reward } = action.data;
|
const { reward } = action.data;
|
||||||
|
|
||||||
return setClaimRewardState(state, reward, true, "");
|
return setClaimRewardState(state, reward, true, '');
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = function(state, action) {
|
||||||
const { reward } = action.data;
|
const { reward } = action.data;
|
||||||
|
|
||||||
const unclaimedRewardsByType = Object.assign(
|
const unclaimedRewardsByType = Object.assign({}, state.unclaimedRewardsByType);
|
||||||
{},
|
|
||||||
state.unclaimedRewardsByType
|
|
||||||
);
|
|
||||||
const existingReward = unclaimedRewardsByType[reward.reward_type];
|
const existingReward = unclaimedRewardsByType[reward.reward_type];
|
||||||
delete state.unclaimedRewardsByType[reward.reward_type];
|
|
||||||
|
|
||||||
const newReward = Object.assign({}, reward, {
|
const newReward = Object.assign({}, reward, {
|
||||||
reward_title: existingReward.reward_title,
|
reward_title: existingReward.reward_title,
|
||||||
|
@ -84,24 +80,19 @@ reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) {
|
||||||
claimedRewardsById,
|
claimedRewardsById,
|
||||||
});
|
});
|
||||||
|
|
||||||
return setClaimRewardState(newState, newReward, false, "");
|
return setClaimRewardState(newState, newReward, false, '');
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CLAIM_REWARD_FAILURE] = function(state, action) {
|
reducers[ACTIONS.CLAIM_REWARD_FAILURE] = function(state, action) {
|
||||||
const { reward, error } = action.data;
|
const { reward, error } = action.data;
|
||||||
|
|
||||||
return setClaimRewardState(state, reward, false, error ? error.message : "");
|
return setClaimRewardState(state, reward, false, error ? error.message : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) {
|
reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) {
|
||||||
const { reward } = action.data;
|
const { reward } = action.data;
|
||||||
|
|
||||||
return setClaimRewardState(
|
return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], '');
|
||||||
state,
|
|
||||||
reward,
|
|
||||||
state.claimPendingByType[reward.reward_type],
|
|
||||||
""
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
export default function reducer(state = defaultState, action) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
@ -6,15 +6,13 @@ const defaultState = {
|
||||||
searching: false,
|
searching: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SEARCH_STARTED] = function(state, action) {
|
reducers[ACTIONS.SEARCH_STARTED] = function(state) {
|
||||||
const { query } = action.data;
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
searching: true,
|
searching: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SEARCH_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.SEARCH_COMPLETED] = function(state, action) {
|
||||||
const { query, uris } = action.data;
|
const { query, uris } = action.data;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
|
@ -23,7 +21,7 @@ reducers[types.SEARCH_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SEARCH_CANCELLED] = function(state, action) {
|
reducers[ACTIONS.SEARCH_CANCELLED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
searching: false,
|
searching: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as settings from "constants/settings";
|
import * as SETTINGS from 'constants/settings';
|
||||||
import LANGUAGES from "constants/languages";
|
import LANGUAGES from 'constants/languages';
|
||||||
|
|
||||||
function getLocalStorageSetting(setting, fallback) {
|
function getLocalStorageSetting(setting, fallback) {
|
||||||
const localStorageVal = localStorage.getItem(`setting_${setting}`);
|
const localStorageVal = localStorage.getItem(`setting_${setting}`);
|
||||||
|
@ -10,38 +10,30 @@ function getLocalStorageSetting(setting, fallback) {
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
clientSettings: {
|
clientSettings: {
|
||||||
instantPurchaseEnabled: getLocalStorageSetting(
|
instantPurchaseEnabled: getLocalStorageSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, false),
|
||||||
settings.INSTANT_PURCHASE_ENABLED,
|
instantPurchaseMax: getLocalStorageSetting(SETTINGS.INSTANT_PURCHASE_MAX, {
|
||||||
false
|
currency: 'LBC',
|
||||||
),
|
|
||||||
instantPurchaseMax: getLocalStorageSetting(settings.INSTANT_PURCHASE_MAX, {
|
|
||||||
currency: "LBC",
|
|
||||||
amount: 0.1,
|
amount: 0.1,
|
||||||
}),
|
}),
|
||||||
showNsfw: getLocalStorageSetting(settings.SHOW_NSFW, false),
|
showNsfw: getLocalStorageSetting(SETTINGS.SHOW_NSFW, false),
|
||||||
showUnavailable: getLocalStorageSetting(settings.SHOW_UNAVAILABLE, true),
|
showUnavailable: getLocalStorageSetting(SETTINGS.SHOW_UNAVAILABLE, true),
|
||||||
welcome_acknowledged: getLocalStorageSetting(
|
welcome_acknowledged: getLocalStorageSetting(SETTINGS.NEW_USER_ACKNOWLEDGED, false),
|
||||||
settings.NEW_USER_ACKNOWLEDGED,
|
email_collection_acknowledged: getLocalStorageSetting(SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED),
|
||||||
false
|
|
||||||
),
|
|
||||||
email_collection_acknowledged: getLocalStorageSetting(
|
|
||||||
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, []),
|
||||||
},
|
},
|
||||||
languages: {},
|
languages: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DAEMON_SETTINGS_RECEIVED] = function(state, action) {
|
reducers[ACTIONS.DAEMON_SETTINGS_RECEIVED] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
daemonSettings: action.data.settings,
|
daemonSettings: action.data.settings,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) {
|
reducers[ACTIONS.CLIENT_SETTING_CHANGED] = function(state, action) {
|
||||||
const { key, value } = action.data;
|
const { key, value } = action.data;
|
||||||
const clientSettings = Object.assign({}, state.clientSettings);
|
const clientSettings = Object.assign({}, state.clientSettings);
|
||||||
|
|
||||||
|
@ -55,16 +47,14 @@ reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
|
reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
|
||||||
const languages = Object.assign({}, state.languages);
|
const languages = Object.assign({}, state.languages);
|
||||||
const language = action.data.language;
|
const { language } = action.data;
|
||||||
|
|
||||||
const langCode = language.substring(0, 2);
|
const langCode = language.substring(0, 2);
|
||||||
|
|
||||||
if (LANGUAGES[langCode]) {
|
if (LANGUAGES[langCode]) {
|
||||||
languages[language] = `${LANGUAGES[langCode][0]} (${
|
languages[language] = `${LANGUAGES[langCode][0]} (${LANGUAGES[langCode][1]})`;
|
||||||
LANGUAGES[langCode][1]
|
|
||||||
})`;
|
|
||||||
} else {
|
} else {
|
||||||
languages[langCode] = langCode;
|
languages[langCode] = langCode;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +62,7 @@ reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
|
||||||
return Object.assign({}, state, { languages });
|
return Object.assign({}, state, { languages });
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) {
|
reducers[ACTIONS.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) {
|
||||||
const languages = Object.assign({}, state.languages);
|
const languages = Object.assign({}, state.languages);
|
||||||
delete languages[action.data.language];
|
delete languages[action.data.language];
|
||||||
return Object.assign({}, state, { languages });
|
return Object.assign({}, state, { languages });
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { handleActions } from "util/redux-utils";
|
import handleActions from 'util/redux-utils';
|
||||||
import * as actions from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as statuses from "constants/shape_shift";
|
import * as STATUSES from 'constants/shape_shift';
|
||||||
|
|
||||||
export type ShapeShiftState = {
|
export type ShapeShiftState = {
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
|
@ -24,40 +24,6 @@ export type ShapeShiftState = {
|
||||||
shapeShiftRate: ?number,
|
shapeShiftRate: ?number,
|
||||||
};
|
};
|
||||||
|
|
||||||
// All ShapeShift actions that will have some payload
|
|
||||||
export type GetSupportedCoinsSuccess = {
|
|
||||||
type: actions.GET_SUPPORTED_COINS_SUCCESS,
|
|
||||||
data: Array<string>,
|
|
||||||
};
|
|
||||||
export type GetCoinStatsStart = {
|
|
||||||
type: actions.GET_SUPPORTED_COINS_SUCCESS,
|
|
||||||
data: string,
|
|
||||||
};
|
|
||||||
export type GetCoinStatsSuccess = {
|
|
||||||
type: actions.GET_COIN_STATS_SUCCESS,
|
|
||||||
data: ShapeShiftMarketInfo,
|
|
||||||
};
|
|
||||||
export type GetCoinStatsFail = {
|
|
||||||
type: actions.GET_COIN_STATS_FAIL,
|
|
||||||
data: string,
|
|
||||||
};
|
|
||||||
export type PrepareShapeShiftSuccess = {
|
|
||||||
type: actions.PREPARE_SHAPE_SHIFT_SUCCESS,
|
|
||||||
data: ActiveShiftInfo,
|
|
||||||
};
|
|
||||||
export type PrepareShapeShiftFail = {
|
|
||||||
type: actions.PREPARE_SHAPE_SHIFT_FAIL,
|
|
||||||
data: ShapeShiftErrorResponse,
|
|
||||||
};
|
|
||||||
export type GetActiveShiftSuccess = {
|
|
||||||
type: actions.GET_ACTIVE_SHIFT_SUCCESS,
|
|
||||||
data: string,
|
|
||||||
};
|
|
||||||
export type GetActiveShiftFail = {
|
|
||||||
type: actions.GET_ACTIVE_SHIFT_FAIL,
|
|
||||||
data: ShapeShiftErrorResponse,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ShapeShift sub-types
|
// ShapeShift sub-types
|
||||||
// Defined for actions that contain an object in the payload
|
// Defined for actions that contain an object in the payload
|
||||||
type ShapeShiftMarketInfo = {
|
type ShapeShiftMarketInfo = {
|
||||||
|
@ -78,6 +44,40 @@ type ShapeShiftErrorResponse = {
|
||||||
message: string,
|
message: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// All ShapeShift actions that will have some payload
|
||||||
|
export type GetSupportedCoinsSuccess = {
|
||||||
|
type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS,
|
||||||
|
data: Array<string>,
|
||||||
|
};
|
||||||
|
export type GetCoinStatsStart = {
|
||||||
|
type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS,
|
||||||
|
data: string,
|
||||||
|
};
|
||||||
|
export type GetCoinStatsSuccess = {
|
||||||
|
type: ACTIONS.GET_COIN_STATS_SUCCESS,
|
||||||
|
data: ShapeShiftMarketInfo,
|
||||||
|
};
|
||||||
|
export type GetCoinStatsFail = {
|
||||||
|
type: ACTIONS.GET_COIN_STATS_FAIL,
|
||||||
|
data: string,
|
||||||
|
};
|
||||||
|
export type PrepareShapeShiftSuccess = {
|
||||||
|
type: ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS,
|
||||||
|
data: ActiveShiftInfo,
|
||||||
|
};
|
||||||
|
export type PrepareShapeShiftFail = {
|
||||||
|
type: ACTIONS.PREPARE_SHAPE_SHIFT_FAIL,
|
||||||
|
data: ShapeShiftErrorResponse,
|
||||||
|
};
|
||||||
|
export type GetActiveShiftSuccess = {
|
||||||
|
type: ACTIONS.GET_ACTIVE_SHIFT_SUCCESS,
|
||||||
|
data: string,
|
||||||
|
};
|
||||||
|
export type GetActiveShiftFail = {
|
||||||
|
type: ACTIONS.GET_ACTIVE_SHIFT_FAIL,
|
||||||
|
data: ShapeShiftErrorResponse,
|
||||||
|
};
|
||||||
|
|
||||||
const defaultState: ShapeShiftState = {
|
const defaultState: ShapeShiftState = {
|
||||||
loading: true,
|
loading: true,
|
||||||
updating: false,
|
updating: false,
|
||||||
|
@ -98,14 +98,12 @@ const defaultState: ShapeShiftState = {
|
||||||
|
|
||||||
export default handleActions(
|
export default handleActions(
|
||||||
{
|
{
|
||||||
[actions.GET_SUPPORTED_COINS_START]: (
|
[ACTIONS.GET_SUPPORTED_COINS_START]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||||
state: ShapeShiftState
|
|
||||||
): ShapeShiftState => ({
|
|
||||||
...state,
|
...state,
|
||||||
loading: true,
|
loading: true,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
}),
|
}),
|
||||||
[actions.GET_SUPPORTED_COINS_SUCCESS]: (
|
[ACTIONS.GET_SUPPORTED_COINS_SUCCESS]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: GetSupportedCoinsSuccess
|
action: GetSupportedCoinsSuccess
|
||||||
): ShapeShiftState => {
|
): ShapeShiftState => {
|
||||||
|
@ -116,15 +114,13 @@ export default handleActions(
|
||||||
shiftSupportedCoins,
|
shiftSupportedCoins,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.GET_SUPPORTED_COINS_FAIL]: (
|
[ACTIONS.GET_SUPPORTED_COINS_FAIL]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||||
state: ShapeShiftState
|
|
||||||
): ShapeShiftState => ({
|
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: "Error getting available coins",
|
error: 'Error getting available coins',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
[actions.GET_COIN_STATS_START]: (
|
[ACTIONS.GET_COIN_STATS_START]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: GetCoinStatsStart
|
action: GetCoinStatsStart
|
||||||
): ShapeShiftState => {
|
): ShapeShiftState => {
|
||||||
|
@ -135,7 +131,7 @@ export default handleActions(
|
||||||
originCoin: coin,
|
originCoin: coin,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.GET_COIN_STATS_SUCCESS]: (
|
[ACTIONS.GET_COIN_STATS_SUCCESS]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: GetCoinStatsSuccess
|
action: GetCoinStatsSuccess
|
||||||
): ShapeShiftState => {
|
): ShapeShiftState => {
|
||||||
|
@ -148,14 +144,12 @@ export default handleActions(
|
||||||
originCoinDepositMax: marketInfo.limit,
|
originCoinDepositMax: marketInfo.limit,
|
||||||
// this will come in scientific notation
|
// this will come in scientific notation
|
||||||
// toFixed shows the real number, then regex to remove trailing zeros
|
// toFixed shows the real number, then regex to remove trailing zeros
|
||||||
originCoinDepositMin: marketInfo.minimum
|
originCoinDepositMin: marketInfo.minimum.toFixed(10).replace(/\.?0+$/, ''),
|
||||||
.toFixed(10)
|
|
||||||
.replace(/\.?0+$/, ""),
|
|
||||||
originCoinDepositFee: marketInfo.minerFee,
|
originCoinDepositFee: marketInfo.minerFee,
|
||||||
shapeShiftRate: marketInfo.rate,
|
shapeShiftRate: marketInfo.rate,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.GET_COIN_STATS_FAIL]: (
|
[ACTIONS.GET_COIN_STATS_FAIL]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: GetCoinStatsFail
|
action: GetCoinStatsFail
|
||||||
): ShapeShiftState => {
|
): ShapeShiftState => {
|
||||||
|
@ -167,13 +161,11 @@ export default handleActions(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
[actions.PREPARE_SHAPE_SHIFT_START]: (
|
[ACTIONS.PREPARE_SHAPE_SHIFT_START]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||||
state: ShapeShiftState
|
|
||||||
): ShapeShiftState => ({
|
|
||||||
...state,
|
...state,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
}),
|
}),
|
||||||
[actions.PREPARE_SHAPE_SHIFT_SUCCESS]: (
|
[ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: PrepareShapeShiftSuccess
|
action: PrepareShapeShiftSuccess
|
||||||
) => {
|
) => {
|
||||||
|
@ -185,13 +177,10 @@ export default handleActions(
|
||||||
shiftCoinType: activeShiftInfo.depositType,
|
shiftCoinType: activeShiftInfo.depositType,
|
||||||
shiftReturnAddress: activeShiftInfo.returnAddress,
|
shiftReturnAddress: activeShiftInfo.returnAddress,
|
||||||
shiftOrderId: activeShiftInfo.orderId,
|
shiftOrderId: activeShiftInfo.orderId,
|
||||||
shiftState: statuses.NO_DEPOSITS,
|
shiftState: STATUSES.NO_DEPOSITS,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.PREPARE_SHAPE_SHIFT_FAIL]: (
|
[ACTIONS.PREPARE_SHAPE_SHIFT_FAIL]: (state: ShapeShiftState, action: PrepareShapeShiftFail) => {
|
||||||
state: ShapeShiftState,
|
|
||||||
action: PrepareShapeShiftFail
|
|
||||||
) => {
|
|
||||||
const error: ShapeShiftErrorResponse = action.data;
|
const error: ShapeShiftErrorResponse = action.data;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -199,7 +188,7 @@ export default handleActions(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
[actions.CLEAR_SHAPE_SHIFT]: (state: ShapeShiftState): ShapeShiftState => ({
|
[ACTIONS.CLEAR_SHAPE_SHIFT]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loading: false,
|
||||||
updating: false,
|
updating: false,
|
||||||
|
@ -211,14 +200,12 @@ export default handleActions(
|
||||||
originCoin: state.shiftSupportedCoins[0],
|
originCoin: state.shiftSupportedCoins[0],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
[actions.GET_ACTIVE_SHIFT_START]: (
|
[ACTIONS.GET_ACTIVE_SHIFT_START]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||||
state: ShapeShiftState
|
|
||||||
): ShapeShiftState => ({
|
|
||||||
...state,
|
...state,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
updating: true,
|
updating: true,
|
||||||
}),
|
}),
|
||||||
[actions.GET_ACTIVE_SHIFT_SUCCESS]: (
|
[ACTIONS.GET_ACTIVE_SHIFT_SUCCESS]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: GetActiveShiftSuccess
|
action: GetActiveShiftSuccess
|
||||||
): ShapeShiftState => {
|
): ShapeShiftState => {
|
||||||
|
@ -229,7 +216,7 @@ export default handleActions(
|
||||||
shiftState: status,
|
shiftState: status,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.GET_ACTIVE_SHIFT_FAIL]: (
|
[ACTIONS.GET_ACTIVE_SHIFT_FAIL]: (
|
||||||
state: ShapeShiftState,
|
state: ShapeShiftState,
|
||||||
action: GetActiveShiftFail
|
action: GetActiveShiftFail
|
||||||
): ShapeShiftState => {
|
): ShapeShiftState => {
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as actions from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { handleActions } from "util/redux-utils";
|
import handleActions from 'util/redux-utils';
|
||||||
|
|
||||||
|
export type Subscription = {
|
||||||
|
channelName: string,
|
||||||
|
uri: string,
|
||||||
|
};
|
||||||
|
|
||||||
// Subscription redux types
|
// Subscription redux types
|
||||||
export type SubscriptionState = {
|
export type SubscriptionState = {
|
||||||
|
@ -8,30 +13,22 @@ export type SubscriptionState = {
|
||||||
hasFetchedSubscriptions: boolean,
|
hasFetchedSubscriptions: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Subscription = {
|
|
||||||
channelName: string,
|
|
||||||
uri: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Subscription action types
|
// Subscription action types
|
||||||
type doChannelSubscribe = {
|
type doChannelSubscribe = {
|
||||||
type: actions.CHANNEL_SUBSCRIBE,
|
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||||
data: Subscription,
|
data: Subscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
type doChannelUnsubscribe = {
|
type doChannelUnsubscribe = {
|
||||||
type: actions.CHANNEL_UNSUBSCRIBE,
|
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||||
data: Subscription,
|
data: Subscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
type HasFetchedSubscriptions = {
|
type HasFetchedSubscriptions = {
|
||||||
type: actions.HAS_FETCHED_SUBSCRIPTIONS,
|
type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Action =
|
export type Action = doChannelSubscribe | doChannelUnsubscribe | HasFetchedSubscriptions;
|
||||||
| doChannelSubscribe
|
|
||||||
| doChannelUnsubscribe
|
|
||||||
| HasFetchedSubscriptions;
|
|
||||||
export type Dispatch = (action: Action) => any;
|
export type Dispatch = (action: Action) => any;
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
@ -41,7 +38,7 @@ const defaultState = {
|
||||||
|
|
||||||
export default handleActions(
|
export default handleActions(
|
||||||
{
|
{
|
||||||
[actions.CHANNEL_SUBSCRIBE]: (
|
[ACTIONS.CHANNEL_SUBSCRIBE]: (
|
||||||
state: SubscriptionState,
|
state: SubscriptionState,
|
||||||
action: doChannelSubscribe
|
action: doChannelSubscribe
|
||||||
): SubscriptionState => {
|
): SubscriptionState => {
|
||||||
|
@ -54,7 +51,7 @@ export default handleActions(
|
||||||
subscriptions: newSubscriptions,
|
subscriptions: newSubscriptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.CHANNEL_UNSUBSCRIBE]: (
|
[ACTIONS.CHANNEL_UNSUBSCRIBE]: (
|
||||||
state: SubscriptionState,
|
state: SubscriptionState,
|
||||||
action: doChannelUnsubscribe
|
action: doChannelUnsubscribe
|
||||||
): SubscriptionState => {
|
): SubscriptionState => {
|
||||||
|
@ -62,20 +59,14 @@ export default handleActions(
|
||||||
|
|
||||||
const newSubscriptions = state.subscriptions
|
const newSubscriptions = state.subscriptions
|
||||||
.slice()
|
.slice()
|
||||||
.filter(
|
.filter(subscription => subscription.channelName !== subscriptionToRemove.channelName);
|
||||||
subscription =>
|
|
||||||
subscription.channelName !== subscriptionToRemove.channelName
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
subscriptions: newSubscriptions,
|
subscriptions: newSubscriptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[actions.HAS_FETCHED_SUBSCRIPTIONS]: (
|
[ACTIONS.HAS_FETCHED_SUBSCRIPTIONS]: (state: SubscriptionState): SubscriptionState => ({
|
||||||
state: SubscriptionState,
|
|
||||||
action: HasFetchedSubscriptions
|
|
||||||
): SubscriptionState => ({
|
|
||||||
...state,
|
...state,
|
||||||
hasFetchedSubscriptions: true,
|
hasFetchedSubscriptions: true,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ const defaultState = {
|
||||||
authenticationIsPending: false,
|
authenticationIsPending: false,
|
||||||
userIsPending: false,
|
userIsPending: false,
|
||||||
emailNewIsPending: false,
|
emailNewIsPending: false,
|
||||||
emailNewErrorMessage: "",
|
emailNewErrorMessage: '',
|
||||||
emailToVerify: "",
|
emailToVerify: '',
|
||||||
inviteNewErrorMessage: "",
|
inviteNewErrorMessage: '',
|
||||||
inviteNewIsPending: false,
|
inviteNewIsPending: false,
|
||||||
inviteStatusIsPending: false,
|
inviteStatusIsPending: false,
|
||||||
invitesRemaining: undefined,
|
invitesRemaining: undefined,
|
||||||
|
@ -16,7 +16,7 @@ const defaultState = {
|
||||||
user: undefined,
|
user: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.AUTHENTICATION_STARTED] = function(state, action) {
|
reducers[ACTIONS.AUTHENTICATION_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
authenticationIsPending: true,
|
authenticationIsPending: true,
|
||||||
userIsPending: true,
|
userIsPending: true,
|
||||||
|
@ -24,7 +24,7 @@ reducers[types.AUTHENTICATION_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.AUTHENTICATION_SUCCESS] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
authenticationIsPending: false,
|
authenticationIsPending: false,
|
||||||
userIsPending: false,
|
userIsPending: false,
|
||||||
|
@ -32,7 +32,7 @@ reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.AUTHENTICATION_FAILURE] = function(state, action) {
|
reducers[ACTIONS.AUTHENTICATION_FAILURE] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
authenticationIsPending: false,
|
authenticationIsPending: false,
|
||||||
userIsPending: false,
|
userIsPending: false,
|
||||||
|
@ -40,35 +40,35 @@ reducers[types.AUTHENTICATION_FAILURE] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_FETCH_STARTED] = function(state, action) {
|
reducers[ACTIONS.USER_FETCH_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
userIsPending: true,
|
userIsPending: true,
|
||||||
user: defaultState.user,
|
user: defaultState.user,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_FETCH_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.USER_FETCH_SUCCESS] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
userIsPending: false,
|
userIsPending: false,
|
||||||
user: action.data.user,
|
user: action.data.user,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_FETCH_FAILURE] = function(state, action) {
|
reducers[ACTIONS.USER_FETCH_FAILURE] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
userIsPending: true,
|
userIsPending: true,
|
||||||
user: null,
|
user: null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_NEW_STARTED] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_NEW_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
emailNewIsPending: true,
|
emailNewIsPending: true,
|
||||||
emailNewErrorMessage: "",
|
emailNewErrorMessage: '',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
|
||||||
const user = Object.assign({}, state.user);
|
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, {
|
||||||
|
@ -78,68 +78,67 @@ reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_NEW_EXISTS] = function(state, action) {
|
||||||
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,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_NEW_FAILURE] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_NEW_FAILURE] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
emailNewIsPending: false,
|
emailNewIsPending: false,
|
||||||
emailNewErrorMessage: action.data.error,
|
emailNewErrorMessage: action.data.error,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_VERIFY_STARTED] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_VERIFY_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
emailVerifyIsPending: true,
|
emailVerifyIsPending: true,
|
||||||
emailVerifyErrorMessage: "",
|
emailVerifyErrorMessage: '',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) {
|
||||||
const user = Object.assign({}, state.user);
|
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,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_EMAIL_VERIFY_FAILURE] = function(state, action) {
|
reducers[ACTIONS.USER_EMAIL_VERIFY_FAILURE] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
emailVerifyIsPending: false,
|
emailVerifyIsPending: false,
|
||||||
emailVerifyErrorMessage: action.data.error,
|
emailVerifyErrorMessage: action.data.error,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_IDENTITY_VERIFY_STARTED] = function(state, action) {
|
reducers[ACTIONS.USER_IDENTITY_VERIFY_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
identityVerifyIsPending: true,
|
identityVerifyIsPending: true,
|
||||||
identityVerifyErrorMessage: "",
|
identityVerifyErrorMessage: '',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
identityVerifyIsPending: false,
|
identityVerifyIsPending: false,
|
||||||
identityVerifyErrorMessage: "",
|
identityVerifyErrorMessage: '',
|
||||||
user: action.data.user,
|
user: action.data.user,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) {
|
reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
identityVerifyIsPending: false,
|
identityVerifyIsPending: false,
|
||||||
identityVerifyErrorMessage: action.data.error,
|
identityVerifyErrorMessage: action.data.error,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) {
|
||||||
const { token } = action.data;
|
const { token } = action.data;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
|
@ -147,13 +146,13 @@ reducers[types.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_INVITE_STATUS_FETCH_STARTED] = function(state, action) {
|
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
inviteStatusIsPending: true,
|
inviteStatusIsPending: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
inviteStatusIsPending: false,
|
inviteStatusIsPending: false,
|
||||||
invitesRemaining: action.data.invitesRemaining,
|
invitesRemaining: action.data.invitesRemaining,
|
||||||
|
@ -161,28 +160,28 @@ reducers[types.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_INVITE_NEW_STARTED] = function(state, action) {
|
reducers[ACTIONS.USER_INVITE_NEW_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
inviteNewIsPending: true,
|
inviteNewIsPending: true,
|
||||||
inviteNewErrorMessage: "",
|
inviteNewErrorMessage: '',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_INVITE_NEW_SUCCESS] = function(state, action) {
|
reducers[ACTIONS.USER_INVITE_NEW_SUCCESS] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
inviteNewIsPending: false,
|
inviteNewIsPending: false,
|
||||||
inviteNewErrorMessage: "",
|
inviteNewErrorMessage: '',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_INVITE_NEW_FAILURE] = function(state, action) {
|
reducers[ACTIONS.USER_INVITE_NEW_FAILURE] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
inviteNewIsPending: false,
|
inviteNewIsPending: false,
|
||||||
inviteNewErrorMessage: action.data.error.message,
|
inviteNewErrorMessage: action.data.error.message,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.USER_INVITE_STATUS_FETCH_FAILURE] = function(state, action) {
|
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
inviteStatusIsPending: false,
|
inviteStatusIsPending: false,
|
||||||
invitesRemaining: null,
|
invitesRemaining: null,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as types from "constants/action_types";
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const address = localStorage.getItem("receiveAddress");
|
const receiveAddress = localStorage.getItem('receiveAddress');
|
||||||
const buildDraftTransaction = () => ({
|
const buildDraftTransaction = () => ({
|
||||||
amount: undefined,
|
amount: undefined,
|
||||||
address: undefined,
|
address: undefined,
|
||||||
|
@ -12,19 +12,19 @@ const defaultState = {
|
||||||
blocks: {},
|
blocks: {},
|
||||||
transactions: {},
|
transactions: {},
|
||||||
fetchingTransactions: false,
|
fetchingTransactions: false,
|
||||||
receiveAddress: address,
|
receiveAddress,
|
||||||
gettingNewAddress: false,
|
gettingNewAddress: false,
|
||||||
draftTransaction: buildDraftTransaction(),
|
draftTransaction: buildDraftTransaction(),
|
||||||
sendingSupport: false,
|
sendingSupport: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_TRANSACTIONS_STARTED] = function(state, action) {
|
reducers[ACTIONS.FETCH_TRANSACTIONS_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
fetchingTransactions: true,
|
fetchingTransactions: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
|
||||||
const byId = Object.assign({}, state.transactions);
|
const byId = Object.assign({}, state.transactions);
|
||||||
|
|
||||||
const { transactions } = action.data;
|
const { transactions } = action.data;
|
||||||
|
@ -39,41 +39,41 @@ reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.GET_NEW_ADDRESS_STARTED] = function(state, action) {
|
reducers[ACTIONS.GET_NEW_ADDRESS_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
gettingNewAddress: true,
|
gettingNewAddress: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.GET_NEW_ADDRESS_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.GET_NEW_ADDRESS_COMPLETED] = function(state, action) {
|
||||||
const { address } = action.data;
|
const { address } = action.data;
|
||||||
|
|
||||||
localStorage.setItem("receiveAddress", address);
|
localStorage.setItem('receiveAddress', address);
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
gettingNewAddress: false,
|
gettingNewAddress: false,
|
||||||
receiveAddress: address,
|
receiveAddress: address,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.UPDATE_BALANCE] = function(state, action) {
|
reducers[ACTIONS.UPDATE_BALANCE] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
balance: action.data.balance,
|
balance: action.data.balance,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CHECK_ADDRESS_IS_MINE_STARTED] = function(state, action) {
|
reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
checkingAddressOwnership: true,
|
checkingAddressOwnership: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
checkingAddressOwnership: false,
|
checkingAddressOwnership: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) {
|
reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) {
|
||||||
const oldDraft = state.draftTransaction;
|
const oldDraft = state.draftTransaction;
|
||||||
const newDraft = Object.assign({}, oldDraft, {
|
const newDraft = Object.assign({}, oldDraft, {
|
||||||
amount: parseFloat(action.data.amount),
|
amount: parseFloat(action.data.amount),
|
||||||
|
@ -84,7 +84,7 @@ reducers[types.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) {
|
reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) {
|
||||||
const oldDraft = state.draftTransaction;
|
const oldDraft = state.draftTransaction;
|
||||||
const newDraft = Object.assign({}, oldDraft, {
|
const newDraft = Object.assign({}, oldDraft, {
|
||||||
address: action.data.address,
|
address: action.data.address,
|
||||||
|
@ -95,7 +95,7 @@ reducers[types.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SEND_TRANSACTION_STARTED] = function(state, action) {
|
reducers[ACTIONS.SEND_TRANSACTION_STARTED] = function(state) {
|
||||||
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
||||||
sending: true,
|
sending: true,
|
||||||
});
|
});
|
||||||
|
@ -105,13 +105,13 @@ reducers[types.SEND_TRANSACTION_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SEND_TRANSACTION_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.SEND_TRANSACTION_COMPLETED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
draftTransaction: buildDraftTransaction(),
|
draftTransaction: buildDraftTransaction(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) {
|
reducers[ACTIONS.SEND_TRANSACTION_FAILED] = function(state, action) {
|
||||||
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
||||||
sending: false,
|
sending: false,
|
||||||
error: action.data.error,
|
error: action.data.error,
|
||||||
|
@ -122,28 +122,28 @@ reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) {
|
reducers[ACTIONS.SUPPORT_TRANSACTION_STARTED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
sendingSupport: true,
|
sendingSupport: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) {
|
reducers[ACTIONS.SUPPORT_TRANSACTION_COMPLETED] = function(state) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
sendingSupport: false,
|
sendingSupport: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) {
|
reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = function(state, action) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
error: action.data.error,
|
error: action.data.error,
|
||||||
sendingSupport: false,
|
sendingSupport: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_BLOCK_SUCCESS] = (state, action) => {
|
reducers[ACTIONS.FETCH_BLOCK_SUCCESS] = (state, action) => {
|
||||||
const { block, block: { height } } = action.data,
|
const { block, block: { height } } = action.data;
|
||||||
blocks = Object.assign({}, state.blocks);
|
const blocks = Object.assign({}, state.blocks);
|
||||||
|
|
||||||
blocks[height] = block;
|
blocks[height] = block;
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,26 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
export const _selectState = state => state.app || {};
|
export const selectState = state => state.app || {};
|
||||||
|
|
||||||
export const selectPlatform = createSelector(
|
export const selectPlatform = createSelector(selectState, state => state.platform);
|
||||||
_selectState,
|
|
||||||
state => state.platform
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUpdateUrl = createSelector(selectPlatform, platform => {
|
export const selectUpdateUrl = createSelector(selectPlatform, platform => {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case "darwin":
|
case 'darwin':
|
||||||
return "https://lbry.io/get/lbry.dmg";
|
return 'https://lbry.io/get/lbry.dmg';
|
||||||
case "linux":
|
case 'linux':
|
||||||
return "https://lbry.io/get/lbry.deb";
|
return 'https://lbry.io/get/lbry.deb';
|
||||||
case "win32":
|
case 'win32':
|
||||||
return "https://lbry.io/get/lbry.exe";
|
return 'https://lbry.io/get/lbry.exe';
|
||||||
default:
|
default:
|
||||||
throw "Unknown platform";
|
throw Error('Unknown platform');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const selectRemoteVersion = createSelector(
|
export const selectRemoteVersion = createSelector(selectState, state => state.remoteVersion);
|
||||||
_selectState,
|
|
||||||
state => state.remoteVersion
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectIsUpgradeAvailable = createSelector(
|
export const selectIsUpgradeAvailable = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.isUpgradeAvailable
|
state => state.isUpgradeAvailable
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -35,81 +29,54 @@ export const selectUpgradeFilename = createSelector(
|
||||||
selectRemoteVersion,
|
selectRemoteVersion,
|
||||||
(platform, version) => {
|
(platform, version) => {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case "darwin":
|
case 'darwin':
|
||||||
return `LBRY_${version}.dmg`;
|
return `LBRY_${version}.dmg`;
|
||||||
case "linux":
|
case 'linux':
|
||||||
return `LBRY_${version}_amd64.deb`;
|
return `LBRY_${version}_amd64.deb`;
|
||||||
case "win32":
|
case 'win32':
|
||||||
return `LBRY_${version}.exe`;
|
return `LBRY_${version}.exe`;
|
||||||
default:
|
default:
|
||||||
throw "Unknown platform";
|
throw Error('Unknown platform');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectCurrentModal = createSelector(
|
export const selectCurrentModal = createSelector(selectState, state => state.modal);
|
||||||
_selectState,
|
|
||||||
state => state.modal
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectDownloadProgress = createSelector(
|
export const selectDownloadProgress = createSelector(selectState, state => state.downloadProgress);
|
||||||
_selectState,
|
|
||||||
state => state.downloadProgress
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectDownloadComplete = createSelector(
|
export const selectDownloadComplete = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.upgradeDownloadCompleted
|
state => state.upgradeDownloadCompleted
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsUpgradeSkipped = createSelector(
|
export const selectIsUpgradeSkipped = createSelector(selectState, state => state.isUpgradeSkipped);
|
||||||
_selectState,
|
|
||||||
state => state.isUpgradeSkipped
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUpgradeDownloadPath = createSelector(
|
export const selectUpgradeDownloadPath = createSelector(selectState, state => state.downloadPath);
|
||||||
_selectState,
|
|
||||||
state => state.downloadPath
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUpgradeDownloadItem = createSelector(
|
export const selectUpgradeDownloadItem = createSelector(selectState, state => state.downloadItem);
|
||||||
_selectState,
|
|
||||||
state => state.downloadItem
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectModalProps = createSelector(
|
export const selectModalProps = createSelector(selectState, state => state.modalProps);
|
||||||
_selectState,
|
|
||||||
state => state.modalProps
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectDaemonReady = createSelector(
|
export const selectDaemonReady = createSelector(selectState, state => state.daemonReady);
|
||||||
_selectState,
|
|
||||||
state => state.daemonReady
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectDaemonVersionMatched = createSelector(
|
export const selectDaemonVersionMatched = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.daemonVersionMatched
|
state => state.daemonVersionMatched
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectSnackBar = createSelector(
|
export const selectSnackBar = createSelector(selectState, state => state.snackBar || {});
|
||||||
_selectState,
|
|
||||||
state => state.snackBar || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSnackBarSnacks = createSelector(
|
export const selectSnackBarSnacks = createSelector(
|
||||||
selectSnackBar,
|
selectSnackBar,
|
||||||
snackBar => snackBar.snacks || []
|
snackBar => snackBar.snacks || []
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectBadgeNumber = createSelector(
|
export const selectBadgeNumber = createSelector(selectState, state => state.badgeNumber);
|
||||||
_selectState,
|
|
||||||
state => state.badgeNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectCurrentLanguage = createSelector(
|
export const selectCurrentLanguage = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
() => app.i18n.getLocale() || "en"
|
() => app.i18n.getLocale() || 'en'
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectVolume = createSelector(_selectState, state => state.volume);
|
export const selectVolume = createSelector(selectState, state => state.volume);
|
||||||
|
|
|
@ -1,22 +1,7 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
const _selectState = state => state.availability;
|
const selectState = state => state.availability;
|
||||||
|
|
||||||
export const selectAvailabilityByUri = createSelector(
|
const selectFetchingAvailability = createSelector(selectState, state => state.fetching || {});
|
||||||
_selectState,
|
|
||||||
state => state.byUri || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectIsAvailableForUri = uri =>
|
export { selectFetchingAvailability as default };
|
||||||
createSelector(
|
|
||||||
selectAvailabilityByUri,
|
|
||||||
byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectFetchingAvailability = createSelector(
|
|
||||||
_selectState,
|
|
||||||
state => state.fetching || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectFetchingAvailabilityForUri = uri =>
|
|
||||||
createSelector(selectFetchingAvailability, byUri => byUri && byUri[uri]);
|
|
||||||
|
|
|
@ -1,77 +1,79 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
import lbryuri from "lbryuri";
|
import Lbryuri from 'lbryuri';
|
||||||
import { makeSelectCurrentParam } from "./navigation";
|
import { makeSelectCurrentParam } from 'redux/selectors/navigation';
|
||||||
|
|
||||||
const _selectState = state => state.claims || {};
|
const selectState = state => state.claims || {};
|
||||||
|
|
||||||
export const selectClaimsById = createSelector(
|
export const selectClaimsById = createSelector(selectState, state => state.byId || {});
|
||||||
_selectState,
|
|
||||||
state => state.byId || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectClaimsByUri = createSelector(
|
export const selectClaimsByUri = createSelector(selectState, selectClaimsById, (state, byId) => {
|
||||||
_selectState,
|
const byUri = state.claimsByUri || {};
|
||||||
selectClaimsById,
|
const claims = {};
|
||||||
(state, byId) => {
|
|
||||||
const byUri = state.claimsByUri || {};
|
|
||||||
const claims = {};
|
|
||||||
|
|
||||||
Object.keys(byUri).forEach(uri => {
|
Object.keys(byUri).forEach(uri => {
|
||||||
const claimId = byUri[uri];
|
const claimId = byUri[uri];
|
||||||
|
|
||||||
// NOTE returning a null claim allows us to differentiate between an
|
// NOTE returning a null claim allows us to differentiate between an
|
||||||
// undefined (never fetched claim) and one which just doesn't exist. Not
|
// undefined (never fetched claim) and one which just doesn't exist. Not
|
||||||
// the cleanest solution but couldn't think of anything better right now
|
// the cleanest solution but couldn't think of anything better right now
|
||||||
if (claimId === null) {
|
if (claimId === null) {
|
||||||
claims[uri] = null;
|
claims[uri] = null;
|
||||||
} else {
|
} else {
|
||||||
const claim = byId[claimId];
|
const claim = byId[claimId];
|
||||||
|
|
||||||
claims[uri] = claim;
|
claims[uri] = claim;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return claims;
|
return claims;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export const selectAllClaimsByChannel = createSelector(
|
export const selectAllClaimsByChannel = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.claimsByChannel || {}
|
state => state.claimsByChannel || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const makeSelectClaimForUri = uri =>
|
export const makeSelectClaimForUri = uri =>
|
||||||
createSelector(
|
createSelector(selectClaimsByUri, claims => claims && claims[Lbryuri.normalize(uri)]);
|
||||||
selectClaimsByUri,
|
|
||||||
claims => claims && claims[lbryuri.normalize(uri)]
|
export const selectMyClaimsRaw = createSelector(selectState, state => state.myClaims);
|
||||||
);
|
|
||||||
|
export const selectAbandoningIds = createSelector(selectState, state =>
|
||||||
|
Object.keys(state.abandoningById || {})
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectMyActiveClaims = createSelector(
|
||||||
|
selectMyClaimsRaw,
|
||||||
|
selectAbandoningIds,
|
||||||
|
(claims, abandoningIds) =>
|
||||||
|
new Set(
|
||||||
|
claims &&
|
||||||
|
claims
|
||||||
|
.map(claim => claim.claim_id)
|
||||||
|
.filter(claimId => Object.keys(abandoningIds).indexOf(claimId) === -1)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
export const makeSelectClaimIsMine = rawUri => {
|
export const makeSelectClaimIsMine = rawUri => {
|
||||||
const uri = lbryuri.normalize(rawUri);
|
const uri = Lbryuri.normalize(rawUri);
|
||||||
return createSelector(
|
return createSelector(
|
||||||
selectClaimsByUri,
|
selectClaimsByUri,
|
||||||
selectMyActiveClaims,
|
selectMyActiveClaims,
|
||||||
(claims, myClaims) =>
|
(claims, myClaims) =>
|
||||||
claims &&
|
claims && claims[uri] && claims[uri].claim_id && myClaims.has(claims[uri].claim_id)
|
||||||
claims[uri] &&
|
|
||||||
claims[uri].claim_id &&
|
|
||||||
myClaims.has(claims[uri].claim_id)
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectAllFetchingChannelClaims = createSelector(
|
export const selectAllFetchingChannelClaims = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.fetchingChannelClaims || {}
|
state => state.fetchingChannelClaims || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const makeSelectFetchingChannelClaims = uri =>
|
export const makeSelectFetchingChannelClaims = uri =>
|
||||||
createSelector(
|
createSelector(selectAllFetchingChannelClaims, fetching => fetching && fetching[uri]);
|
||||||
selectAllFetchingChannelClaims,
|
|
||||||
fetching => fetching && fetching[uri]
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectClaimsInChannelForCurrentPage = uri => {
|
export const makeSelectClaimsInChannelForCurrentPage = uri => {
|
||||||
const pageSelector = makeSelectCurrentParam("page");
|
const pageSelector = makeSelectCurrentParam('page');
|
||||||
|
|
||||||
return createSelector(
|
return createSelector(
|
||||||
selectClaimsById,
|
selectClaimsById,
|
||||||
|
@ -90,53 +92,27 @@ export const makeSelectClaimsInChannelForCurrentPage = uri => {
|
||||||
|
|
||||||
export const makeSelectMetadataForUri = uri =>
|
export const makeSelectMetadataForUri = uri =>
|
||||||
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 || (claim === undefined ? undefined : null);
|
const value = metadata || (claim === undefined ? undefined : null);
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
export const makeSelectTitleForUri = uri =>
|
export const makeSelectTitleForUri = uri =>
|
||||||
createSelector(
|
createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title);
|
||||||
makeSelectMetadataForUri(uri),
|
|
||||||
metadata => metadata && metadata.title
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectContentTypeForUri = uri =>
|
export const makeSelectContentTypeForUri = uri =>
|
||||||
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,
|
||||||
state => !!state.isFetchingClaimListMine
|
state => !!state.isFetchingClaimListMine
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectMyClaimsRaw = createSelector(
|
export const selectPendingClaims = createSelector(selectState, state =>
|
||||||
_selectState,
|
|
||||||
state => state.myClaims
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectAbandoningIds = createSelector(_selectState, state =>
|
|
||||||
Object.keys(state.abandoningById || {})
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectMyActiveClaims = createSelector(
|
|
||||||
selectMyClaimsRaw,
|
|
||||||
selectAbandoningIds,
|
|
||||||
(claims, abandoningIds) =>
|
|
||||||
new Set(
|
|
||||||
claims &&
|
|
||||||
claims
|
|
||||||
.map(claim => claim.claim_id)
|
|
||||||
.filter(claimId => Object.keys(abandoningIds).indexOf(claimId) === -1)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectPendingClaims = createSelector(_selectState, state =>
|
|
||||||
Object.values(state.pendingById || {})
|
Object.values(state.pendingById || {})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -151,46 +127,38 @@ export const selectMyClaims = createSelector(
|
||||||
myClaimIds.forEach(id => {
|
myClaimIds.forEach(id => {
|
||||||
const claim = byId[id];
|
const claim = byId[id];
|
||||||
|
|
||||||
if (claim && abandoningIds.indexOf(id) == -1) claims.push(claim);
|
if (claim && abandoningIds.indexOf(id) === -1) claims.push(claim);
|
||||||
});
|
});
|
||||||
|
|
||||||
return [...claims, ...pendingClaims];
|
return [...claims, ...pendingClaims];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectMyClaimsWithoutChannels = createSelector(
|
export const selectMyClaimsWithoutChannels = createSelector(selectMyClaims, myClaims =>
|
||||||
selectMyClaims,
|
myClaims.filter(claim => !claim.name.match(/^@/))
|
||||||
myClaims => myClaims.filter(claim => !claim.name.match(/^@/))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectAllMyClaimsByOutpoint = createSelector(
|
export const selectAllMyClaimsByOutpoint = createSelector(
|
||||||
selectMyClaimsRaw,
|
selectMyClaimsRaw,
|
||||||
claims =>
|
claims =>
|
||||||
new Set(
|
new Set(claims && claims.length ? claims.map(claim => `${claim.txid}:${claim.nout}`) : null)
|
||||||
claims && claims.length
|
|
||||||
? claims.map(claim => `${claim.txid}:${claim.nout}`)
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectMyClaimsOutpoints = createSelector(
|
export const selectMyClaimsOutpoints = createSelector(selectMyClaims, myClaims => {
|
||||||
selectMyClaims,
|
const outpoints = [];
|
||||||
myClaims => {
|
|
||||||
const outpoints = [];
|
|
||||||
|
|
||||||
myClaims.forEach(claim => outpoints.push(`${claim.txid}:${claim.nout}`));
|
myClaims.forEach(claim => outpoints.push(`${claim.txid}:${claim.nout}`));
|
||||||
|
|
||||||
return outpoints;
|
return outpoints;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export const selectFetchingMyChannels = createSelector(
|
export const selectFetchingMyChannels = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => !!state.fetchingMyChannels
|
state => !!state.fetchingMyChannels
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectMyChannelClaims = createSelector(
|
export const selectMyChannelClaims = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
selectClaimsById,
|
selectClaimsById,
|
||||||
(state, byId) => {
|
(state, byId) => {
|
||||||
const ids = state.myChannelClaims || [];
|
const ids = state.myChannelClaims || [];
|
||||||
|
|
|
@ -1,35 +1,26 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
export const _selectState = state => state.content || {};
|
export const selectState = state => state.content || {};
|
||||||
|
|
||||||
export const selectFeaturedUris = createSelector(
|
export const selectFeaturedUris = createSelector(selectState, state => state.featuredUris);
|
||||||
_selectState,
|
|
||||||
state => state.featuredUris
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectFetchingFeaturedUris = createSelector(
|
export const selectFetchingFeaturedUris = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => !!state.fetchingFeaturedContent
|
state => !!state.fetchingFeaturedContent
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectResolvingUris = createSelector(
|
export const selectResolvingUris = createSelector(selectState, state => state.resolvingUris || []);
|
||||||
_selectState,
|
|
||||||
state => state.resolvingUris || []
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectPlayingUri = createSelector(
|
export const selectPlayingUri = createSelector(selectState, state => state.playingUri);
|
||||||
_selectState,
|
|
||||||
state => state.playingUri
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectIsUriResolving = uri =>
|
export const makeSelectIsUriResolving = uri =>
|
||||||
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 || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -43,6 +34,6 @@ export const makeSelectTotalPagesForChannel = uri =>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectRewardContentClaimIds = createSelector(
|
export const selectRewardContentClaimIds = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.rewardedContentClaimIds
|
state => state.rewardedContentClaimIds
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,33 +1,20 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
import { selectCurrentParams } from "redux/selectors/navigation";
|
import { selectCurrentParams } from 'redux/selectors/navigation';
|
||||||
|
|
||||||
export const _selectState = state => state.costInfo || {};
|
export const selectState = state => state.costInfo || {};
|
||||||
|
|
||||||
export const selectAllCostInfoByUri = createSelector(
|
export const selectAllCostInfoByUri = createSelector(selectState, state => state.byUri || {});
|
||||||
_selectState,
|
|
||||||
state => state.byUri || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectCostInfoForUri = uri =>
|
export const makeSelectCostInfoForUri = uri =>
|
||||||
createSelector(
|
createSelector(selectAllCostInfoByUri, costInfos => costInfos && costInfos[uri]);
|
||||||
selectAllCostInfoByUri,
|
|
||||||
costInfos => costInfos && costInfos[uri]
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectCostForCurrentPageUri = createSelector(
|
export const selectCostForCurrentPageUri = createSelector(
|
||||||
selectAllCostInfoByUri,
|
selectAllCostInfoByUri,
|
||||||
selectCurrentParams,
|
selectCurrentParams,
|
||||||
(costInfo, params) =>
|
(costInfo, params) => (params.uri && costInfo[params.uri] ? costInfo[params.uri].cost : undefined)
|
||||||
params.uri && costInfo[params.uri] ? costInfo[params.uri].cost : undefined
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectFetchingCostInfo = createSelector(
|
export const selectFetchingCostInfo = createSelector(selectState, state => state.fetching || {});
|
||||||
_selectState,
|
|
||||||
state => state.fetching || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectFetchingCostInfoForUri = uri =>
|
export const makeSelectFetchingCostInfoForUri = uri =>
|
||||||
createSelector(
|
createSelector(selectFetchingCostInfo, fetchingByUri => fetchingByUri && fetchingByUri[uri]);
|
||||||
selectFetchingCostInfo,
|
|
||||||
fetchingByUri => fetchingByUri && fetchingByUri[uri]
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,45 +1,39 @@
|
||||||
import lbry from "lbry";
|
import { createSelector } from 'reselect';
|
||||||
import { createSelector } from "reselect";
|
|
||||||
import {
|
import {
|
||||||
selectClaimsByUri,
|
selectClaimsByUri,
|
||||||
selectIsFetchingClaimListMine,
|
selectIsFetchingClaimListMine,
|
||||||
selectMyClaims,
|
selectMyClaims,
|
||||||
selectMyClaimsOutpoints,
|
selectMyClaimsOutpoints,
|
||||||
} from "redux/selectors/claims";
|
} from 'redux/selectors/claims';
|
||||||
|
|
||||||
export const _selectState = state => state.fileInfo || {};
|
export const selectState = state => state.fileInfo || {};
|
||||||
|
|
||||||
export const selectFileInfosByOutpoint = createSelector(
|
export const selectFileInfosByOutpoint = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.byOutpoint || {}
|
state => state.byOutpoint || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsFetchingFileList = createSelector(
|
export const selectIsFetchingFileList = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => !!state.isFetchingFileList
|
state => state.isFetchingFileList
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsFetchingFileListDownloadedOrPublished = createSelector(
|
export const selectIsFetchingFileListDownloadedOrPublished = createSelector(
|
||||||
selectIsFetchingFileList,
|
selectIsFetchingFileList,
|
||||||
selectIsFetchingClaimListMine,
|
selectIsFetchingClaimListMine,
|
||||||
(isFetchingFileList, isFetchingClaimListMine) =>
|
(isFetchingFileList, isFetchingClaimListMine) => isFetchingFileList || isFetchingClaimListMine
|
||||||
isFetchingFileList || isFetchingClaimListMine
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const makeSelectFileInfoForUri = uri =>
|
export const makeSelectFileInfoForUri = uri =>
|
||||||
createSelector(
|
createSelector(selectClaimsByUri, selectFileInfosByOutpoint, (claims, byOutpoint) => {
|
||||||
selectClaimsByUri,
|
const claim = claims[uri];
|
||||||
selectFileInfosByOutpoint,
|
const outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
|
||||||
(claims, byOutpoint) => {
|
|
||||||
const claim = claims[uri],
|
|
||||||
outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
|
|
||||||
|
|
||||||
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 || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -53,17 +47,13 @@ export const makeSelectDownloadingForUri = uri =>
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUrisLoading = createSelector(
|
export const selectUrisLoading = createSelector(selectState, state => state.urisLoading || {});
|
||||||
_selectState,
|
|
||||||
state => state.urisLoading || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const makeSelectLoadingForUri = uri =>
|
export const makeSelectLoadingForUri = uri =>
|
||||||
createSelector(selectUrisLoading, byUri => byUri && byUri[uri]);
|
createSelector(selectUrisLoading, byUri => byUri && byUri[uri]);
|
||||||
|
|
||||||
export const selectFileInfosPendingPublish = createSelector(
|
export const selectFileInfosPendingPublish = createSelector(selectState, state =>
|
||||||
_selectState,
|
Object.values(state.pendingByOutpoint || {})
|
||||||
state => Object.values(state.pendingByOutpoint || {})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectFileInfosDownloaded = createSelector(
|
export const selectFileInfosDownloaded = createSelector(
|
||||||
|
@ -141,18 +131,15 @@ export const selectDownloadingFileInfos = createSelector(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectTotalDownloadProgress = createSelector(
|
export const selectTotalDownloadProgress = createSelector(selectDownloadingFileInfos, fileInfos => {
|
||||||
selectDownloadingFileInfos,
|
const progress = [];
|
||||||
fileInfos => {
|
|
||||||
const progress = [];
|
|
||||||
|
|
||||||
fileInfos.forEach(fileInfo => {
|
fileInfos.forEach(fileInfo => {
|
||||||
progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100);
|
progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalProgress = progress.reduce((a, b) => a + b, 0);
|
const totalProgress = progress.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
|
if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
import { parseQueryParams, toQueryString } from "util/query_params";
|
import { parseQueryParams, toQueryString } from 'util/query_params';
|
||||||
import * as settings from "constants/settings.js";
|
import Lbryuri from 'lbryuri';
|
||||||
import lbryuri from "lbryuri";
|
|
||||||
|
|
||||||
export const _selectState = state => state.navigation || {};
|
export const selectState = state => state.navigation || {};
|
||||||
|
|
||||||
export const selectCurrentPath = createSelector(
|
export const selectCurrentPath = createSelector(selectState, state => state.currentPath);
|
||||||
_selectState,
|
|
||||||
state => state.currentPath
|
|
||||||
);
|
|
||||||
|
|
||||||
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 =>
|
||||||
computePageFromPath(path)
|
computePageFromPath(path)
|
||||||
|
@ -21,50 +16,47 @@ export const selectCurrentParams = createSelector(selectCurrentPath, path => {
|
||||||
if (path === undefined) return {};
|
if (path === undefined) return {};
|
||||||
if (!path.match(/\?/)) return {};
|
if (!path.match(/\?/)) return {};
|
||||||
|
|
||||||
return parseQueryParams(path.split("?")[1]);
|
return parseQueryParams(path.split('?')[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const makeSelectCurrentParam = param =>
|
export const makeSelectCurrentParam = param =>
|
||||||
createSelector(
|
createSelector(selectCurrentParams, params => (params ? params[param] : undefined));
|
||||||
selectCurrentParams,
|
|
||||||
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
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case "wallet":
|
case 'wallet':
|
||||||
case "history":
|
case 'history':
|
||||||
case "send":
|
case 'send':
|
||||||
case "getcredits":
|
case 'getcredits':
|
||||||
case "invite":
|
case 'invite':
|
||||||
case "rewards":
|
case 'rewards':
|
||||||
case "backup":
|
case 'backup':
|
||||||
return {
|
return {
|
||||||
wallet: __("Overview"),
|
wallet: __('Overview'),
|
||||||
getcredits: __("Get Credits"),
|
getcredits: __('Get Credits'),
|
||||||
send: __("Send / Receive"),
|
send: __('Send / Receive'),
|
||||||
rewards: __("Rewards"),
|
rewards: __('Rewards'),
|
||||||
invite: __("Invites"),
|
invite: __('Invites'),
|
||||||
history: __("History"),
|
history: __('History'),
|
||||||
};
|
};
|
||||||
case "downloaded":
|
case 'downloaded':
|
||||||
case "published":
|
case 'published':
|
||||||
return {
|
return {
|
||||||
downloaded: __("Downloaded"),
|
downloaded: __('Downloaded'),
|
||||||
published: __("Published"),
|
published: __('Published'),
|
||||||
};
|
};
|
||||||
case "settings":
|
case 'settings':
|
||||||
case "help":
|
case 'help':
|
||||||
return {
|
return {
|
||||||
settings: __("Settings"),
|
settings: __('Settings'),
|
||||||
help: __("Help"),
|
help: __('Help'),
|
||||||
};
|
};
|
||||||
case "discover":
|
case 'discover':
|
||||||
case "subscriptions":
|
case 'subscriptions':
|
||||||
return {
|
return {
|
||||||
discover: __("Discover"),
|
discover: __('Discover'),
|
||||||
subscriptions: __("Subscriptions"),
|
subscriptions: __('Subscriptions'),
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
@ -76,86 +68,72 @@ export const selectPageTitle = createSelector(
|
||||||
selectCurrentParams,
|
selectCurrentParams,
|
||||||
(page, params) => {
|
(page, params) => {
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case "settings":
|
case 'settings':
|
||||||
return __("Settings");
|
return __('Settings');
|
||||||
case "report":
|
case 'report':
|
||||||
return __("Report");
|
return __('Report');
|
||||||
case "wallet":
|
case 'wallet':
|
||||||
return __("Wallet");
|
return __('Wallet');
|
||||||
case "send":
|
case 'send':
|
||||||
return __("Send or Receive LBRY Credits");
|
return __('Send or Receive LBRY Credits');
|
||||||
case "getcredits":
|
case 'getcredits':
|
||||||
return __("Get LBRY Credits");
|
return __('Get LBRY Credits');
|
||||||
case "backup":
|
case 'backup':
|
||||||
return __("Backup Your Wallet");
|
return __('Backup Your Wallet');
|
||||||
case "rewards":
|
case 'rewards':
|
||||||
return __("Rewards");
|
return __('Rewards');
|
||||||
case "invite":
|
case 'invite':
|
||||||
return __("Invites");
|
return __('Invites');
|
||||||
case "start":
|
case 'start':
|
||||||
return __("Start");
|
return __('Start');
|
||||||
case "publish":
|
case 'publish':
|
||||||
return params.id ? __("Edit") : __("Publish");
|
return params.id ? __('Edit') : __('Publish');
|
||||||
case "help":
|
case 'help':
|
||||||
return __("Help");
|
return __('Help');
|
||||||
case "developer":
|
case 'developer':
|
||||||
return __("Developer");
|
return __('Developer');
|
||||||
case "show": {
|
case 'show': {
|
||||||
const parts = [lbryuri.normalize(params.uri)];
|
const parts = [Lbryuri.normalize(params.uri)];
|
||||||
// If the params has any keys other than "uri"
|
// If the params has any keys other than "uri"
|
||||||
if (Object.keys(params).length > 1) {
|
if (Object.keys(params).length > 1) {
|
||||||
parts.push(toQueryString(Object.assign({}, params, { uri: null })));
|
parts.push(toQueryString(Object.assign({}, params, { uri: null })));
|
||||||
}
|
}
|
||||||
return parts.join("?");
|
return parts.join('?');
|
||||||
}
|
}
|
||||||
case "downloaded":
|
case 'downloaded':
|
||||||
return __("Downloads & Purchases");
|
return __('Downloads & Purchases');
|
||||||
case "published":
|
case 'published':
|
||||||
return __("Publishes");
|
return __('Publications');
|
||||||
case "search":
|
case 'search':
|
||||||
return params.query
|
return params.query ? __('Search results for %s', params.query) : __('Search');
|
||||||
? __("Search results for %s", params.query)
|
case 'subscriptions':
|
||||||
: __("Search");
|
return __('Your Subscriptions');
|
||||||
case "subscriptions":
|
case 'discover':
|
||||||
return __("Your Subscriptions");
|
|
||||||
case "discover":
|
|
||||||
case false:
|
case false:
|
||||||
case null:
|
case null:
|
||||||
case "":
|
case '':
|
||||||
return "";
|
return '';
|
||||||
default:
|
default:
|
||||||
return page[0].toUpperCase() + (page.length > 0 ? page.substr(1) : "");
|
return page[0].toUpperCase() + (page.length > 0 ? page.substr(1) : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectPathAfterAuth = createSelector(
|
export const selectPathAfterAuth = createSelector(selectState, state => state.pathAfterAuth);
|
||||||
_selectState,
|
|
||||||
state => state.pathAfterAuth
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectIsBackDisabled = createSelector(
|
export const selectIsBackDisabled = createSelector(selectState, state => state.index === 0);
|
||||||
_selectState,
|
|
||||||
state => state.index === 0
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectIsForwardDisabled = createSelector(
|
export const selectIsForwardDisabled = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.index === state.stack.length - 1
|
state => state.index === state.stack.length - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectHistoryIndex = createSelector(
|
export const selectHistoryIndex = createSelector(selectState, state => state.index);
|
||||||
_selectState,
|
|
||||||
state => state.index
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectHistoryStack = createSelector(
|
export const selectHistoryStack = createSelector(selectState, state => state.stack);
|
||||||
_selectState,
|
|
||||||
state => state.stack
|
|
||||||
);
|
|
||||||
|
|
||||||
// returns current page attributes (scrollY, path)
|
// returns current page attributes (scrollY, path)
|
||||||
export const selectActiveHistoryEntry = createSelector(
|
export const selectActiveHistoryEntry = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.stack[state.index]
|
state => state.stack[state.index]
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
import { selectUser } from "redux/selectors/user";
|
import REWARDS from 'rewards';
|
||||||
import rewards from "rewards";
|
|
||||||
|
|
||||||
const _selectState = state => state.rewards || {};
|
const selectState = state => state.rewards || {};
|
||||||
|
|
||||||
export const selectUnclaimedRewardsByType = createSelector(
|
export const selectUnclaimedRewardsByType = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.unclaimedRewardsByType
|
state => state.unclaimedRewardsByType
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectClaimedRewardsById = createSelector(
|
export const selectClaimedRewardsById = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.claimedRewardsById
|
state => state.claimedRewardsById
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -19,13 +18,12 @@ export const selectClaimedRewards = createSelector(
|
||||||
byId => Object.values(byId) || []
|
byId => Object.values(byId) || []
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectClaimedRewardsByTransactionId = createSelector(
|
export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedRewards, rewards =>
|
||||||
selectClaimedRewards,
|
rewards.reduce((mapParam, reward) => {
|
||||||
rewards =>
|
const map = mapParam;
|
||||||
rewards.reduce((map, reward) => {
|
map[reward.transaction_id] = reward;
|
||||||
map[reward.transaction_id] = reward;
|
return map;
|
||||||
return map;
|
}, {})
|
||||||
}, {})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUnclaimedRewards = createSelector(
|
export const selectUnclaimedRewards = createSelector(
|
||||||
|
@ -33,38 +31,20 @@ export const selectUnclaimedRewards = createSelector(
|
||||||
byType =>
|
byType =>
|
||||||
Object.values(byType).sort(
|
Object.values(byType).sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
rewards.SORT_ORDER.indexOf(a.reward_type) <
|
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 selectFetchingRewards = createSelector(selectState, state => !!state.fetching);
|
||||||
selectUser,
|
|
||||||
user => user.can_claim_rewards
|
export const selectUnclaimedRewardValue = createSelector(selectUnclaimedRewards, rewards =>
|
||||||
|
rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectFetchingRewards = createSelector(
|
|
||||||
_selectState,
|
|
||||||
state => !!state.fetching
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUnclaimedRewardValue = createSelector(
|
|
||||||
selectUnclaimedRewards,
|
|
||||||
rewards => rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectHasClaimedReward = (state, props) => {
|
|
||||||
const reward = selectRewardsByType(state)[props.reward_type];
|
|
||||||
return reward && reward.transaction_id !== "";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const makeSelectHasClaimedReward = () =>
|
|
||||||
createSelector(selectHasClaimedReward, claimed => claimed);
|
|
||||||
|
|
||||||
export const selectClaimsPendingByType = createSelector(
|
export const selectClaimsPendingByType = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.claimPendingByType
|
state => state.claimPendingByType
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -75,7 +55,7 @@ export const makeSelectIsRewardClaimPending = () =>
|
||||||
createSelector(selectIsClaimRewardPending, isClaiming => isClaiming);
|
createSelector(selectIsClaimRewardPending, isClaiming => isClaiming);
|
||||||
|
|
||||||
export const selectClaimErrorsByType = createSelector(
|
export const selectClaimErrorsByType = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.claimErrorsByType
|
state => state.claimErrorsByType
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -85,14 +65,9 @@ const selectClaimRewardError = (state, props) =>
|
||||||
export const makeSelectClaimRewardError = () =>
|
export const makeSelectClaimRewardError = () =>
|
||||||
createSelector(selectClaimRewardError, errorMessage => errorMessage);
|
createSelector(selectClaimRewardError, errorMessage => errorMessage);
|
||||||
|
|
||||||
const selectRewardByType = (state, props) =>
|
const selectRewardByType = (state, props) => selectUnclaimedRewardsByType(state)[props.reward_type];
|
||||||
selectUnclaimedRewardsByType(state)[props.reward_type];
|
|
||||||
|
|
||||||
export const makeSelectRewardByType = () =>
|
export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward);
|
||||||
createSelector(selectRewardByType, reward => reward);
|
|
||||||
|
|
||||||
export const makeSelectRewardAmountByType = () =>
|
export const makeSelectRewardAmountByType = () =>
|
||||||
createSelector(
|
createSelector(selectRewardByType, reward => (reward ? reward.reward_amount : 0));
|
||||||
selectRewardByType,
|
|
||||||
reward => (reward ? reward.reward_amount : 0)
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,40 +1,34 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
import {
|
import {
|
||||||
selectPageTitle,
|
selectPageTitle,
|
||||||
selectCurrentPage,
|
selectCurrentPage,
|
||||||
selectCurrentParams,
|
selectCurrentParams,
|
||||||
} from "redux/selectors/navigation";
|
} from 'redux/selectors/navigation';
|
||||||
|
|
||||||
export const _selectState = state => state.search || {};
|
export const selectState = state => state.search || {};
|
||||||
|
|
||||||
export const selectSearchQuery = createSelector(
|
export const selectSearchQuery = createSelector(
|
||||||
selectCurrentPage,
|
selectCurrentPage,
|
||||||
selectCurrentParams,
|
selectCurrentParams,
|
||||||
(page, params) => (page === "search" ? params && params.query : null)
|
(page, params) => (page === 'search' ? params && params.query : null)
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsSearching = createSelector(
|
export const selectIsSearching = createSelector(selectState, state => !!state.searching);
|
||||||
_selectState,
|
|
||||||
state => !!state.searching
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSearchUrisByQuery = createSelector(
|
export const selectSearchUrisByQuery = createSelector(selectState, state => state.urisByQuery);
|
||||||
_selectState,
|
|
||||||
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
|
||||||
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 || title)
|
(page, title, query) => (page !== 'search' ? title : query || title)
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectWunderBarIcon = createSelector(
|
export const selectWunderBarIcon = createSelector(
|
||||||
|
@ -42,44 +36,44 @@ export const selectWunderBarIcon = createSelector(
|
||||||
selectCurrentParams,
|
selectCurrentParams,
|
||||||
(page, params) => {
|
(page, params) => {
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case "auth":
|
case 'auth':
|
||||||
return "icon-user";
|
return 'icon-user';
|
||||||
case "settings":
|
case 'settings':
|
||||||
return "icon-gear";
|
return 'icon-gear';
|
||||||
case "help":
|
case 'help':
|
||||||
return "icon-question";
|
return 'icon-question';
|
||||||
case "report":
|
case 'report':
|
||||||
return "icon-file";
|
return 'icon-file';
|
||||||
case "downloaded":
|
case 'downloaded':
|
||||||
return "icon-folder";
|
return 'icon-folder';
|
||||||
case "published":
|
case 'published':
|
||||||
return "icon-folder";
|
return 'icon-folder';
|
||||||
case "history":
|
case 'history':
|
||||||
return "icon-history";
|
return 'icon-history';
|
||||||
case "send":
|
case 'send':
|
||||||
return "icon-send";
|
return 'icon-send';
|
||||||
case "rewards":
|
case 'rewards':
|
||||||
return "icon-rocket";
|
return 'icon-rocket';
|
||||||
case "invite":
|
case 'invite':
|
||||||
return "icon-envelope-open";
|
return 'icon-envelope-open';
|
||||||
case "getcredits":
|
case 'getcredits':
|
||||||
return "icon-shopping-cart";
|
return 'icon-shopping-cart';
|
||||||
case "wallet":
|
case 'wallet':
|
||||||
case "backup":
|
case 'backup':
|
||||||
return "icon-bank";
|
return 'icon-bank';
|
||||||
case "show":
|
case 'show':
|
||||||
return "icon-file";
|
return 'icon-file';
|
||||||
case "publish":
|
case 'publish':
|
||||||
return params.id ? __("icon-pencil") : __("icon-upload");
|
return params.id ? __('icon-pencil') : __('icon-upload');
|
||||||
case "developer":
|
case 'developer':
|
||||||
return "icon-code";
|
return 'icon-code';
|
||||||
case "discover":
|
case 'discover':
|
||||||
case "search":
|
case 'search':
|
||||||
return "icon-search";
|
return 'icon-search';
|
||||||
case "subscriptions":
|
case 'subscriptions':
|
||||||
return "icon-th-list";
|
return 'icon-th-list';
|
||||||
default:
|
default:
|
||||||
return "icon-file";
|
return 'icon-file';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,24 +1,17 @@
|
||||||
import * as settings from "constants/settings";
|
import * as SETTINGS from 'constants/settings';
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
import path from "path";
|
|
||||||
|
|
||||||
const _selectState = state => state.settings || {};
|
const selectState = state => state.settings || {};
|
||||||
|
|
||||||
export const selectDaemonSettings = createSelector(
|
export const selectDaemonSettings = createSelector(selectState, state => state.daemonSettings);
|
||||||
_selectState,
|
|
||||||
state => state.daemonSettings
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectClientSettings = createSelector(
|
export const selectClientSettings = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.clientSettings || {}
|
state => state.clientSettings || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const makeSelectClientSetting = setting =>
|
export const makeSelectClientSetting = setting =>
|
||||||
createSelector(
|
createSelector(selectClientSettings, settings => (settings ? settings[setting] : undefined));
|
||||||
selectClientSettings,
|
|
||||||
settings => (settings ? settings[setting] : undefined)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSettingsIsGenerous = createSelector(
|
export const selectSettingsIsGenerous = createSelector(
|
||||||
selectDaemonSettings,
|
selectDaemonSettings,
|
||||||
|
@ -26,14 +19,11 @@ export const selectSettingsIsGenerous = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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(selectState, state => state.languages || {});
|
||||||
_selectState,
|
|
||||||
state => state.languages || {}
|
|
||||||
);
|
|
||||||
|
|
||||||
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`
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
const _selectState = state => state.shapeShift;
|
const selectState = state => state.shapeShift;
|
||||||
|
|
||||||
export const selectShapeShift = createSelector(_selectState, state => ({
|
export const selectShapeShift = createSelector(selectState, state => ({
|
||||||
...state,
|
...state,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export { selectShapeShift as default };
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import * as settings from "constants/settings";
|
import { createSelector } from 'reselect';
|
||||||
import { createSelector } from "reselect";
|
import { selectAllClaimsByChannel, selectClaimsById } from './claims';
|
||||||
import { selectAllClaimsByChannel, selectClaimsById } from "./claims";
|
|
||||||
|
|
||||||
// get the entire subscriptions state
|
// get the entire subscriptions state
|
||||||
const _selectState = state => state.subscriptions || {};
|
const selectState = state => state.subscriptions || {};
|
||||||
|
|
||||||
// list of saved channel names and uris
|
// list of saved channel names and uris
|
||||||
export const selectSubscriptions = createSelector(
|
export const selectSubscriptions = createSelector(selectState, state => state.subscriptions);
|
||||||
_selectState,
|
|
||||||
state => state.subscriptions
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectSubscriptionsFromClaims = createSelector(
|
export const selectSubscriptionsFromClaims = createSelector(
|
||||||
selectAllClaimsByChannel,
|
selectAllClaimsByChannel,
|
||||||
|
@ -29,7 +25,7 @@ export const selectSubscriptionsFromClaims = createSelector(
|
||||||
// if subscribed channel has content
|
// if subscribed channel has content
|
||||||
if (channelIds[subscription.uri]) {
|
if (channelIds[subscription.uri]) {
|
||||||
// This will need to be more robust, we will want to be able to load more than the first page
|
// This will need to be more robust, we will want to be able to load more than the first page
|
||||||
const pageOneChannelIds = channelIds[subscription.uri]["1"];
|
const pageOneChannelIds = channelIds[subscription.uri]['1'];
|
||||||
|
|
||||||
// we have the channel ids and the corresponding claims
|
// we have the channel ids and the corresponding claims
|
||||||
// loop over the list of ids and grab the claim
|
// loop over the list of ids and grab the claim
|
||||||
|
@ -40,9 +36,7 @@ export const selectSubscriptionsFromClaims = createSelector(
|
||||||
}
|
}
|
||||||
|
|
||||||
// all we really need is a uri for each claim
|
// all we really need is a uri for each claim
|
||||||
channelClaims = channelClaims.map(
|
channelClaims = channelClaims.map(claim => `${claim.name}#${claim.claim_id}`);
|
||||||
claim => `${claim.name}#${claim.claim_id}`
|
|
||||||
);
|
|
||||||
|
|
||||||
fetchedSubscriptions.push({
|
fetchedSubscriptions.push({
|
||||||
claims: channelClaims,
|
claims: channelClaims,
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
export const _selectState = state => state.user || {};
|
export const selectState = state => state.user || {};
|
||||||
|
|
||||||
export const selectAuthenticationIsPending = createSelector(
|
export const selectAuthenticationIsPending = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.authenticationIsPending
|
state => state.authenticationIsPending
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUserIsPending = createSelector(
|
export const selectUserIsPending = createSelector(selectState, state => state.userIsPending);
|
||||||
_selectState,
|
|
||||||
state => state.userIsPending
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUser = createSelector(_selectState, state => state.user);
|
export const selectUser = createSelector(selectState, state => state.user);
|
||||||
|
|
||||||
export const selectUserEmail = createSelector(
|
export const selectUserEmail = createSelector(
|
||||||
selectUser,
|
selectUser,
|
||||||
|
@ -20,7 +17,7 @@ export const selectUserEmail = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectEmailToVerify = createSelector(
|
export const selectEmailToVerify = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
selectUserEmail,
|
selectUserEmail,
|
||||||
(state, userEmail) => state.emailToVerify || userEmail
|
(state, userEmail) => state.emailToVerify || userEmail
|
||||||
);
|
);
|
||||||
|
@ -31,32 +28,32 @@ export const selectUserIsRewardApproved = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectEmailNewIsPending = createSelector(
|
export const selectEmailNewIsPending = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.emailNewIsPending
|
state => state.emailNewIsPending
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectEmailNewErrorMessage = createSelector(
|
export const selectEmailNewErrorMessage = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.emailNewErrorMessage
|
state => state.emailNewErrorMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectEmailVerifyIsPending = createSelector(
|
export const selectEmailVerifyIsPending = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.emailVerifyIsPending
|
state => state.emailVerifyIsPending
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectEmailVerifyErrorMessage = createSelector(
|
export const selectEmailVerifyErrorMessage = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.emailVerifyErrorMessage
|
state => state.emailVerifyErrorMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIdentityVerifyIsPending = createSelector(
|
export const selectIdentityVerifyIsPending = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.identityVerifyIsPending
|
state => state.identityVerifyIsPending
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIdentityVerifyErrorMessage = createSelector(
|
export const selectIdentityVerifyErrorMessage = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.identityVerifyErrorMessage
|
state => state.identityVerifyErrorMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -65,37 +62,31 @@ export const selectUserIsVerificationCandidate = createSelector(
|
||||||
user => user && (!user.has_verified_email || !user.is_identity_verified)
|
user => user && (!user.has_verified_email || !user.is_identity_verified)
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectAccessToken = createSelector(
|
export const selectAccessToken = createSelector(selectState, state => state.accessToken);
|
||||||
_selectState,
|
|
||||||
state => state.accessToken
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUserInviteStatusIsPending = createSelector(
|
export const selectUserInviteStatusIsPending = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.inviteStatusIsPending
|
state => state.inviteStatusIsPending
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUserInvitesRemaining = createSelector(
|
export const selectUserInvitesRemaining = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.invitesRemaining
|
state => state.invitesRemaining
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUserInvitees = createSelector(
|
export const selectUserInvitees = createSelector(selectState, state => state.invitees);
|
||||||
_selectState,
|
|
||||||
state => state.invitees
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectUserInviteStatusFailed = createSelector(
|
export const selectUserInviteStatusFailed = createSelector(
|
||||||
selectUserInvitesRemaining,
|
selectUserInvitesRemaining,
|
||||||
inviteStatus => selectUserInvitesRemaining === null
|
() => selectUserInvitesRemaining === null
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUserInviteNewIsPending = createSelector(
|
export const selectUserInviteNewIsPending = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.inviteNewIsPending
|
state => state.inviteNewIsPending
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectUserInviteNewErrorMessage = createSelector(
|
export const selectUserInviteNewErrorMessage = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.inviteNewErrorMessage
|
state => state.inviteNewErrorMessage
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,99 +1,81 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
export const _selectState = state => state.wallet || {};
|
export const selectState = state => state.wallet || {};
|
||||||
|
|
||||||
export const selectBalance = createSelector(
|
export const selectBalance = createSelector(selectState, state => state.balance);
|
||||||
_selectState,
|
|
||||||
state => state.balance
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectTransactionsById = createSelector(
|
export const selectTransactionsById = createSelector(selectState, state => state.transactions);
|
||||||
_selectState,
|
|
||||||
state => state.transactions
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectTransactionItems = createSelector(
|
export const selectTransactionItems = createSelector(selectTransactionsById, byId => {
|
||||||
selectTransactionsById,
|
const items = [];
|
||||||
byId => {
|
|
||||||
const items = [];
|
|
||||||
|
|
||||||
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) &&
|
||||||
tx.claim_info.length == 0 &&
|
tx.claim_info.length === 0 &&
|
||||||
tx.support_info.length == 0 &&
|
tx.support_info.length === 0 &&
|
||||||
tx.update_info.length == 0
|
tx.update_info.length === 0
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const append = [];
|
const append = [];
|
||||||
|
|
||||||
|
append.push(
|
||||||
|
...tx.claim_info.map(item =>
|
||||||
|
Object.assign({}, tx, item, {
|
||||||
|
type: item.claim_name[0] === '@' ? 'channel' : 'publish',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
append.push(
|
||||||
|
...tx.support_info.map(item =>
|
||||||
|
Object.assign({}, tx, item, {
|
||||||
|
type: !item.is_tip ? 'support' : 'tip',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
append.push(...tx.update_info.map(item => Object.assign({}, tx, item, { type: 'update' })));
|
||||||
|
|
||||||
|
if (!append.length) {
|
||||||
append.push(
|
append.push(
|
||||||
...tx.claim_info.map(item =>
|
Object.assign({}, tx, {
|
||||||
Object.assign({}, tx, item, {
|
type: tx.value < 0 ? 'spend' : 'receive',
|
||||||
type: item.claim_name[0] === "@" ? "channel" : "publish",
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
append.push(
|
|
||||||
...tx.support_info.map(item =>
|
|
||||||
Object.assign({}, tx, item, {
|
|
||||||
type: !item.is_tip ? "support" : "tip",
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
append.push(
|
|
||||||
...tx.update_info.map(item =>
|
|
||||||
Object.assign({}, tx, item, { type: "update" })
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!append.length) {
|
|
||||||
append.push(
|
|
||||||
Object.assign({}, tx, {
|
|
||||||
type: tx.value < 0 ? "spend" : "receive",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
items.push(
|
|
||||||
...append.map(item => {
|
|
||||||
// value on transaction, amount on outpoint
|
|
||||||
// amount is always positive, but should match sign of value
|
|
||||||
const amount = parseFloat(
|
|
||||||
item.balance_delta ? item.balance_delta : item.value
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
txid,
|
|
||||||
date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null,
|
|
||||||
amount,
|
|
||||||
fee: amount < 0 ? -1 * tx.fee / append.length : 0,
|
|
||||||
claim_id: item.claim_id,
|
|
||||||
claim_name: item.claim_name,
|
|
||||||
type: item.type || "send",
|
|
||||||
nout: item.nout,
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
return items.reverse();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectRecentTransactions = createSelector(
|
items.push(
|
||||||
selectTransactionItems,
|
...append.map(item => {
|
||||||
transactions => {
|
// value on transaction, amount on outpoint
|
||||||
const threshold = new Date();
|
// amount is always positive, but should match sign of value
|
||||||
threshold.setDate(threshold.getDate() - 7);
|
const amount = parseFloat(item.balance_delta ? item.balance_delta : item.value);
|
||||||
return transactions.filter(transaction => transaction.date > threshold);
|
|
||||||
}
|
return {
|
||||||
);
|
txid,
|
||||||
|
date: tx.timestamp ? new Date(Number(tx.timestamp) * 1000) : null,
|
||||||
|
amount,
|
||||||
|
fee: amount < 0 ? -1 * tx.fee / append.length : 0,
|
||||||
|
claim_id: item.claim_id,
|
||||||
|
claim_name: item.claim_name,
|
||||||
|
type: item.type || 'send',
|
||||||
|
nout: item.nout,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return items.reverse();
|
||||||
|
});
|
||||||
|
|
||||||
|
export const selectRecentTransactions = createSelector(selectTransactionItems, transactions => {
|
||||||
|
const threshold = new Date();
|
||||||
|
threshold.setDate(threshold.getDate() - 7);
|
||||||
|
return transactions.filter(transaction => transaction.date > threshold);
|
||||||
|
});
|
||||||
|
|
||||||
export const selectHasTransactions = createSelector(
|
export const selectHasTransactions = createSelector(
|
||||||
selectTransactionItems,
|
selectTransactionItems,
|
||||||
|
@ -101,27 +83,21 @@ export const selectHasTransactions = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsFetchingTransactions = createSelector(
|
export const selectIsFetchingTransactions = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.fetchingTransactions
|
state => state.fetchingTransactions
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsSendingSupport = createSelector(
|
export const selectIsSendingSupport = createSelector(selectState, state => state.sendingSupport);
|
||||||
_selectState,
|
|
||||||
state => state.sendingSupport
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectReceiveAddress = createSelector(
|
export const selectReceiveAddress = createSelector(selectState, state => state.receiveAddress);
|
||||||
_selectState,
|
|
||||||
state => state.receiveAddress
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectGettingNewAddress = createSelector(
|
export const selectGettingNewAddress = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.gettingNewAddress
|
state => state.gettingNewAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectDraftTransaction = createSelector(
|
export const selectDraftTransaction = createSelector(
|
||||||
_selectState,
|
selectState,
|
||||||
state => state.draftTransaction || {}
|
state => state.draftTransaction || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -140,11 +116,10 @@ export const selectDraftTransactionError = createSelector(
|
||||||
draft => draft.error
|
draft => draft.error
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectBlocks = createSelector(_selectState, state => state.blocks);
|
export const selectBlocks = createSelector(selectState, state => state.blocks);
|
||||||
|
|
||||||
export const makeSelectBlockDate = block =>
|
export const makeSelectBlockDate = block =>
|
||||||
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
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,53 +1,32 @@
|
||||||
import lbry from "lbry";
|
import Lbry from 'lbry';
|
||||||
import lbryio from "lbryio";
|
import Lbryio from 'lbryio';
|
||||||
import { doShowSnackBar } from "redux/actions/app";
|
import { doShowSnackBar } from 'redux/actions/app';
|
||||||
|
|
||||||
function rewardMessage(type, amount) {
|
function rewardMessage(type, amount) {
|
||||||
return {
|
return {
|
||||||
new_developer: __(
|
new_developer: __('You earned %s for registering as a new developer.', amount),
|
||||||
"You earned %s for registering as a new developer.",
|
new_user: __('You earned %s LBC new user reward.', amount),
|
||||||
amount
|
confirm_email: __('You earned %s LBC for verifying your email address.', amount),
|
||||||
),
|
new_channel: __('You earned %s LBC for creating a publisher identity.', amount),
|
||||||
new_user: __("You earned %s LBC new user reward.", amount),
|
first_stream: __('You earned %s LBC for streaming your first video.', amount),
|
||||||
confirm_email: __(
|
many_downloads: __('You earned %s LBC for downloading a bunch of things.', amount),
|
||||||
"You earned %s LBC for verifying your email address.",
|
first_publish: __('You earned %s LBC for making your first publication.', amount),
|
||||||
amount
|
featured_download: __('You earned %s LBC for watching a featured download.', amount),
|
||||||
),
|
referral: __('You earned %s LBC for referring someone.', amount),
|
||||||
new_channel: __(
|
|
||||||
"You earned %s LBC for creating a publisher identity.",
|
|
||||||
amount
|
|
||||||
),
|
|
||||||
first_stream: __(
|
|
||||||
"You earned %s LBC for streaming your first video.",
|
|
||||||
amount
|
|
||||||
),
|
|
||||||
many_downloads: __(
|
|
||||||
"You earned %s LBC for downloading a bunch of things.",
|
|
||||||
amount
|
|
||||||
),
|
|
||||||
first_publish: __(
|
|
||||||
"You earned %s LBC for making your first publication.",
|
|
||||||
amount
|
|
||||||
),
|
|
||||||
featured_download: __(
|
|
||||||
"You earned %s LBC for watching a featured download.",
|
|
||||||
amount
|
|
||||||
),
|
|
||||||
referral: __("You earned %s LBC for referring someone.", amount),
|
|
||||||
}[type];
|
}[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
const rewards = {};
|
const rewards = {};
|
||||||
|
|
||||||
rewards.TYPE_NEW_DEVELOPER = "new_developer";
|
rewards.TYPE_NEW_DEVELOPER = 'new_developer';
|
||||||
rewards.TYPE_NEW_USER = "new_user";
|
rewards.TYPE_NEW_USER = 'new_user';
|
||||||
rewards.TYPE_CONFIRM_EMAIL = "verified_email";
|
rewards.TYPE_CONFIRM_EMAIL = 'verified_email';
|
||||||
rewards.TYPE_FIRST_CHANNEL = "new_channel";
|
rewards.TYPE_FIRST_CHANNEL = 'new_channel';
|
||||||
rewards.TYPE_FIRST_STREAM = "first_stream";
|
rewards.TYPE_FIRST_STREAM = 'first_stream';
|
||||||
rewards.TYPE_MANY_DOWNLOADS = "many_downloads";
|
rewards.TYPE_MANY_DOWNLOADS = 'many_downloads';
|
||||||
rewards.TYPE_FIRST_PUBLISH = "first_publish";
|
rewards.TYPE_FIRST_PUBLISH = 'first_publish';
|
||||||
rewards.TYPE_FEATURED_DOWNLOAD = "featured_download";
|
rewards.TYPE_FEATURED_DOWNLOAD = 'featured_download';
|
||||||
rewards.TYPE_REFERRAL = "referral";
|
rewards.TYPE_REFERRAL = 'referral';
|
||||||
rewards.SORT_ORDER = [
|
rewards.SORT_ORDER = [
|
||||||
rewards.TYPE_NEW_USER,
|
rewards.TYPE_NEW_USER,
|
||||||
rewards.TYPE_CONFIRM_EMAIL,
|
rewards.TYPE_CONFIRM_EMAIL,
|
||||||
|
@ -62,18 +41,18 @@ rewards.SORT_ORDER = [
|
||||||
|
|
||||||
rewards.claimReward = function(type) {
|
rewards.claimReward = function(type) {
|
||||||
function requestReward(resolve, reject, params) {
|
function requestReward(resolve, reject, params) {
|
||||||
if (!lbryio.enabled) {
|
if (!Lbryio.enabled) {
|
||||||
reject(new Error(__("Rewards are not enabled.")));
|
reject(new Error(__('Rewards are not enabled.')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lbryio.call("reward", "new", params, "post").then(reward => {
|
Lbryio.call('reward', 'new', params, 'post').then(reward => {
|
||||||
const message = rewardMessage(type, reward.reward_amount);
|
const message = rewardMessage(type, reward.reward_amount);
|
||||||
|
|
||||||
// Display global notice
|
// Display global notice
|
||||||
const action = doShowSnackBar({
|
const action = doShowSnackBar({
|
||||||
message,
|
message,
|
||||||
linkText: __("Show All"),
|
linkText: __('Show All'),
|
||||||
linkTarget: "/rewards",
|
linkTarget: '/rewards',
|
||||||
isError: false,
|
isError: false,
|
||||||
});
|
});
|
||||||
window.app.store.dispatch(action);
|
window.app.store.dispatch(action);
|
||||||
|
@ -85,7 +64,7 @@ rewards.claimReward = function(type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
lbry.wallet_unused_address().then(address => {
|
Lbry.wallet_unused_address().then(address => {
|
||||||
const params = {
|
const params = {
|
||||||
reward_type: type,
|
reward_type: type,
|
||||||
wallet_address: address,
|
wallet_address: address,
|
||||||
|
@ -93,42 +72,38 @@ rewards.claimReward = function(type) {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case rewards.TYPE_FIRST_CHANNEL:
|
case rewards.TYPE_FIRST_CHANNEL:
|
||||||
lbry
|
Lbry.claim_list_mine()
|
||||||
.claim_list_mine()
|
|
||||||
.then(claims => {
|
.then(claims => {
|
||||||
const claim = claims
|
const claim = claims
|
||||||
.reverse()
|
.reverse()
|
||||||
.find(
|
.find(
|
||||||
claim =>
|
foundClaim =>
|
||||||
claim.name.length &&
|
foundClaim.name.length &&
|
||||||
claim.name[0] == "@" &&
|
foundClaim.name[0] === '@' &&
|
||||||
claim.txid.length &&
|
foundClaim.txid.length &&
|
||||||
claim.category == "claim"
|
foundClaim.category === 'claim'
|
||||||
);
|
);
|
||||||
if (claim) {
|
if (claim) {
|
||||||
params.transaction_id = claim.txid;
|
params.transaction_id = claim.txid;
|
||||||
requestReward(resolve, reject, params);
|
requestReward(resolve, reject, params);
|
||||||
} else {
|
} else {
|
||||||
reject(
|
reject(new Error(__('Please create a channel identity first.')));
|
||||||
new Error(__("Please create a channel identity first."))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rewards.TYPE_FIRST_PUBLISH:
|
case rewards.TYPE_FIRST_PUBLISH:
|
||||||
lbry
|
Lbry.claim_list_mine()
|
||||||
.claim_list_mine()
|
|
||||||
.then(claims => {
|
.then(claims => {
|
||||||
const claim = claims
|
const claim = claims
|
||||||
.reverse()
|
.reverse()
|
||||||
.find(
|
.find(
|
||||||
claim =>
|
foundClaim =>
|
||||||
claim.name.length &&
|
foundClaim.name.length &&
|
||||||
claim.name[0] != "@" &&
|
foundClaim.name[0] !== '@' &&
|
||||||
claim.txid.length &&
|
foundClaim.txid.length &&
|
||||||
claim.category == "claim"
|
foundClaim.category === 'claim'
|
||||||
);
|
);
|
||||||
if (claim) {
|
if (claim) {
|
||||||
params.transaction_id = claim.txid;
|
params.transaction_id = claim.txid;
|
||||||
|
@ -138,12 +113,10 @@ rewards.claimReward = function(type) {
|
||||||
claims.length
|
claims.length
|
||||||
? new Error(
|
? new Error(
|
||||||
__(
|
__(
|
||||||
"Please publish something and wait for confirmation by the network to claim this reward."
|
'Please publish something and wait for confirmation by the network to claim this reward.'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
: new Error(
|
: new Error(__('Please publish something to claim this reward.'))
|
||||||
__("Please publish something to claim this reward.")
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
@import url(https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700);
|
@import url(https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700);
|
||||||
|
|
||||||
html
|
html {
|
||||||
{
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: var(--font-size);
|
font-size: var(--font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
body
|
body {
|
||||||
{
|
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
line-height: var(--font-line-height);
|
line-height: var(--font-line-height);
|
||||||
|
@ -19,30 +17,25 @@ body
|
||||||
color: var(--text-selection-color);
|
color: var(--text-selection-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#window
|
#window {
|
||||||
{
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: var(--window-bg);
|
background: var(--window-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount--indicator
|
.credit-amount--indicator {
|
||||||
{
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--color-money);
|
color: var(--color-money);
|
||||||
}
|
}
|
||||||
.credit-amount--fee
|
.credit-amount--fee {
|
||||||
{
|
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
color: var(--color-meta-light);
|
color: var(--color-meta-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.credit-amount--bold
|
.credit-amount--bold {
|
||||||
{
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-content
|
#main-content {
|
||||||
{
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -58,8 +51,7 @@ body
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
main.main--single-column
|
main.main--single-column {
|
||||||
{
|
|
||||||
width: $width-page-constrained;
|
width: $width-page-constrained;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +68,7 @@ body
|
||||||
background: url('../../../static/img/busy.gif') no-repeat center center;
|
background: url('../../../static/img/busy.gif') no-repeat center center;
|
||||||
width: $width;
|
width: $width;
|
||||||
height: $spacing-vertical;
|
height: $spacing-vertical;
|
||||||
content: "";
|
content: '';
|
||||||
left: 50%;
|
left: 50%;
|
||||||
margin-left: -1 / 2 * $width;
|
margin-left: -1 / 2 * $width;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -93,30 +85,37 @@ h2 {
|
||||||
font-size: 1.75em;
|
font-size: 1.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 { font-size: 1.4em; }
|
h3 {
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 { font-size: 1.1em; }
|
h5 {
|
||||||
sup, sub {
|
font-size: 1.1em;
|
||||||
vertical-align: baseline;
|
}
|
||||||
position: relative;
|
sup,
|
||||||
|
sub {
|
||||||
|
vertical-align: baseline;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
sup {
|
||||||
|
top: -0.4em;
|
||||||
|
}
|
||||||
|
sub {
|
||||||
|
top: 0.4em;
|
||||||
}
|
}
|
||||||
sup { top: -0.4em; }
|
|
||||||
sub { top: 0.4em; }
|
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace;
|
font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace;
|
||||||
background-color: var(--color-bg-alt);
|
background-color: var(--color-bg-alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
p
|
p {
|
||||||
{
|
|
||||||
margin-bottom: 0.8em;
|
margin-bottom: 0.8em;
|
||||||
&:last-child
|
&:last-child {
|
||||||
{
|
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,8 +136,7 @@ p
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
.busy-indicator
|
.busy-indicator {
|
||||||
{
|
|
||||||
background: url('../../../static/img/busy.gif') no-repeat center center;
|
background: url('../../../static/img/busy.gif') no-repeat center center;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: -1em 0;
|
margin: -1em 0;
|
||||||
|
@ -146,30 +144,26 @@ p
|
||||||
min-height: 8px;
|
min-height: 8px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding: 0 30px;
|
padding: 0 30px;
|
||||||
&:last-child
|
&:last-child {
|
||||||
{
|
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
}
|
}
|
||||||
&:first-child
|
&:first-child {
|
||||||
{
|
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
font-size: .85em;
|
font-size: 0.85em;
|
||||||
color: var(--color-help);
|
color: var(--color-help);
|
||||||
}
|
}
|
||||||
|
|
||||||
.meta
|
.meta {
|
||||||
{
|
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
color: var(--color-meta-light);
|
color: var(--color-meta-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty
|
.empty {
|
||||||
{
|
color: var(--color-meta-light);
|
||||||
color:var(--color-meta-light);
|
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +179,6 @@ p
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: $spacing-vertical * 2/3;
|
margin-bottom: $spacing-vertical * 2/3;
|
||||||
|
|
||||||
|
|
||||||
text-align: right;
|
text-align: right;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
|
@ -196,7 +189,6 @@ section.section-spaced {
|
||||||
margin-bottom: $spacing-vertical;
|
margin-bottom: $spacing-vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-center
|
.text-center {
|
||||||
{
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,39 +1,70 @@
|
||||||
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, select, textarea, p, blockquote, th, td, iframe
|
body,
|
||||||
{
|
div,
|
||||||
margin:0;
|
dl,
|
||||||
padding:0;
|
dt,
|
||||||
|
dd,
|
||||||
|
ul,
|
||||||
|
ol,
|
||||||
|
li,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
form,
|
||||||
|
fieldset,
|
||||||
|
legend,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea,
|
||||||
|
p,
|
||||||
|
blockquote,
|
||||||
|
th,
|
||||||
|
td,
|
||||||
|
iframe {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
:focus
|
:focus {
|
||||||
{
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
input::-webkit-search-cancel-button {
|
input::-webkit-search-cancel-button {
|
||||||
/* Remove default */
|
/* Remove default */
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
table
|
table {
|
||||||
{
|
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-spacing:0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
fieldset, img, iframe
|
fieldset,
|
||||||
{
|
img,
|
||||||
border: 0;
|
iframe {
|
||||||
|
border: 0;
|
||||||
}
|
}
|
||||||
h1, h2, h3, h4, h5, h6
|
h1,
|
||||||
{
|
h2,
|
||||||
font-weight:normal;
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
ol, ul
|
ol,
|
||||||
{
|
ul {
|
||||||
|
list-style-position: inside;
|
||||||
|
> li {
|
||||||
list-style-position: inside;
|
list-style-position: inside;
|
||||||
> li { list-style-position: inside; }
|
}
|
||||||
}
|
}
|
||||||
input, textarea, select
|
input,
|
||||||
{
|
textarea,
|
||||||
font-family:inherit;
|
select {
|
||||||
font-size:inherit;
|
font-family: inherit;
|
||||||
font-weight:inherit;
|
font-size: inherit;
|
||||||
|
font-weight: inherit;
|
||||||
border: 0 none;
|
border: 0 none;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
|
@ -42,8 +73,7 @@ img {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
-ms-interpolation-mode: bicubic;
|
-ms-interpolation-mode: bicubic;
|
||||||
}
|
}
|
||||||
a
|
a {
|
||||||
{
|
color: inherit;
|
||||||
color: inherit;
|
text-decoration: none;
|
||||||
text-decoration: none;
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -6,28 +6,27 @@ $width-page-constrained: 800px;
|
||||||
$text-color: #000;
|
$text-color: #000;
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
|
||||||
/* Colors */
|
/* Colors */
|
||||||
--color-brand: #155B4A;
|
--color-brand: #155b4a;
|
||||||
--color-primary: #155B4A;
|
--color-primary: #155b4a;
|
||||||
--color-primary-light: saturate(lighten(#155B4A, 50%), 20%);
|
--color-primary-light: saturate(lighten(#155b4a, 50%), 20%);
|
||||||
--color-light-alt: hsl(hue(#155B4A), 15, 85);
|
--color-light-alt: hsl(hue(#155b4a), 15, 85);
|
||||||
--color-dark-overlay: rgba(32,32,32,0.9);
|
--color-dark-overlay: rgba(32, 32, 32, 0.9);
|
||||||
--color-help: rgba(0, 0, 0, 0.54);
|
--color-help: rgba(0, 0, 0, 0.54);
|
||||||
--color-notice: #8a6d3b;
|
--color-notice: #8a6d3b;
|
||||||
--color-error: #a94442;
|
--color-error: #a94442;
|
||||||
--color-load-screen-text: #c3c3c3;
|
--color-load-screen-text: #c3c3c3;
|
||||||
--color-meta-light: #505050;
|
--color-meta-light: #505050;
|
||||||
--color-money: #216C2A;
|
--color-money: #216c2a;
|
||||||
--color-download: rgba(0, 0, 0, 0.75);
|
--color-download: rgba(0, 0, 0, 0.75);
|
||||||
--color-canvas: #f5f5f5;
|
--color-canvas: #f5f5f5;
|
||||||
--color-bg: #ffffff;
|
--color-bg: #ffffff;
|
||||||
--color-bg-alt: #D9D9D9;
|
--color-bg-alt: #d9d9d9;
|
||||||
|
|
||||||
/* Misc */
|
/* Misc */
|
||||||
--content-max-width: 1000px;
|
--content-max-width: 1000px;
|
||||||
--nsfw-blur-intensity: 20px;
|
--nsfw-blur-intensity: 20px;
|
||||||
--height-video-embedded: $width-page-constrained * 9 / 16 ;
|
--height-video-embedded: $width-page-constrained * 9 / 16;
|
||||||
|
|
||||||
/* Font */
|
/* Font */
|
||||||
--font-size: 16px;
|
--font-size: 16px;
|
||||||
|
@ -35,20 +34,21 @@ $text-color: #000;
|
||||||
--font-size-subtext-multiple: 0.82;
|
--font-size-subtext-multiple: 0.82;
|
||||||
|
|
||||||
/* Shadows */
|
/* Shadows */
|
||||||
--box-shadow-layer: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
--box-shadow-layer: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
|
||||||
--box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12);
|
--box-shadow-focus: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2),
|
||||||
|
2px 3px 7px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
|
||||||
/* Transition */
|
/* Transition */
|
||||||
--transition-duration: .225s;
|
--transition-duration: 0.225s;
|
||||||
--transition-type: ease;
|
--transition-type: ease;
|
||||||
|
|
||||||
/* Text */
|
/* Text */
|
||||||
--text-color: $text-color;
|
--text-color: $text-color;
|
||||||
--text-help-color: #EEE;
|
--text-help-color: #eee;
|
||||||
--text-max-width: 660px;
|
--text-max-width: 660px;
|
||||||
--text-link-padding: 4px;
|
--text-link-padding: 4px;
|
||||||
--text-selection-bg: rgba(saturate(lighten(#155B4A, 20%), 20%), 1); // temp color
|
--text-selection-bg: rgba(saturate(lighten(#155b4a, 20%), 20%), 1); // temp color
|
||||||
--text-selection-color: #FFF;
|
--text-selection-color: #fff;
|
||||||
|
|
||||||
/* Window */
|
/* Window */
|
||||||
--window-bg: var(--color-canvas);
|
--window-bg: var(--color-canvas);
|
||||||
|
@ -72,7 +72,7 @@ $text-color: #000;
|
||||||
|
|
||||||
/* input:hover */
|
/* input:hover */
|
||||||
--input-hover-border-color: rgba(0, 0, 0, 0.87);
|
--input-hover-border-color: rgba(0, 0, 0, 0.87);
|
||||||
/* input:placeholder */
|
/* input:placeholder */
|
||||||
--input-placeholder-color: rgba(0, 0, 0, 0.42);
|
--input-placeholder-color: rgba(0, 0, 0, 0.42);
|
||||||
--input-placeholder-opacity: 1;
|
--input-placeholder-opacity: 1;
|
||||||
|
|
||||||
|
@ -82,9 +82,9 @@ $text-color: #000;
|
||||||
|
|
||||||
/* Button */
|
/* Button */
|
||||||
--button-bg: var(--color-bg-alt);
|
--button-bg: var(--color-bg-alt);
|
||||||
--button-color: #FFF;
|
--button-color: #fff;
|
||||||
--button-primary-bg: var(--color-primary);
|
--button-primary-bg: var(--color-primary);
|
||||||
--button-primary-color: #FFF;
|
--button-primary-color: #fff;
|
||||||
--button-padding: $spacing-vertical * 2/3;
|
--button-padding: $spacing-vertical * 2/3;
|
||||||
--button-height: $spacing-vertical * 1.5;
|
--button-height: $spacing-vertical * 1.5;
|
||||||
--button-intra-margin: $spacing-vertical;
|
--button-intra-margin: $spacing-vertical;
|
||||||
|
@ -93,14 +93,14 @@ $text-color: #000;
|
||||||
/* Header */
|
/* Header */
|
||||||
--header-bg: var(--color-bg);
|
--header-bg: var(--color-bg);
|
||||||
--header-color: #666;
|
--header-color: #666;
|
||||||
--header-active-color: rgba(0,0,0, 0.85);
|
--header-active-color: rgba(0, 0, 0, 0.85);
|
||||||
--header-height: $spacing-vertical * 2.5;
|
--header-height: $spacing-vertical * 2.5;
|
||||||
--header-button-bg: transparent; //var(--button-bg);
|
--header-button-bg: transparent; //var(--button-bg);
|
||||||
--header-button-hover-bg: rgba(100, 100, 100, 0.15);
|
--header-button-hover-bg: rgba(100, 100, 100, 0.15);
|
||||||
|
|
||||||
/* Header -> search */
|
/* Header -> search */
|
||||||
--search-bg: rgba(255, 255, 255, 0.7);
|
--search-bg: rgba(255, 255, 255, 0.7);
|
||||||
--search-border:1px solid #ccc;
|
--search-border: 1px solid #ccc;
|
||||||
--search-color: #666;
|
--search-color: #666;
|
||||||
--search-active-color: var(--header-active-color);
|
--search-active-color: var(--header-active-color);
|
||||||
--search-active-shadow: 0 0 3px 0px var(--text-selection-bg);
|
--search-active-shadow: 0 0 3px 0px var(--text-selection-bg);
|
||||||
|
@ -130,7 +130,7 @@ $text-color: #000;
|
||||||
/* Modal */
|
/* Modal */
|
||||||
--modal-width: 440px;
|
--modal-width: 440px;
|
||||||
--modal-bg: var(--color-bg);
|
--modal-bg: var(--color-bg);
|
||||||
--modal-overlay-bg: rgba(#F5F5F5, 0.75); // --color-canvas: #F5F5F5
|
--modal-overlay-bg: rgba(#f5f5f5, 0.75); // --color-canvas: #F5F5F5
|
||||||
--modal-border: 1px solid rgb(204, 204, 204);
|
--modal-border: 1px solid rgb(204, 204, 204);
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
|
@ -146,7 +146,7 @@ $text-color: #000;
|
||||||
|
|
||||||
/* Scrollbar */
|
/* Scrollbar */
|
||||||
--scrollbar-radius: 10px;
|
--scrollbar-radius: 10px;
|
||||||
--scrollbar-thumb-bg: rgba(0, 0, 0, 0.20);
|
--scrollbar-thumb-bg: rgba(0, 0, 0, 0.2);
|
||||||
--scrollbar-thumb-hover-bg: rgba(0, 0, 0, 0.35);
|
--scrollbar-thumb-hover-bg: rgba(0, 0, 0, 0.35);
|
||||||
--scrollbar-thumb-active-bg: var(--color-primary);
|
--scrollbar-thumb-active-bg: var(--color-primary);
|
||||||
--scrollbar-track-bg: transparent;
|
--scrollbar-track-bg: transparent;
|
||||||
|
@ -156,6 +156,5 @@ $text-color: #000;
|
||||||
|
|
||||||
/* Animation :) */
|
/* Animation :) */
|
||||||
--animation-duration: 0.3s;
|
--animation-duration: 0.3s;
|
||||||
--animation-style: cubic-bezier(.55,0,.1,1);
|
--animation-style: cubic-bezier(0.55, 0, 0.1, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
@import "_reset";
|
@import '_reset';
|
||||||
@import "_vars";
|
@import '_vars';
|
||||||
@import "_icons";
|
@import '_icons';
|
||||||
@import "_gui";
|
@import '_gui';
|
||||||
@import "component/_table";
|
@import 'component/_table';
|
||||||
@import "component/_button.scss";
|
@import 'component/_button.scss';
|
||||||
@import "component/_card.scss";
|
@import 'component/_card.scss';
|
||||||
@import "component/_file-download.scss";
|
@import 'component/_file-download.scss';
|
||||||
@import "component/_file-selector.scss";
|
@import 'component/_file-selector.scss';
|
||||||
@import "component/_file-tile.scss";
|
@import 'component/_file-tile.scss';
|
||||||
@import "component/_form-field.scss";
|
@import 'component/_form-field.scss';
|
||||||
@import "component/_header.scss";
|
@import 'component/_header.scss';
|
||||||
@import "component/_menu.scss";
|
@import 'component/_menu.scss';
|
||||||
@import "component/_tooltip.scss";
|
@import 'component/_tooltip.scss';
|
||||||
@import "component/_load-screen.scss";
|
@import 'component/_load-screen.scss';
|
||||||
@import "component/_channel-indicator.scss";
|
@import 'component/_channel-indicator.scss';
|
||||||
@import "component/_notice.scss";
|
@import 'component/_notice.scss';
|
||||||
@import "component/_modal.scss";
|
@import 'component/_modal.scss';
|
||||||
@import "component/_snack-bar.scss";
|
@import 'component/_snack-bar.scss';
|
||||||
@import "component/_video.scss";
|
@import 'component/_video.scss';
|
||||||
@import "component/_pagination.scss";
|
@import 'component/_pagination.scss';
|
||||||
@import "component/_markdown-editor.scss";
|
@import 'component/_markdown-editor.scss';
|
||||||
@import "component/_scrollbar.scss";
|
@import 'component/_scrollbar.scss';
|
||||||
@import "component/_tabs.scss";
|
@import 'component/_tabs.scss';
|
||||||
@import "component/_divider.scss";
|
@import 'component/_divider.scss';
|
||||||
@import "component/_checkbox.scss";
|
@import 'component/_checkbox.scss';
|
||||||
@import "component/_radio.scss";
|
@import 'component/_radio.scss';
|
||||||
@import "component/_shapeshift.scss";
|
@import 'component/_shapeshift.scss';
|
||||||
@import "component/_spinner.scss";
|
@import 'component/_spinner.scss';
|
||||||
@import "page/_show.scss";
|
@import 'page/_show.scss';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "../mixin/link.scss";
|
@import '../mixin/link.scss';
|
||||||
|
|
||||||
$button-focus-shift: 12%;
|
$button-focus-shift: 12%;
|
||||||
|
|
||||||
|
@ -6,14 +6,13 @@ $button-focus-shift: 12%;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
+ .button-set-item
|
+ .button-set-item {
|
||||||
{
|
|
||||||
margin-left: var(--button-intra-margin);
|
margin-left: var(--button-intra-margin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-block, .faux-button-block
|
.button-block,
|
||||||
{
|
.faux-button-block {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: var(--button-height);
|
height: var(--button-height);
|
||||||
line-height: var(--button-height);
|
line-height: var(--button-height);
|
||||||
|
@ -22,26 +21,21 @@ $button-focus-shift: 12%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: var(--button-radius);
|
border-radius: var(--button-radius);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
.icon
|
.icon {
|
||||||
{
|
|
||||||
top: 0em;
|
top: 0em;
|
||||||
}
|
}
|
||||||
.icon:first-child
|
.icon:first-child {
|
||||||
{
|
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
.icon:last-child
|
.icon:last-child {
|
||||||
{
|
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
.icon:only-child
|
.icon:only-child {
|
||||||
{
|
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.button-block
|
.button-block {
|
||||||
{
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -57,9 +51,7 @@ $button-focus-shift: 12%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-primary
|
.button-primary {
|
||||||
{
|
|
||||||
|
|
||||||
color: var(--button-primary-color);
|
color: var(--button-primary-color);
|
||||||
background-color: var(--button-primary-bg);
|
background-color: var(--button-primary-bg);
|
||||||
box-shadow: var(--box-shadow-layer);
|
box-shadow: var(--box-shadow-layer);
|
||||||
|
@ -70,14 +62,12 @@ $button-focus-shift: 12%;
|
||||||
//box-shadow: $box-shadow-focus;
|
//box-shadow: $box-shadow-focus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.button-alt
|
.button-alt {
|
||||||
{
|
|
||||||
background-color: var(--button-bg);
|
background-color: var(--button-bg);
|
||||||
box-shadow: var(--box-shadow-layer);
|
box-shadow: var(--box-shadow-layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-text
|
.button-text {
|
||||||
{
|
|
||||||
@include text-link();
|
@include text-link();
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
|
@ -85,17 +75,15 @@ $button-focus-shift: 12%;
|
||||||
margin: 0 var(--text-link-padding);
|
margin: 0 var(--text-link-padding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.button-text-help
|
.button-text-help {
|
||||||
{
|
|
||||||
@include text-link(var(--text-help-color));
|
@include text-link(var(--text-help-color));
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
.button--flat
|
.button--flat {
|
||||||
{
|
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--submit {
|
.button--submit {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
//below added to prevent scrollbar on long titles when show page loads, would prefer a cleaner CSS solution
|
//below added to prevent scrollbar on long titles when show page loads, would prefer a cleaner CSS solution
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
.card--obscured
|
.card--obscured {
|
||||||
{
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.card--obscured .card__inner {
|
.card--obscured .card__inner {
|
||||||
filter: blur( var(--nsfw-blur-intensity) );
|
filter: blur(var(--nsfw-blur-intensity));
|
||||||
}
|
}
|
||||||
.card__title-primary,
|
.card__title-primary,
|
||||||
.card__title-identity,
|
.card__title-identity,
|
||||||
|
@ -52,7 +51,6 @@
|
||||||
margin-top: var(--card-margin);
|
margin-top: var(--card-margin);
|
||||||
margin-bottom: var(--card-margin);
|
margin-bottom: var(--card-margin);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
.card__actions--bottom {
|
.card__actions--bottom {
|
||||||
margin-top: $spacing-vertical * 1/3;
|
margin-top: $spacing-vertical * 1/3;
|
||||||
|
@ -88,7 +86,7 @@
|
||||||
$font-size-subtext-multiple: 0.82;
|
$font-size-subtext-multiple: 0.82;
|
||||||
.card__subtext {
|
.card__subtext {
|
||||||
color: var(--color-meta-light);
|
color: var(--color-meta-light);
|
||||||
font-size: calc( var(--font-size-subtext-multiple) * 1.0em );
|
font-size: calc(var(--font-size-subtext-multiple) * 1em);
|
||||||
margin-top: $spacing-vertical * 1/3;
|
margin-top: $spacing-vertical * 1/3;
|
||||||
margin-bottom: $spacing-vertical * 1/3;
|
margin-bottom: $spacing-vertical * 1/3;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +94,9 @@ $font-size-subtext-multiple: 0.82;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
.card__subtext--two-lines {
|
.card__subtext--two-lines {
|
||||||
height: calc( var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2); /*this is so one line text still has the proper height*/
|
height: calc(
|
||||||
|
var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2
|
||||||
|
); /*this is so one line text still has the proper height*/
|
||||||
}
|
}
|
||||||
.card-overlay {
|
.card-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -117,7 +117,7 @@ $font-size-subtext-multiple: 0.82;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.card--link {
|
.card--link {
|
||||||
transition: transform 0.2s var(--animation-style);
|
transition: transform 0.2s var(--animation-style);
|
||||||
}
|
}
|
||||||
.card--link:hover {
|
.card--link:hover {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -126,7 +126,7 @@ $font-size-subtext-multiple: 0.82;
|
||||||
transform: scale(var(--card-link-scaling)) translateX(var(--card-hover-translate));
|
transform: scale(var(--card-link-scaling)) translateX(var(--card-hover-translate));
|
||||||
transform-origin: 50% 50%;
|
transform-origin: 50% 50%;
|
||||||
overflow-x: visible;
|
overflow-x: visible;
|
||||||
overflow-y: visible
|
overflow-y: visible;
|
||||||
}
|
}
|
||||||
.card--link:hover ~ .card--link {
|
.card--link:hover ~ .card--link {
|
||||||
transform: translateX(calc(var(--card-hover-translate) * 2));
|
transform: translateX(calc(var(--card-hover-translate) * 2));
|
||||||
|
@ -139,49 +139,49 @@ $font-size-subtext-multiple: 0.82;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__media--autothumb {
|
.card__media--autothumb {
|
||||||
position: relative
|
position: relative;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.purple {
|
.card__media--autothumb.purple {
|
||||||
background-color: #9c27b0
|
background-color: #9c27b0;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.red {
|
.card__media--autothumb.red {
|
||||||
background-color: #e53935
|
background-color: #e53935;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.pink {
|
.card__media--autothumb.pink {
|
||||||
background-color: #e91e63
|
background-color: #e91e63;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.indigo {
|
.card__media--autothumb.indigo {
|
||||||
background-color: #3f51b5
|
background-color: #3f51b5;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.blue {
|
.card__media--autothumb.blue {
|
||||||
background-color: #2196f3
|
background-color: #2196f3;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.light-blue {
|
.card__media--autothumb.light-blue {
|
||||||
background-color: #039be5
|
background-color: #039be5;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.cyan {
|
.card__media--autothumb.cyan {
|
||||||
background-color: #00acc1
|
background-color: #00acc1;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.teal {
|
.card__media--autothumb.teal {
|
||||||
background-color: #009688
|
background-color: #009688;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.green {
|
.card__media--autothumb.green {
|
||||||
background-color: #43a047
|
background-color: #43a047;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.yellow {
|
.card__media--autothumb.yellow {
|
||||||
background-color: #ffeb3b
|
background-color: #ffeb3b;
|
||||||
}
|
}
|
||||||
.card__media--autothumb.orange {
|
.card__media--autothumb.orange {
|
||||||
background-color: #ffa726
|
background-color: #ffa726;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__media--autothumb .card__autothumb__text {
|
.card__media--autothumb .card__autothumb__text {
|
||||||
font-size: 2.0em;
|
font-size: 2em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 36%
|
top: 36%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__indicators {
|
.card__indicators {
|
||||||
|
@ -194,17 +194,17 @@ $font-size-subtext-multiple: 0.82;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
.card--small .card__media {
|
.card--small .card__media {
|
||||||
height: calc( var(--card-small-width) * 9 / 16);
|
height: calc(var(--card-small-width) * 9 / 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card--form {
|
.card--form {
|
||||||
width: calc( var(--input-width) + var(--card-padding) * 2);
|
width: calc(var(--input-width) + var(--card-padding) * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__subtitle {
|
.card__subtitle {
|
||||||
color: var(--color-help);
|
color: var(--color-help);
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
line-height: calc( var(--font-line-height) * 1 / 0.85);
|
line-height: calc(var(--font-line-height) * 1 / 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card--file-subtitle {
|
.card--file-subtitle {
|
||||||
|
@ -219,8 +219,7 @@ $font-size-subtext-multiple: 0.82;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-series-submit
|
.card-series-submit {
|
||||||
{
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
max-width: var(--card-max-width);
|
max-width: var(--card-max-width);
|
||||||
|
@ -279,7 +278,7 @@ $padding-right-card-hover-hack: 30px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 0 var(--card-margin);
|
padding: 0 var(--card-margin);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
top: calc( $padding-top-card-hover-hack - var(--card-margin) );
|
top: calc($padding-top-card-hover-hack - var(--card-margin));
|
||||||
}
|
}
|
||||||
.card-row__nav .card-row__scroll-button {
|
.card-row__nav .card-row__scroll-button {
|
||||||
background: var(--card-bg);
|
background: var(--card-bg);
|
||||||
|
@ -295,8 +294,8 @@ $padding-right-card-hover-hack: 30px;
|
||||||
transition: transform 0.2s var(--animation-style);
|
transition: transform 0.2s var(--animation-style);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1.0;
|
opacity: 1;
|
||||||
transform: scale(calc( var(--card-link-scaling) * 1.1));
|
transform: scale(calc(var(--card-link-scaling) * 1.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.card-row__nav--left {
|
.card-row__nav--left {
|
||||||
|
@ -311,11 +310,11 @@ if we keep doing things like this, we should add a real grid system, but I'm goi
|
||||||
*/
|
*/
|
||||||
.card-grid {
|
.card-grid {
|
||||||
$margin-card-grid: $spacing-vertical * 2/3;
|
$margin-card-grid: $spacing-vertical * 2/3;
|
||||||
display:flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
> .card {
|
> .card {
|
||||||
width: $width-page-constrained / 2 - $margin-card-grid / 2;
|
width: $width-page-constrained / 2 - $margin-card-grid / 2;
|
||||||
flex-grow:1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
> .card:nth-of-type(2n - 1):not(:last-child) {
|
> .card:nth-of-type(2n - 1):not(:last-child) {
|
||||||
margin-right: $margin-card-grid;
|
margin-right: $margin-card-grid;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
.channel-name {
|
.channel-name {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
*, *:before, *:after {
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,17 +9,18 @@ $md-checkbox-border-color: var(--input-border-color);
|
||||||
$md-checkbox-size: 20px;
|
$md-checkbox-size: 20px;
|
||||||
$md-checkbox-padding: 4px;
|
$md-checkbox-padding: 4px;
|
||||||
$md-checkmark-width: 2px;
|
$md-checkmark-width: 2px;
|
||||||
$md-checkmark-color: #FFF;
|
$md-checkmark-color: #fff;
|
||||||
|
|
||||||
.form-field--checkbox {
|
.form-field--checkbox {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:before, &:after {
|
&:before,
|
||||||
content: "";
|
&:after {
|
||||||
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left:0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ $md-checkmark-color: #FFF;
|
||||||
border: 2px solid $md-checkbox-border-color;
|
border: 2px solid $md-checkbox-border-color;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background .3s;
|
transition: background 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
|
@ -37,19 +40,17 @@ $md-checkmark-color: #FFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type='checkbox'] {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
|
|
||||||
&:checked {
|
&:checked {
|
||||||
|
+ label:before {
|
||||||
+ label:before{
|
|
||||||
background: $md-checkbox-checked-color;
|
background: $md-checkbox-checked-color;
|
||||||
border:none;
|
border: none;
|
||||||
}
|
}
|
||||||
+ label:after {
|
+ label:after {
|
||||||
|
|
||||||
$md-checkmark-size: $md-checkbox-size - 2*$md-checkbox-padding;
|
$md-checkmark-size: $md-checkbox-size - 2*$md-checkbox-padding;
|
||||||
|
|
||||||
transform: rotate(-45deg);
|
transform: rotate(-45deg);
|
||||||
|
@ -65,5 +66,4 @@ $md-checkmark-color: #FFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
.file-download, .file-download__overlay {
|
.file-download,
|
||||||
.button__content {
|
.file-download__overlay {
|
||||||
margin: 0 var(--text-link-padding);
|
.button__content {
|
||||||
}
|
margin: 0 var(--text-link-padding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-download
|
.file-download {
|
||||||
{
|
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--color-download);
|
color: var(--color-download);
|
||||||
}
|
}
|
||||||
.file-download__overlay
|
.file-download__overlay {
|
||||||
{
|
|
||||||
background: var(--color-download);
|
background: var(--color-download);
|
||||||
color: var(--color-bg);
|
color: var(--color-bg);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -19,5 +19,4 @@ $height-file-tile: $spacing-vertical * 6;
|
||||||
.card__title-primary {
|
.card__title-primary {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
.form-row-submit
|
.form-row-submit {
|
||||||
{
|
|
||||||
margin-top: $spacing-vertical;
|
margin-top: $spacing-vertical;
|
||||||
}
|
}
|
||||||
.form-row-submit--with-footer
|
.form-row-submit--with-footer {
|
||||||
{
|
|
||||||
margin-bottom: $spacing-vertical;
|
margin-bottom: $spacing-vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +9,7 @@
|
||||||
margin-top: $spacing-vertical * 5/6;
|
margin-top: $spacing-vertical * 5/6;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-size:calc( 0.9 * var(--font-size));
|
font-size: calc(0.9 * var(--font-size));
|
||||||
}
|
}
|
||||||
.form-row__label-row--prefix {
|
.form-row__label-row--prefix {
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -19,7 +17,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-row--focus {
|
.form-row--focus {
|
||||||
.form-field__label, .form-field__prefix {
|
.form-field__label,
|
||||||
|
.form-field__prefix {
|
||||||
color: var(--color-primary) !important;
|
color: var(--color-primary) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,26 +36,27 @@
|
||||||
background: var(--select-bg);
|
background: var(--select-bg);
|
||||||
color: var(--select-color);
|
color: var(--select-color);
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: var(--input-border-size) solid var(--color-primary);
|
outline: var(--input-border-size) solid var(--color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"], input[type="checkbox"], {
|
input[type='radio'],
|
||||||
&:checked + .form-field__label, {
|
input[type='checkbox'] {
|
||||||
|
&:checked + .form-field__label {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"].input-copyable {
|
input[type='text'].input-copyable {
|
||||||
background: var(--input-bg);
|
background: var(--input-bg);
|
||||||
color: var(--input-disabled-color);
|
color: var(--input-disabled-color);
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
padding-top: $spacing-vertical * 1/3;
|
padding-top: $spacing-vertical * 1/3;
|
||||||
padding-bottom: $spacing-vertical * 1/3;
|
padding-bottom: $spacing-vertical * 1/3;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: "Consolas", "Lucida Console", "Adobe Source Code Pro", monospace;
|
font-family: 'Consolas', 'Lucida Console', 'Adobe Source Code Pro', monospace;
|
||||||
|
|
||||||
&.input-copyable--with-copy-btn {
|
&.input-copyable--with-copy-btn {
|
||||||
width: 85%;
|
width: 85%;
|
||||||
|
@ -64,44 +64,44 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
input[readonly] {
|
input[readonly] {
|
||||||
color: var(--input-disabled-color) !important;
|
color: var(--input-disabled-color) !important;
|
||||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[readonly]:focus {
|
input[readonly]:focus {
|
||||||
background: var(--input-bg) !important;
|
background: var(--input-bg) !important;
|
||||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea,
|
textarea,
|
||||||
input[type="text"],
|
input[type='text'],
|
||||||
input[type="password"],
|
input[type='password'],
|
||||||
input[type="email"],
|
input[type='email'],
|
||||||
input[type="number"],
|
input[type='number'],
|
||||||
input[type="search"],
|
input[type='search'],
|
||||||
input[type="date"]{
|
input[type='date'] {
|
||||||
background: var(--input-bg);
|
background: var(--input-bg);
|
||||||
border-bottom: var(--input-border-size) solid var(--input-border-color);
|
border-bottom: var(--input-border-size) solid var(--input-border-color);
|
||||||
caret-color: var(--color-primary);
|
caret-color: var(--color-primary);
|
||||||
color: var(--input-color);
|
color: var(--input-color);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
padding:0 1px 8px 1px;
|
padding: 0 1px 8px 1px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
transition: all var(--transition-duration) var(--transition-type);
|
transition: all var(--transition-duration) var(--transition-type);
|
||||||
|
|
||||||
&::-webkit-input-placeholder {
|
&::-webkit-input-placeholder {
|
||||||
color: var(--input-placeholder-color);
|
color: var(--input-placeholder-color);
|
||||||
opacity: var(--input-placeholder-opacity) !important;
|
opacity: var(--input-placeholder-opacity) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: var(--color-primary);
|
border-color: var(--color-primary);
|
||||||
background: var(--input-active-bg);
|
background: var(--input-active-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover:not(:focus){
|
&:hover:not(:focus) {
|
||||||
border-color: var(--input-hover-border-color);
|
border-color: var(--input-hover-border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,11 +112,10 @@
|
||||||
&.form-field__input--inline {
|
&.form-field__input--inline {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
border-bottom-width: var(--input-border-size);
|
border-bottom-width: var(--input-border-size);
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
|
@ -132,7 +131,8 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field__label, .form-row__label {
|
.form-field__label,
|
||||||
|
.form-row__label {
|
||||||
color: var(--form-label-color);
|
color: var(--form-label-color);
|
||||||
&[for] {
|
&[for] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -167,17 +167,18 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field__error, .form-field__helper {
|
.form-field__error,
|
||||||
|
.form-field__helper {
|
||||||
margin-top: $spacing-vertical * 1/3;
|
margin-top: $spacing-vertical * 1/3;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
transition: opacity var(--transition-duration) var(--transition-type);
|
transition: opacity var(--transition-duration) var(--transition-type);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field__error {
|
.form-field__error {
|
||||||
color: var(--color-error);
|
color: var(--color-error);
|
||||||
}
|
}
|
||||||
.form-field__helper {
|
.form-field__helper {
|
||||||
color:var(--color-help);
|
color: var(--color-help);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll {
|
.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
|
#header {
|
||||||
#header
|
|
||||||
{
|
|
||||||
color: var(--header-color);
|
color: var(--header-color);
|
||||||
background: var(--header-bg);
|
background: var(--header-bg);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -19,11 +17,11 @@
|
||||||
padding-left: $spacing-vertical / 4;
|
padding-left: $spacing-vertical / 4;
|
||||||
padding-right: $spacing-vertical / 4;
|
padding-right: $spacing-vertical / 4;
|
||||||
.button-alt {
|
.button-alt {
|
||||||
background: var(--header-button-bg) !important;
|
background: var(--header-button-bg) !important;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
.button-alt:hover {
|
.button-alt:hover {
|
||||||
background: var(--header-button-hover-bg) !important;
|
background: var(--header-button-hover-bg) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,17 +29,18 @@
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wunderbar
|
.wunderbar {
|
||||||
{
|
|
||||||
position: relative;
|
position: relative;
|
||||||
.icon {
|
.icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
top: $spacing-vertical / 2 - 4px; //hacked
|
top: $spacing-vertical / 2 - 4px; //hacked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wunderbar--active .icon-search { color: var(--color-primary); }
|
.wunderbar--active .icon-search {
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
// below styles should be inside the common input styling
|
// below styles should be inside the common input styling
|
||||||
// will come back to this with the redesign - sean
|
// will come back to this with the redesign - sean
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
.load-screen {
|
.load-screen {
|
||||||
color: white;
|
color: white;
|
||||||
background: var(--color-brand);
|
background: var(--color-brand);
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
background: var(--color-canvas) !important;
|
background: var(--color-canvas) !important;
|
||||||
border: 0px !important;
|
border: 0px !important;
|
||||||
border-radius: 0px !important;
|
border-radius: 0px !important;
|
||||||
color: var(--text-color) !important;
|
color: var(--text-color) !important;
|
||||||
box-shadow: var(--box-shadow-layer);
|
box-shadow: var(--box-shadow-layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar {
|
.editor-toolbar {
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
background: var(--color-bg-alt);
|
background: var(--color-bg-alt);
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
box-shadow: var(--box-shadow-layer);
|
box-shadow: var(--box-shadow-layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar i.separator {
|
.editor-toolbar i.separator {
|
||||||
|
@ -20,85 +20,85 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar.fullscreen {
|
.editor-toolbar.fullscreen {
|
||||||
background: var(--color-bg) !important;
|
background: var(--color-bg) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.editor-toolbar a {
|
div.editor-toolbar a {
|
||||||
opacity: 0.64;
|
opacity: 0.64;
|
||||||
color: var(--text-color) !important;
|
color: var(--text-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar a.active,
|
.editor-toolbar a.active,
|
||||||
.editor-toolbar a:hover {
|
.editor-toolbar a:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background: var(--button-bg) !important;
|
background: var(--button-bg) !important;
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar.disabled-for-preview a:not(.no-disable) {
|
.editor-toolbar.disabled-for-preview a:not(.no-disable) {
|
||||||
background: var(--color-bg-alt) !important;
|
background: var(--color-bg-alt) !important;
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-statusbar {
|
.editor-statusbar {
|
||||||
color: var(--form-label-color) !important;
|
color: var(--form-label-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-preview {
|
.editor-preview {
|
||||||
background: var(--card-bg) !important;
|
background: var(--card-bg) !important;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-preview-side {
|
.editor-preview-side {
|
||||||
background: var(--color-bg-alt) !important;
|
background: var(--color-bg-alt) !important;
|
||||||
border: 1px solid var(--input-border-color) !important;
|
border: 1px solid var(--input-border-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-preview pre,
|
.editor-preview pre,
|
||||||
.editor-preview-side pre {
|
.editor-preview-side pre {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-preview table td,
|
.editor-preview table td,
|
||||||
.editor-preview table th,
|
.editor-preview table th,
|
||||||
.editor-preview-side table td,
|
.editor-preview-side table td,
|
||||||
.editor-preview-side table th {
|
.editor-preview-side table th {
|
||||||
border: 1px solid var(--input-border-color) !important;
|
border: 1px solid var(--input-border-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-tag {
|
.CodeMirror .CodeMirror-code .cm-tag {
|
||||||
color: #63a35c;
|
color: #63a35c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-attribute {
|
.CodeMirror .CodeMirror-code .cm-attribute {
|
||||||
color: #795da3;
|
color: #795da3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-string {
|
.CodeMirror .CodeMirror-code .cm-string {
|
||||||
color: #183691;
|
color: #183691;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-selected {
|
.CodeMirror .CodeMirror-selected {
|
||||||
background: var(--text-selection-bg) !important;
|
background: var(--text-selection-bg) !important;
|
||||||
color: var(--text-selection-color) !important;
|
color: var(--text-selection-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-cursor{
|
.CodeMirror .CodeMirror-cursor {
|
||||||
border-color: var(--color-primary) !important;
|
border-color: var(--color-primary) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-comment {
|
.CodeMirror .CodeMirror-code .cm-comment {
|
||||||
background: rgba(0, 0, 0, .05);
|
background: rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-link {
|
.CodeMirror .CodeMirror-code .cm-link {
|
||||||
color: #7f8c8d;
|
color: #7f8c8d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-url {
|
.CodeMirror .CodeMirror-code .cm-url {
|
||||||
color: #aab2b3;
|
color: #aab2b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-placeholder {
|
.CodeMirror .CodeMirror-placeholder {
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
$border-radius-menu: 2px;
|
$border-radius-menu: 2px;
|
||||||
|
|
||||||
.menu-container {
|
.menu-container {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
.modal-overlay,
|
||||||
.modal-overlay, .error-modal-overlay {
|
.error-modal-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -72,11 +72,12 @@
|
||||||
max-width: none;
|
max-width: none;
|
||||||
width: var(--modal-width);
|
width: var(--modal-width);
|
||||||
}
|
}
|
||||||
.error-modal__error-list { /*shitty hack/temp fix for long errors making modal unusable*/
|
.error-modal__error-list {
|
||||||
|
/*shitty hack/temp fix for long errors making modal unusable*/
|
||||||
border: 1px solid var(--input-border-color);
|
border: 1px solid var(--input-border-color);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
max-width: var(--modal-width);
|
max-width: var(--modal-width);
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
|
|
||||||
.notice {
|
.notice {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
color: #468847;
|
color: #468847;
|
||||||
background-color: #dff0d8;
|
background-color: #dff0d8;
|
||||||
border-color: #d6e9c6;
|
border-color: #d6e9c6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice--error {
|
.notice--error {
|
||||||
color: #b94a48;
|
color: #b94a48;
|
||||||
background-color: #f2dede;
|
background-color: #f2dede;
|
||||||
border-color: #eed3d7;
|
border-color: #eed3d7;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -13,7 +12,9 @@
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
&:not(.pagination__item--selected):hover {
|
&:not(.pagination__item--selected):hover {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
> a { cursor: hand }
|
> a {
|
||||||
|
cursor: hand;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
> a {
|
> a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -21,12 +22,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination__item--previous, .pagination__item--next {
|
.pagination__item--previous,
|
||||||
|
.pagination__item--next {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination__item--break {
|
.pagination__item--break {
|
||||||
padding: 0 $spacing-vertical * 2 / 3;
|
padding: 0 $spacing-vertical * 2 / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination__item--selected {
|
.pagination__item--selected {
|
||||||
|
|
|
@ -5,50 +5,50 @@ $md-radio-checked-size: 10px;
|
||||||
$md-radio-ripple-size: 15px;
|
$md-radio-ripple-size: 15px;
|
||||||
|
|
||||||
.form-field--radio {
|
.form-field--radio {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
transition-property: transform, border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
width: $md-radio-size;
|
||||||
|
height: $md-radio-size;
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid $md-radio-border-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:before, &:after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left:0;
|
|
||||||
top: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: all .3s ease;
|
|
||||||
transition-property: transform, border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
width: $md-radio-size;
|
|
||||||
height: $md-radio-size;
|
|
||||||
background: transparent;
|
|
||||||
border: 2px solid $md-radio-border-color;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
top: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
|
||||||
left: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
|
||||||
width:$md-radio-checked-size;
|
|
||||||
height:$md-radio-checked-size;
|
|
||||||
transform: scale(0);
|
|
||||||
background:$md-radio-checked-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"] {
|
&:after {
|
||||||
visibility: hidden;
|
top: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
||||||
margin-right: 16px;
|
left: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
||||||
|
width: $md-radio-checked-size;
|
||||||
&:checked + label:before {
|
height: $md-radio-checked-size;
|
||||||
border-color: $md-radio-checked-color;
|
transform: scale(0);
|
||||||
}
|
background: $md-radio-checked-color;
|
||||||
|
|
||||||
&:checked + label:after {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='radio'] {
|
||||||
|
visibility: hidden;
|
||||||
|
margin-right: 16px;
|
||||||
|
|
||||||
|
&:checked + label:before {
|
||||||
|
border-color: $md-radio-checked-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked + label:after {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: var(--scrollbar-track-bg);
|
background: var(--scrollbar-track-bg);
|
||||||
border-radius: var(--scrollbar-radius);
|
border-radius: var(--scrollbar-radius);
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
border-radius: var(--scrollbar-radius);
|
border-radius: var(--scrollbar-radius);
|
||||||
background-color: var(--scrollbar-thumb-bg);
|
background-color: var(--scrollbar-thumb-bg);
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
background-color: var(--scrollbar-thumb-hover-bg);
|
background-color: var(--scrollbar-thumb-hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:active {
|
::-webkit-scrollbar-thumb:active {
|
||||||
background-color: var(--scrollbar-thumb-active-bg);
|
background-color: var(--scrollbar-thumb-active-bg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.shapeshift__link {
|
.shapeshift__link {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
$padding-snack-horizontal: $spacing-vertical;
|
$padding-snack-horizontal: $spacing-vertical;
|
||||||
|
|
||||||
.snack-bar {
|
.snack-bar {
|
||||||
|
@ -24,7 +23,7 @@ $padding-snack-horizontal: $spacing-vertical;
|
||||||
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
||||||
transition: all var(--transition-duration) var(--transition-type);
|
transition: all var(--transition-duration) var(--transition-type);
|
||||||
|
|
||||||
z-index: 10000; /*hack to get it over react modal */
|
z-index: 10000; /*hack to get it over react modal */
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,4 +55,4 @@
|
||||||
&:after {
|
&:after {
|
||||||
background: var(--color-bg);
|
background: var(--color-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
table.table-standard {
|
table.table-standard {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
padding: $spacing-vertical/2 8px;
|
padding: $spacing-vertical/2 8px;
|
||||||
}
|
}
|
||||||
th {
|
th {
|
||||||
|
@ -13,7 +13,8 @@ table.table-standard {
|
||||||
td {
|
td {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
thead th, > tr:first-child th {
|
thead th,
|
||||||
|
> tr:first-child th {
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
@ -32,7 +33,7 @@ table.table-standard {
|
||||||
}
|
}
|
||||||
tfoot td {
|
tfoot td {
|
||||||
padding: $spacing-vertical / 2 8px;
|
padding: $spacing-vertical / 2 8px;
|
||||||
font-size: .85em;
|
font-size: 0.85em;
|
||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
tr {
|
tr {
|
||||||
|
@ -62,9 +63,19 @@ table.table-stretch {
|
||||||
}
|
}
|
||||||
|
|
||||||
table.table-transactions {
|
table.table-transactions {
|
||||||
td:nth-of-type(1) { width: 15%; }
|
td:nth-of-type(1) {
|
||||||
td:nth-of-type(2) { width: 15%; }
|
width: 15%;
|
||||||
td:nth-of-type(3) { width: 15%; }
|
}
|
||||||
td:nth-of-type(4) { width: 40%; }
|
td:nth-of-type(2) {
|
||||||
td:nth-of-type(5) { width: 15%; }
|
width: 15%;
|
||||||
|
}
|
||||||
|
td:nth-of-type(3) {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
|
td:nth-of-type(4) {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
td:nth-of-type(5) {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
/* Tabs */
|
/* Tabs */
|
||||||
|
|
||||||
nav.sub-header
|
nav.sub-header {
|
||||||
{
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
max-width: $width-page-constrained;
|
max-width: $width-page-constrained;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
border-bottom: var(--divider);
|
border-bottom: var(--divider);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
> a
|
> a {
|
||||||
{
|
|
||||||
height: 38px;
|
height: 38px;
|
||||||
line-height: 38px;
|
line-height: 38px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -21,16 +19,13 @@ nav.sub-header
|
||||||
color: var(--tab-color);
|
color: var(--tab-color);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:first-child
|
&:first-child {
|
||||||
{
|
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
&:last-child
|
&:last-child {
|
||||||
{
|
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
&.sub-header-selected
|
&.sub-header-selected {
|
||||||
{
|
|
||||||
color: var(--tab-active-color);
|
color: var(--tab-active-color);
|
||||||
&:before {
|
&:before {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -45,8 +40,7 @@ nav.sub-header
|
||||||
animation-timing-function: var(--animation-style);
|
animation-timing-function: var(--animation-style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover
|
&:hover {
|
||||||
{
|
|
||||||
color: var(--tab-active-color);
|
color: var(--tab-active-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +54,11 @@ nav.sub-header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@keyframes activeTab {
|
@keyframes activeTab {
|
||||||
from {width: 0;}
|
from {
|
||||||
to {width: 100%;}
|
width: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "../mixin/link.scss";
|
@import '../mixin/link.scss';
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
.tooltip--header .tooltip__link {
|
.tooltip--header .tooltip__link {
|
||||||
@include text-link(#aaa);
|
@include text-link(#aaa);
|
||||||
font-size: calc( var(--font-size) * 3/4 );
|
font-size: calc(var(--font-size) * 3/4);
|
||||||
margin-left: var(--button-padding);
|
margin-left: var(--button-padding);
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
$height-video-embedded: $width-page-constrained * 9 / 16;
|
$height-video-embedded: $width-page-constrained * 9 / 16;
|
||||||
|
|
||||||
video {
|
video {
|
||||||
|
@ -32,13 +31,11 @@ video {
|
||||||
height: $height-video-embedded;
|
height: $height-video-embedded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.video--obscured .video__cover
|
.video--obscured .video__cover {
|
||||||
{
|
|
||||||
position: relative;
|
position: relative;
|
||||||
filter: blur(var(--nsfw-blur-intensity));
|
filter: blur(var(--nsfw-blur-intensity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.video__loading-screen {
|
.video__loading-screen {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
@mixin text-link($color: var(--color-primary), $hover-opacity: 0.70) {
|
@mixin text-link($color: var(--color-primary), $hover-opacity: 0.7) {
|
||||||
.icon
|
.icon {
|
||||||
{
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
@ -15,10 +14,9 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover
|
&:hover {
|
||||||
{
|
|
||||||
opacity: $hover-opacity;
|
opacity: $hover-opacity;
|
||||||
transition: opacity var(--transition-duration) var(--transition-type);
|
transition: opacity var(--transition-duration) var(--transition-type);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
.icon {
|
.icon {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
|
@ -1,29 +1,27 @@
|
||||||
import { createLogger } from "redux-logger";
|
import { createLogger } from 'redux-logger';
|
||||||
import appReducer from "redux/reducers/app";
|
import appReducer from 'redux/reducers/app';
|
||||||
import availabilityReducer from "redux/reducers/availability";
|
import availabilityReducer from 'redux/reducers/availability';
|
||||||
import claimsReducer from "redux/reducers/claims";
|
import claimsReducer from 'redux/reducers/claims';
|
||||||
import contentReducer from "redux/reducers/content";
|
import contentReducer from 'redux/reducers/content';
|
||||||
import costInfoReducer from "redux/reducers/cost_info";
|
import costInfoReducer from 'redux/reducers/cost_info';
|
||||||
import fileInfoReducer from "redux/reducers/file_info";
|
import fileInfoReducer from 'redux/reducers/file_info';
|
||||||
import navigationReducer from "redux/reducers/navigation";
|
import navigationReducer from 'redux/reducers/navigation';
|
||||||
import rewardsReducer from "redux/reducers/rewards";
|
import rewardsReducer from 'redux/reducers/rewards';
|
||||||
import searchReducer from "redux/reducers/search";
|
import searchReducer from 'redux/reducers/search';
|
||||||
import settingsReducer from "redux/reducers/settings";
|
import settingsReducer from 'redux/reducers/settings';
|
||||||
import userReducer from "redux/reducers/user";
|
import userReducer from 'redux/reducers/user';
|
||||||
import walletReducer from "redux/reducers/wallet";
|
import walletReducer from 'redux/reducers/wallet';
|
||||||
import shapeShiftReducer from "redux/reducers/shape_shift";
|
import shapeShiftReducer from 'redux/reducers/shape_shift';
|
||||||
import subscriptionsReducer from "redux/reducers/subscriptions";
|
import subscriptionsReducer from 'redux/reducers/subscriptions';
|
||||||
import { persistStore, autoRehydrate } from "redux-persist";
|
import { persistStore, autoRehydrate } from 'redux-persist';
|
||||||
import createCompressor from "redux-persist-transform-compress";
|
import createCompressor from 'redux-persist-transform-compress';
|
||||||
import createFilter from "redux-persist-transform-filter";
|
import createFilter from 'redux-persist-transform-filter';
|
||||||
import localForage from "localforage";
|
import localForage from 'localforage';
|
||||||
import { createStore, applyMiddleware, compose, combineReducers } from "redux";
|
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||||
import thunk from "redux-thunk";
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
const env = process.env.NODE_ENV || "production"
|
|
||||||
|
|
||||||
function isFunction(object) {
|
function isFunction(object) {
|
||||||
return typeof object === "function";
|
return typeof object === 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNotFunction(object) {
|
function isNotFunction(object) {
|
||||||
|
@ -32,10 +30,8 @@ function isNotFunction(object) {
|
||||||
|
|
||||||
function createBulkThunkMiddleware() {
|
function createBulkThunkMiddleware() {
|
||||||
return ({ dispatch, getState }) => next => action => {
|
return ({ dispatch, getState }) => next => action => {
|
||||||
if (action.type === "BATCH_ACTIONS") {
|
if (action.type === 'BATCH_ACTIONS') {
|
||||||
action.actions
|
action.actions.filter(isFunction).map(actionFn => actionFn(dispatch, getState));
|
||||||
.filter(isFunction)
|
|
||||||
.map(actionFn => actionFn(dispatch, getState));
|
|
||||||
}
|
}
|
||||||
return next(action);
|
return next(action);
|
||||||
};
|
};
|
||||||
|
@ -44,10 +40,8 @@ function createBulkThunkMiddleware() {
|
||||||
function enableBatching(reducer) {
|
function enableBatching(reducer) {
|
||||||
return function batchingReducer(state, action) {
|
return function batchingReducer(state, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "BATCH_ACTIONS":
|
case 'BATCH_ACTIONS':
|
||||||
return action.actions
|
return action.actions.filter(isNotFunction).reduce(batchingReducer, state);
|
||||||
.filter(isNotFunction)
|
|
||||||
.reduce(batchingReducer, state);
|
|
||||||
default:
|
default:
|
||||||
return reducer(state, action);
|
return reducer(state, action);
|
||||||
}
|
}
|
||||||
|
@ -74,13 +68,14 @@ const reducers = combineReducers({
|
||||||
const bulkThunk = createBulkThunkMiddleware();
|
const bulkThunk = createBulkThunkMiddleware();
|
||||||
const middleware = [thunk, bulkThunk];
|
const middleware = [thunk, bulkThunk];
|
||||||
|
|
||||||
if (env === "development") {
|
if (app.env === 'development') {
|
||||||
const logger = createLogger({
|
const logger = createLogger({
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
});
|
});
|
||||||
middleware.push(logger);
|
middleware.push(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||||
|
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
|
@ -88,18 +83,18 @@ const store = createStore(
|
||||||
{}, // initial state
|
{}, // initial state
|
||||||
composeEnhancers(
|
composeEnhancers(
|
||||||
autoRehydrate({
|
autoRehydrate({
|
||||||
log: env === "development",
|
log: app.env === 'development',
|
||||||
}),
|
}),
|
||||||
applyMiddleware(...middleware)
|
applyMiddleware(...middleware)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const compressor = createCompressor();
|
const compressor = createCompressor();
|
||||||
const saveClaimsFilter = createFilter("claims", ["byId", "claimsByUri"]);
|
const saveClaimsFilter = createFilter('claims', ['byId', 'claimsByUri']);
|
||||||
const subscriptionsFilter = createFilter("subscriptions", ["subscriptions"]);
|
const subscriptionsFilter = createFilter('subscriptions', ['subscriptions']);
|
||||||
|
|
||||||
const persistOptions = {
|
const persistOptions = {
|
||||||
whitelist: ["claims", "subscriptions"],
|
whitelist: ['claims', 'subscriptions'],
|
||||||
// Order is important. Needs to be compressed last or other transforms can't
|
// Order is important. Needs to be compressed last or other transforms can't
|
||||||
// read the data
|
// read the data
|
||||||
transforms: [saveClaimsFilter, subscriptionsFilter, compressor],
|
transforms: [saveClaimsFilter, subscriptionsFilter, compressor],
|
||||||
|
@ -109,7 +104,7 @@ const persistOptions = {
|
||||||
|
|
||||||
window.cacheStore = persistStore(store, persistOptions, err => {
|
window.cacheStore = persistStore(store, persistOptions, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error("Unable to load saved settings");
|
console.error('Unable to load saved SETTINGS');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
export type FormikActions = {
|
export type FormikActions = {
|
||||||
setSubmitting: boolean => mixed,
|
setSubmitting: boolean => mixed,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// https://github.com/reactjs/redux/issues/911
|
// https://github.com/reactjs/redux/issues/911
|
||||||
function batchActions(...actions) {
|
function batchActions(...actions) {
|
||||||
return {
|
return {
|
||||||
type: "BATCH_ACTIONS",
|
type: 'BATCH_ACTIONS',
|
||||||
actions,
|
actions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
export function formatCredits(amount, precision) {
|
export function formatCredits(amount, precision) {
|
||||||
return amount.toFixed(precision || 1).replace(/\.?0+$/, "");
|
return amount.toFixed(precision || 1).replace(/\.?0+$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatFullPrice(amount, precision) {
|
export function formatFullPrice(amount, precision = 1) {
|
||||||
let formated = "";
|
let formated = '';
|
||||||
|
|
||||||
const quantity = amount.toString().split(".");
|
const quantity = amount.toString().split('.');
|
||||||
const fraction = quantity[1];
|
const fraction = quantity[1];
|
||||||
|
|
||||||
if (fraction) {
|
if (fraction) {
|
||||||
// Set precision
|
const decimals = fraction.split('');
|
||||||
precision = precision || 1;
|
const first = decimals.filter(number => number !== '0')[0];
|
||||||
|
|
||||||
const decimals = fraction.split("");
|
|
||||||
const first = decimals.filter(number => number != "0")[0];
|
|
||||||
const index = decimals.indexOf(first);
|
const index = decimals.indexOf(first);
|
||||||
|
|
||||||
// Set format fraction
|
// Set format fraction
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
export function parseQueryParams(queryString) {
|
export function parseQueryParams(queryString) {
|
||||||
if (queryString === "") return {};
|
if (queryString === '') return {};
|
||||||
const parts = queryString
|
const parts = queryString
|
||||||
.split("?")
|
.split('?')
|
||||||
.pop()
|
.pop()
|
||||||
.split("&")
|
.split('&')
|
||||||
.map(p => p.split("="));
|
.map(p => p.split('='));
|
||||||
|
|
||||||
const params = {};
|
const params = {};
|
||||||
parts.forEach(arr => {
|
parts.forEach(array => {
|
||||||
params[arr[0]] = arr[1];
|
const [first, second] = array;
|
||||||
|
params[first] = second;
|
||||||
});
|
});
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toQueryString(params) {
|
export function toQueryString(params) {
|
||||||
if (!params) return "";
|
if (!params) return '';
|
||||||
|
|
||||||
const parts = [];
|
const parts = [];
|
||||||
for (const key in params) {
|
Object.keys(params).forEach(key => {
|
||||||
if (params.hasOwnProperty(key) && params[key]) {
|
if (Object.prototype.hasOwnProperty.call(params, key) && params[key]) {
|
||||||
parts.push(`${key}=${params[key]}`);
|
parts.push(`${key}=${params[key]}`);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return parts.join("&");
|
|
||||||
|
return parts.join('&');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
// 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) => (
|
const handleActions = (actionMap, defaultState) => (state = defaultState, action) => {
|
||||||
state = defaultState,
|
|
||||||
action
|
|
||||||
) => {
|
|
||||||
const handler = actionMap[action.type];
|
const handler = actionMap[action.type];
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
|
@ -16,3 +13,5 @@ export const handleActions = (actionMap, defaultState) => (
|
||||||
// returning a copy here breaks redux-persist
|
// returning a copy here breaks redux-persist
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { handleActions as default };
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const { remote } = require("electron");
|
const { remote } = require('electron');
|
||||||
|
|
||||||
const application = remote.app;
|
const application = remote.app;
|
||||||
const dock = application.dock;
|
const { dock } = application;
|
||||||
const win = remote.BrowserWindow.getFocusedWindow();
|
const win = remote.BrowserWindow.getFocusedWindow();
|
||||||
const setBadge = text => {
|
const setBadge = text => {
|
||||||
if (!dock) return;
|
if (!dock) return;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
const { remote } = require("electron");
|
import { remote } from 'electron';
|
||||||
|
|
||||||
const application = remote.app;
|
|
||||||
const win = remote.getCurrentWindow();
|
const win = remote.getCurrentWindow();
|
||||||
|
|
||||||
const setProgressBar = progress => {
|
const setProgressBar = progress => {
|
||||||
|
|
|
@ -19,7 +19,7 @@ const validateAddress = (coinType, address) => {
|
||||||
return coinRegex.test(address);
|
return coinRegex.test(address);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const validateShapeShiftForm = (vals, props) => {
|
export const validateShapeShiftForm = vals => {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
|
|
||||||
if (!vals.returnAddress) {
|
if (!vals.returnAddress) {
|
||||||
|
@ -36,13 +36,13 @@ export const validateShapeShiftForm = (vals, props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const exampleCoinAddresses = {
|
const exampleCoinAddresses = {
|
||||||
BTC: "1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq",
|
BTC: '1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq',
|
||||||
BCH: "1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq",
|
BCH: '1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq',
|
||||||
ETH: "0x8507cA6a274123fC8f80d929AF9D83602bC4e8cC",
|
ETH: '0x8507cA6a274123fC8f80d929AF9D83602bC4e8cC',
|
||||||
DASH: "XedBP7vLPFXbS3URjrH2Z57Fg9SWftBmQ6",
|
DASH: 'XedBP7vLPFXbS3URjrH2Z57Fg9SWftBmQ6',
|
||||||
LTC: "LgZivMvFMTDoqcA5weCQ2QrmRp7pa56bBk",
|
LTC: 'LgZivMvFMTDoqcA5weCQ2QrmRp7pa56bBk',
|
||||||
XMR:
|
XMR:
|
||||||
"466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm",
|
'466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getExampleAddress = coin => exampleCoinAddresses[coin];
|
export const getExampleAddress = coin => exampleCoinAddresses[coin];
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue