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",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"precommit": "lint-staged",
|
||||
"lint": "eslint src/**/*.{js,jsx} --fix",
|
||||
"pretty": "prettier src/**/*.{js,jsx,scss,json} --write"
|
||||
"lint": "eslint 'src/**/*.{js,jsx}' --fix",
|
||||
"pretty-print": "prettier 'src/**/*.{js,jsx,scss,json}' --write"
|
||||
},
|
||||
"keywords": [
|
||||
"lbry"
|
||||
|
|
|
@ -1,68 +1,39 @@
|
|||
/* eslint-disable no-console */
|
||||
// Module imports
|
||||
const {
|
||||
app,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
Menu,
|
||||
Tray,
|
||||
globalShortcut,
|
||||
} = require("electron");
|
||||
const path = require("path");
|
||||
const url = require("url");
|
||||
const jayson = require("jayson");
|
||||
const semver = require("semver");
|
||||
const https = require("https");
|
||||
const keytar = require("keytar");
|
||||
// tree-kill has better cross-platform handling of
|
||||
// killing a process. child-process.kill was unreliable
|
||||
const kill = require("tree-kill");
|
||||
const child_process = require("child_process");
|
||||
const assert = require("assert");
|
||||
import Path from 'path';
|
||||
import Url from 'url';
|
||||
import Jayson from 'jayson';
|
||||
import Semver from 'semver';
|
||||
import Https from 'https';
|
||||
import Keytar from 'keytar';
|
||||
import ChildProcess from 'child_process';
|
||||
import Assert from 'assert';
|
||||
import { app, BrowserWindow, globalShortcut, ipcMain, Menu, Tray } from 'electron';
|
||||
import mainMenu from './menu/mainMenu';
|
||||
|
||||
const localVersion = app.getVersion();
|
||||
const setMenu = require("./menu/main-menu.js");
|
||||
export const contextMenu = require("./menu/context-menu");
|
||||
export { contextMenu as Default } from './menu/contextMenu';
|
||||
|
||||
// Debug configs
|
||||
const isDevelopment = process.env.NODE_ENV === "development";
|
||||
if (isDevelopment) {
|
||||
try {
|
||||
const {
|
||||
default: installExtension,
|
||||
REACT_DEVELOPER_TOOLS,
|
||||
REDUX_DEVTOOLS,
|
||||
} = require("electron-devtools-installer");
|
||||
app.on("ready", () => {
|
||||
[REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => {
|
||||
installExtension(extension)
|
||||
.then(name => console.log(`Added Extension: ${name}`))
|
||||
.catch(err => console.log("An error occurred: ", err));
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
|
||||
// Misc constants
|
||||
const LATEST_RELEASE_API_URL =
|
||||
"https://api.github.com/repos/lbryio/lbry-app/releases/latest";
|
||||
const DAEMON_PATH =
|
||||
process.env.LBRY_DAEMON || path.join(__static, "daemon/lbrynet-daemon");
|
||||
const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest';
|
||||
const DAEMON_PATH = process.env.LBRY_DAEMON || Path.join(__static, 'daemon/lbrynet-daemon');
|
||||
const rendererUrl = isDevelopment
|
||||
? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`
|
||||
: `file://${__dirname}/index.html`;
|
||||
|
||||
const client = jayson.client.http({
|
||||
host: "localhost",
|
||||
const client = Jayson.client.http({
|
||||
host: 'localhost',
|
||||
port: 5279,
|
||||
path: "/",
|
||||
path: '/',
|
||||
timeout: 1000,
|
||||
});
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let win;
|
||||
let rendererWindow;
|
||||
// Also keep the daemon subprocess alive
|
||||
let daemonSubprocess;
|
||||
|
||||
|
@ -95,8 +66,8 @@ function processRequestedUri(uri) {
|
|||
// lbry://channel/#claimid. We remove the slash here as well.
|
||||
// On Linux and Mac, we just return the URI as given.
|
||||
|
||||
if (process.platform === "win32") {
|
||||
return uri.replace(/\/$/, "").replace("/#", "#");
|
||||
if (process.platform === 'win32') {
|
||||
return uri.replace(/\/$/, '').replace('/#', '#');
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
@ -109,223 +80,22 @@ function processRequestedUri(uri) {
|
|||
function openItem(fullPath) {
|
||||
const subprocOptions = {
|
||||
detached: true,
|
||||
stdio: "ignore",
|
||||
stdio: 'ignore',
|
||||
};
|
||||
|
||||
let child;
|
||||
if (process.platform === "darwin") {
|
||||
child = child_process.spawn("open", [fullPath], subprocOptions);
|
||||
} else if (process.platform === "linux") {
|
||||
child = child_process.spawn("xdg-open", [fullPath], subprocOptions);
|
||||
} else if (process.platform === "win32") {
|
||||
child = child_process.spawn(
|
||||
fullPath,
|
||||
Object.assign({}, subprocOptions, { shell: true })
|
||||
);
|
||||
if (process.platform === 'darwin') {
|
||||
child = ChildProcess.spawn('open', [fullPath], subprocOptions);
|
||||
} else if (process.platform === 'linux') {
|
||||
child = ChildProcess.spawn('xdg-open', [fullPath], subprocOptions);
|
||||
} else if (process.platform === 'win32') {
|
||||
child = ChildProcess.spawn(fullPath, Object.assign({}, subprocOptions, { shell: true }));
|
||||
}
|
||||
|
||||
// Causes child process reference to be garbage collected, allowing main process to exit
|
||||
child.unref();
|
||||
}
|
||||
|
||||
function getPidsForProcessName(name) {
|
||||
if (process.platform === "win32") {
|
||||
const tasklistOut = child_process.execSync(
|
||||
`tasklist /fi "Imagename eq ${name}.exe" /nh`,
|
||||
{ encoding: "utf8" }
|
||||
);
|
||||
if (tasklistOut.startsWith("INFO")) {
|
||||
return [];
|
||||
}
|
||||
return tasklistOut.match(/[^\r\n]+/g).map(line => line.split(/\s+/)[1]); // Second column of every non-empty line
|
||||
}
|
||||
const pgrepOut = child_process.spawnSync("pgrep", ["-x", name], {
|
||||
encoding: "utf8",
|
||||
}).stdout;
|
||||
return pgrepOut.match(/\d+/g);
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
// Disable renderer process's webSecurity on development to enable CORS.
|
||||
win = isDevelopment
|
||||
? new BrowserWindow({
|
||||
backgroundColor: "#155B4A",
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
webPreferences: { webSecurity: false },
|
||||
})
|
||||
: new BrowserWindow({
|
||||
backgroundColor: "#155B4A",
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
});
|
||||
|
||||
win.webContents.session.setUserAgent(`LBRY/${localVersion}`);
|
||||
|
||||
win.maximize();
|
||||
if (isDevelopment) {
|
||||
win.webContents.openDevTools();
|
||||
}
|
||||
win.loadURL(rendererUrl);
|
||||
if (openUri) {
|
||||
// We stored and received a URI that an external app requested before we had a window object
|
||||
win.webContents.on("did-finish-load", () => {
|
||||
win.webContents.send("open-uri-requested", openUri);
|
||||
});
|
||||
}
|
||||
|
||||
win.removeAllListeners();
|
||||
|
||||
win.on("close", event => {
|
||||
if (minimize) {
|
||||
event.preventDefault();
|
||||
win.hide();
|
||||
}
|
||||
});
|
||||
|
||||
win.on("closed", () => {
|
||||
win = null;
|
||||
});
|
||||
|
||||
win.on("hide", () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
});
|
||||
|
||||
win.on("show", () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
});
|
||||
|
||||
win.on("blur", () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
|
||||
// Unregisters Alt+F4 shortcut
|
||||
globalShortcut.unregister("Alt+F4");
|
||||
});
|
||||
|
||||
win.on("focus", () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
|
||||
// Registers shortcut for closing(quitting) the app
|
||||
globalShortcut.register("Alt+F4", () => safeQuit());
|
||||
|
||||
win.webContents.send("window-is-focused", null);
|
||||
});
|
||||
|
||||
// Menu bar
|
||||
win.setAutoHideMenuBar(true);
|
||||
win.setMenuBarVisibility(isDevelopment);
|
||||
setMenu();
|
||||
}
|
||||
|
||||
function createTray() {
|
||||
// Minimize to tray logic follows:
|
||||
// Set the tray icon
|
||||
let iconPath;
|
||||
if (process.platform === "darwin") {
|
||||
// Using @2x for mac retina screens so the icon isn't blurry
|
||||
// file name needs to include "Template" at the end for dark menu bar
|
||||
iconPath = path.join(__static, "/img/fav/macTemplate@2x.png");
|
||||
} else {
|
||||
iconPath = path.join(__static, "/img/fav/32x32.png");
|
||||
}
|
||||
|
||||
tray = new Tray(iconPath);
|
||||
tray.setToolTip("LBRY App");
|
||||
tray.setTitle("LBRY");
|
||||
tray.on("double-click", () => {
|
||||
win.show();
|
||||
});
|
||||
}
|
||||
|
||||
// This needs to be done as for linux the context menu doesn't update automatically(docs)
|
||||
function updateTray() {
|
||||
const contextMenu = Menu.buildFromTemplate(getMenuTemplate());
|
||||
if (tray) {
|
||||
tray.setContextMenu(contextMenu);
|
||||
} else {
|
||||
console.log("How did update tray get called without a tray?");
|
||||
}
|
||||
}
|
||||
|
||||
function getMenuTemplate() {
|
||||
return [
|
||||
getToggleItem(),
|
||||
{
|
||||
label: "Quit",
|
||||
click: () => safeQuit(),
|
||||
},
|
||||
];
|
||||
|
||||
function getToggleItem() {
|
||||
if (win.isVisible() && win.isFocused()) {
|
||||
return {
|
||||
label: "Hide LBRY App",
|
||||
click: () => win.hide(),
|
||||
};
|
||||
}
|
||||
return {
|
||||
label: "Show LBRY App",
|
||||
click: () => win.show(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function handleOpenUriRequested(uri) {
|
||||
if (!win) {
|
||||
// Window not created yet, so store up requested URI for when it is
|
||||
openUri = processRequestedUri(uri);
|
||||
} else {
|
||||
if (win.isMinimized()) {
|
||||
win.restore();
|
||||
} else if (!win.isVisible()) {
|
||||
win.show();
|
||||
}
|
||||
|
||||
win.focus();
|
||||
win.webContents.send("open-uri-requested", processRequestedUri(uri));
|
||||
}
|
||||
}
|
||||
|
||||
function handleDaemonSubprocessExited() {
|
||||
console.log("The daemon has exited.");
|
||||
daemonSubprocess = null;
|
||||
if (!daemonStopRequested) {
|
||||
// We didn't request to stop the daemon, so display a
|
||||
// warning and schedule a quit.
|
||||
//
|
||||
// TODO: maybe it would be better to restart the daemon?
|
||||
if (win) {
|
||||
console.log("Did not request daemon stop, so quitting in 5 seconds.");
|
||||
win.loadURL(`file://${__static}/warning.html`);
|
||||
setTimeout(quitNow, 5000);
|
||||
} else {
|
||||
console.log("Did not request daemon stop, so quitting.");
|
||||
quitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function launchDaemon() {
|
||||
assert(!daemonSubprocess, "Tried to launch daemon twice");
|
||||
|
||||
console.log("Launching daemon:", DAEMON_PATH);
|
||||
daemonSubprocess = child_process.spawn(DAEMON_PATH);
|
||||
// Need to handle the data event instead of attaching to
|
||||
// process.stdout because the latter doesn't work. I believe on
|
||||
// windows it buffers stdout and we don't get any meaningful output
|
||||
daemonSubprocess.stdout.on("data", buf => {
|
||||
console.log(String(buf).trim());
|
||||
});
|
||||
daemonSubprocess.stderr.on("data", buf => {
|
||||
console.log(String(buf).trim());
|
||||
});
|
||||
daemonSubprocess.on("exit", handleDaemonSubprocessExited);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quits by first killing the daemon, the calling quitting for real.
|
||||
*/
|
||||
|
@ -334,6 +104,155 @@ export function safeQuit() {
|
|||
app.quit();
|
||||
}
|
||||
|
||||
function getMenuTemplate() {
|
||||
function getToggleItem() {
|
||||
if (rendererWindow.isVisible() && rendererWindow.isFocused()) {
|
||||
return {
|
||||
label: 'Hide LBRY App',
|
||||
click: () => rendererWindow.hide(),
|
||||
};
|
||||
}
|
||||
return {
|
||||
label: 'Show LBRY App',
|
||||
click: () => rendererWindow.show(),
|
||||
};
|
||||
}
|
||||
|
||||
return [
|
||||
getToggleItem(),
|
||||
{
|
||||
label: 'Quit',
|
||||
click: () => safeQuit(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// This needs to be done as for linux the context menu doesn't update automatically(docs)
|
||||
function updateTray() {
|
||||
const trayContextMenu = Menu.buildFromTemplate(getMenuTemplate());
|
||||
if (tray) {
|
||||
tray.setContextMenu(trayContextMenu);
|
||||
} else {
|
||||
console.log('How did update tray get called without a tray?');
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
// Disable renderer process's webSecurity on development to enable CORS.
|
||||
let windowConfiguration = {
|
||||
backgroundColor: '#155B4A',
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
autoHideMenuBar: true,
|
||||
};
|
||||
|
||||
windowConfiguration = isDevelopment
|
||||
? {
|
||||
...windowConfiguration,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
},
|
||||
}
|
||||
: windowConfiguration;
|
||||
|
||||
let window = new BrowserWindow(windowConfiguration);
|
||||
|
||||
window.webContents.session.setUserAgent(`LBRY/${localVersion}`);
|
||||
|
||||
window.maximize();
|
||||
if (isDevelopment) {
|
||||
window.webContents.openDevTools();
|
||||
}
|
||||
window.loadURL(rendererUrl);
|
||||
if (openUri) {
|
||||
// We stored and received a URI that an external app requested before we had a window object
|
||||
window.webContents.on('did-finish-load', () => {
|
||||
window.webContents.send('open-uri-requested', openUri);
|
||||
});
|
||||
}
|
||||
|
||||
window.removeAllListeners();
|
||||
|
||||
window.on('close', event => {
|
||||
if (minimize) {
|
||||
event.preventDefault();
|
||||
window.hide();
|
||||
}
|
||||
});
|
||||
|
||||
window.on('closed', () => {
|
||||
window = null;
|
||||
});
|
||||
|
||||
window.on('hide', () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
});
|
||||
|
||||
window.on('show', () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
});
|
||||
|
||||
window.on('blur', () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
|
||||
// Unregisters Alt+F4 shortcut
|
||||
globalShortcut.unregister('Alt+F4');
|
||||
});
|
||||
|
||||
window.on('focus', () => {
|
||||
// Checks what to show in the tray icon menu
|
||||
if (minimize) updateTray();
|
||||
|
||||
// Registers shortcut for closing(quitting) the app
|
||||
globalShortcut.register('Alt+F4', () => safeQuit());
|
||||
|
||||
window.webContents.send('window-is-focused', null);
|
||||
});
|
||||
|
||||
mainMenu();
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
function createTray() {
|
||||
// Minimize to tray logic follows:
|
||||
// Set the tray icon
|
||||
let iconPath;
|
||||
if (process.platform === 'darwin') {
|
||||
// Using @2x for mac retina screens so the icon isn't blurry
|
||||
// file name needs to include "Template" at the end for dark menu bar
|
||||
iconPath = Path.join(__static, '/img/fav/macTemplate@2x.png');
|
||||
} else {
|
||||
iconPath = Path.join(__static, '/img/fav/32x32.png');
|
||||
}
|
||||
|
||||
tray = new Tray(iconPath);
|
||||
tray.setToolTip('LBRY App');
|
||||
tray.setTitle('LBRY');
|
||||
tray.on('double-click', () => {
|
||||
rendererWindow.show();
|
||||
});
|
||||
}
|
||||
|
||||
function handleOpenUriRequested(uri) {
|
||||
if (!rendererWindow) {
|
||||
// Window not created yet, so store up requested URI for when it is
|
||||
openUri = processRequestedUri(uri);
|
||||
} else {
|
||||
if (rendererWindow.isMinimized()) {
|
||||
rendererWindow.restore();
|
||||
} else if (!rendererWindow.isVisible()) {
|
||||
rendererWindow.show();
|
||||
}
|
||||
|
||||
rendererWindow.focus();
|
||||
rendererWindow.webContents.send('open-uri-requested', processRequestedUri(uri));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Quits without any preparation. When a quit is requested (either through the
|
||||
* interface or through app.quit()), we abort the quit, try to shut down the daemon,
|
||||
|
@ -344,16 +263,52 @@ function quitNow() {
|
|||
safeQuit();
|
||||
}
|
||||
|
||||
function handleDaemonSubprocessExited() {
|
||||
console.log('The daemon has exited.');
|
||||
daemonSubprocess = null;
|
||||
if (!daemonStopRequested) {
|
||||
// We didn't request to stop the daemon, so display a
|
||||
// warning and schedule a quit.
|
||||
//
|
||||
// TODO: maybe it would be better to restart the daemon?
|
||||
if (rendererWindow) {
|
||||
console.log('Did not request daemon stop, so quitting in 5 seconds.');
|
||||
rendererWindow.loadURL(`file://${__static}/warning.html`);
|
||||
setTimeout(quitNow, 5000);
|
||||
} else {
|
||||
console.log('Did not request daemon stop, so quitting.');
|
||||
quitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function launchDaemon() {
|
||||
Assert(!daemonSubprocess, 'Tried to launch daemon twice');
|
||||
|
||||
console.log('Launching daemon:', DAEMON_PATH);
|
||||
daemonSubprocess = ChildProcess.spawn(DAEMON_PATH);
|
||||
// Need to handle the data event instead of attaching to
|
||||
// process.stdout because the latter doesn't work. I believe on
|
||||
// windows it buffers stdout and we don't get any meaningful output
|
||||
daemonSubprocess.stdout.on('data', buf => {
|
||||
console.log(String(buf).trim());
|
||||
});
|
||||
daemonSubprocess.stderr.on('data', buf => {
|
||||
console.log(String(buf).trim());
|
||||
});
|
||||
daemonSubprocess.on('exit', handleDaemonSubprocessExited);
|
||||
}
|
||||
|
||||
const isSecondaryInstance = app.makeSingleInstance(argv => {
|
||||
if (argv.length >= 2) {
|
||||
handleOpenUriRequested(argv[1]); // This will handle restoring and focusing the window
|
||||
} else if (win) {
|
||||
if (win.isMinimized()) {
|
||||
win.restore();
|
||||
} else if (!win.isVisible()) {
|
||||
win.show();
|
||||
} else if (rendererWindow) {
|
||||
if (rendererWindow.isMinimized()) {
|
||||
rendererWindow.restore();
|
||||
} else if (!rendererWindow.isVisible()) {
|
||||
rendererWindow.show();
|
||||
}
|
||||
win.focus();
|
||||
rendererWindow.focus();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -365,126 +320,44 @@ if (isSecondaryInstance) {
|
|||
function launchDaemonIfNotRunning() {
|
||||
// Check if the daemon is already running. If we get
|
||||
// an error its because its not running
|
||||
console.log("Checking for lbrynet daemon");
|
||||
client.request("status", [], (err, res) => {
|
||||
console.log('Checking for lbrynet daemon');
|
||||
client.request('status', [], err => {
|
||||
if (err) {
|
||||
console.log("lbrynet daemon needs to be launched");
|
||||
console.log('lbrynet daemon needs to be launched');
|
||||
launchDaemon();
|
||||
} else {
|
||||
console.log("lbrynet daemon is already running");
|
||||
console.log('lbrynet daemon is already running');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Last resort for killing unresponsive daemon instances.
|
||||
* Looks for any processes called "lbrynet-daemon" and
|
||||
* tries to force kill them.
|
||||
*/
|
||||
function forceKillAllDaemonsAndQuit() {
|
||||
console.log(
|
||||
"Attempting to force kill any running lbrynet-daemon instances..."
|
||||
);
|
||||
|
||||
const daemonPids = getPidsForProcessName("lbrynet-daemon");
|
||||
if (!daemonPids) {
|
||||
console.log("No lbrynet-daemon found running.");
|
||||
quitNow();
|
||||
} else {
|
||||
console.log(
|
||||
`Found ${
|
||||
daemonPids.length
|
||||
} running daemon instances. Attempting to force kill...`
|
||||
);
|
||||
|
||||
for (const pid of daemonPids) {
|
||||
let daemonKillAttemptsComplete = 0;
|
||||
kill(pid, "SIGKILL", err => {
|
||||
daemonKillAttemptsComplete++;
|
||||
if (err) {
|
||||
console.log(
|
||||
`Failed to force kill daemon task with pid ${pid}. Error message: ${
|
||||
err.message
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
console.log(`Force killed daemon task with pid ${pid}.`);
|
||||
}
|
||||
if (daemonKillAttemptsComplete >= daemonPids.length - 1) {
|
||||
quitNow();
|
||||
}
|
||||
});
|
||||
// Taken from webtorrent-desktop
|
||||
function checkLinuxTraySupport(cb) {
|
||||
// Check that we're on Ubuntu (or another debian system) and that we have
|
||||
// libappindicator1.
|
||||
ChildProcess.exec('dpkg --get-selections libappindicator1', (err, stdout) => {
|
||||
if (err) return cb(err);
|
||||
// Unfortunately there's no cleaner way, as far as I can tell, to check
|
||||
// whether a debian package is installed:
|
||||
if (stdout.endsWith('\tinstall\n')) {
|
||||
return cb(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.setAsDefaultProtocolClient("lbry");
|
||||
|
||||
app.on("ready", () => {
|
||||
launchDaemonIfNotRunning();
|
||||
if (process.platform === "linux") {
|
||||
checkLinuxTraySupport(err => {
|
||||
if (!err) createTray();
|
||||
else minimize = false;
|
||||
});
|
||||
} else {
|
||||
createTray();
|
||||
}
|
||||
createWindow();
|
||||
});
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on("window-all-closed", () => {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== "darwin") {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on("before-quit", event => {
|
||||
if (!readyToQuit) {
|
||||
// We need to shutdown the daemon before we're ready to actually quit. This
|
||||
// event will be triggered re-entrantly once preparation is done.
|
||||
event.preventDefault();
|
||||
shutdownDaemonAndQuit();
|
||||
} else {
|
||||
console.log("Quitting.");
|
||||
}
|
||||
});
|
||||
|
||||
app.on("activate", () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (win === null) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
if (process.platform === "darwin") {
|
||||
app.on("open-url", (event, uri) => {
|
||||
handleOpenUriRequested(uri);
|
||||
return cb(new Error('debian package not installed'));
|
||||
});
|
||||
} else if (process.argv.length >= 2) {
|
||||
handleOpenUriRequested(process.argv[1]);
|
||||
}
|
||||
|
||||
// When a quit is attempted, this is called. It attempts to shutdown the daemon,
|
||||
// then calls quitNow() to quit for real.
|
||||
function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
|
||||
function doShutdown() {
|
||||
console.log("Shutting down daemon");
|
||||
console.log('Shutting down daemon');
|
||||
daemonStopRequested = true;
|
||||
client.request("daemon_stop", [], (err, res) => {
|
||||
client.request('daemon_stop', [], err => {
|
||||
if (err) {
|
||||
console.log(
|
||||
`received error when stopping lbrynet-daemon. Error message: ${
|
||||
err.message
|
||||
}\n`
|
||||
);
|
||||
console.log("You will need to manually kill the daemon.");
|
||||
console.log(`received error when stopping lbrynet-daemon. Error message: ${err.message}\n`);
|
||||
console.log('You will need to manually kill the daemon.');
|
||||
} else {
|
||||
console.log("Successfully stopped daemon via RPC call.");
|
||||
console.log('Successfully stopped daemon via RPC call.');
|
||||
quitNow();
|
||||
}
|
||||
});
|
||||
|
@ -493,7 +366,7 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
|
|||
if (daemonSubprocess) {
|
||||
doShutdown();
|
||||
} else if (!evenIfNotStartedByApp) {
|
||||
console.log("Not killing lbrynet-daemon because app did not start it");
|
||||
console.log('Not killing lbrynet-daemon because app did not start it');
|
||||
quitNow();
|
||||
} else {
|
||||
doShutdown();
|
||||
|
@ -503,111 +376,154 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) {
|
|||
// If not, we should wait until the daemon is closed before we start the install.
|
||||
}
|
||||
|
||||
// Taken from webtorrent-desktop
|
||||
function checkLinuxTraySupport(cb) {
|
||||
// Check that we're on Ubuntu (or another debian system) and that we have
|
||||
// libappindicator1.
|
||||
child_process.exec(
|
||||
"dpkg --get-selections libappindicator1",
|
||||
(err, stdout) => {
|
||||
if (err) return cb(err);
|
||||
// Unfortunately there's no cleaner way, as far as I can tell, to check
|
||||
// whether a debian package is installed:
|
||||
if (stdout.endsWith("\tinstall\n")) {
|
||||
cb(null);
|
||||
} else {
|
||||
cb(new Error("debian package not installed"));
|
||||
}
|
||||
}
|
||||
);
|
||||
if (isDevelopment) {
|
||||
import('devtron')
|
||||
.then(({ install }) => {
|
||||
install();
|
||||
console.log('Added Extension: Devtron');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
import('electron-devtools-installer')
|
||||
.then(({ default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS }) => {
|
||||
app.on('ready', () => {
|
||||
[REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => {
|
||||
installExtension(extension)
|
||||
.then(name => console.log(`Added Extension: ${name}`))
|
||||
.catch(err => console.log('An error occurred: ', err));
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
ipcMain.on("upgrade", (event, installerPath) => {
|
||||
app.on("quit", () => {
|
||||
console.log("Launching upgrade installer at", installerPath);
|
||||
app.setAsDefaultProtocolClient('lbry');
|
||||
|
||||
app.on('ready', () => {
|
||||
launchDaemonIfNotRunning();
|
||||
if (process.platform === 'linux') {
|
||||
checkLinuxTraySupport(err => {
|
||||
if (!err) createTray();
|
||||
else minimize = false;
|
||||
});
|
||||
} else {
|
||||
createTray();
|
||||
}
|
||||
rendererWindow = createWindow();
|
||||
});
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', () => {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('before-quit', event => {
|
||||
if (!readyToQuit) {
|
||||
// We need to shutdown the daemon before we're ready to actually quit. This
|
||||
// event will be triggered re-entrantly once preparation is done.
|
||||
event.preventDefault();
|
||||
shutdownDaemonAndQuit();
|
||||
} else {
|
||||
console.log('Quitting.');
|
||||
}
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (rendererWindow === null) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
app.on('open-url', (event, uri) => {
|
||||
handleOpenUriRequested(uri);
|
||||
});
|
||||
} else if (process.argv.length >= 2) {
|
||||
handleOpenUriRequested(process.argv[1]);
|
||||
}
|
||||
|
||||
ipcMain.on('upgrade', (event, installerPath) => {
|
||||
app.on('quit', () => {
|
||||
console.log('Launching upgrade installer at', installerPath);
|
||||
// This gets triggered called after *all* other quit-related events, so
|
||||
// we'll only get here if we're fully prepared and quitting for real.
|
||||
openItem(installerPath);
|
||||
});
|
||||
|
||||
if (win) {
|
||||
win.loadURL(`file://${__static}/upgrade.html`);
|
||||
if (rendererWindow) {
|
||||
rendererWindow.loadURL(`file://${__static}/upgrade.html`);
|
||||
}
|
||||
|
||||
shutdownDaemonAndQuit(true);
|
||||
// wait for daemon to shut down before upgrading
|
||||
// what to do if no shutdown in a long time?
|
||||
console.log("Update downloaded to", installerPath);
|
||||
console.log('Update downloaded to', installerPath);
|
||||
console.log(
|
||||
"The app will close, and you will be prompted to install the latest version of LBRY."
|
||||
'The app will close, and you will be prompted to install the latest version of LBRY.'
|
||||
);
|
||||
console.log("After the install is complete, please reopen the app.");
|
||||
console.log('After the install is complete, please reopen the app.');
|
||||
});
|
||||
|
||||
ipcMain.on("version-info-requested", () => {
|
||||
ipcMain.on('version-info-requested', () => {
|
||||
function formatRc(ver) {
|
||||
// Adds dash if needed to make RC suffix semver friendly
|
||||
return ver.replace(/([^-])rc/, "$1-rc");
|
||||
return ver.replace(/([^-])rc/, '$1-rc');
|
||||
}
|
||||
|
||||
let result = "";
|
||||
let result = '';
|
||||
const opts = {
|
||||
headers: {
|
||||
"User-Agent": `LBRY/${localVersion}`,
|
||||
'User-Agent': `LBRY/${localVersion}`,
|
||||
},
|
||||
};
|
||||
|
||||
const req = https.get(
|
||||
Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)),
|
||||
res => {
|
||||
res.on("data", data => {
|
||||
result += data;
|
||||
});
|
||||
res.on("end", () => {
|
||||
const tagName = JSON.parse(result).tag_name;
|
||||
const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/);
|
||||
if (!remoteVersion) {
|
||||
if (win) {
|
||||
win.webContents.send("version-info-received", null);
|
||||
}
|
||||
} else {
|
||||
const upgradeAvailable = semver.gt(
|
||||
formatRc(remoteVersion),
|
||||
formatRc(localVersion)
|
||||
);
|
||||
if (win) {
|
||||
win.webContents.send("version-info-received", {
|
||||
remoteVersion,
|
||||
localVersion,
|
||||
upgradeAvailable,
|
||||
});
|
||||
}
|
||||
const req = Https.get(Object.assign(opts, Url.parse(LATEST_RELEASE_API_URL)), res => {
|
||||
res.on('data', data => {
|
||||
result += data;
|
||||
});
|
||||
res.on('end', () => {
|
||||
const tagName = JSON.parse(result).tag_name;
|
||||
const [, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/);
|
||||
if (!remoteVersion) {
|
||||
if (rendererWindow) {
|
||||
rendererWindow.webContents.send('version-info-received', null);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
const upgradeAvailable = Semver.gt(formatRc(remoteVersion), formatRc(localVersion));
|
||||
if (rendererWindow) {
|
||||
rendererWindow.webContents.send('version-info-received', {
|
||||
remoteVersion,
|
||||
localVersion,
|
||||
upgradeAvailable,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on("error", err => {
|
||||
console.log("Failed to get current version from GitHub. Error:", err);
|
||||
if (win) {
|
||||
win.webContents.send("version-info-received", null);
|
||||
req.on('error', err => {
|
||||
console.log('Failed to get current version from GitHub. Error:', err);
|
||||
if (rendererWindow) {
|
||||
rendererWindow.webContents.send('version-info-received', null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("get-auth-token", event => {
|
||||
keytar.getPassword("LBRY", "auth_token").then(token => {
|
||||
event.sender.send(
|
||||
"auth-token-response",
|
||||
token ? token.toString().trim() : null
|
||||
);
|
||||
ipcMain.on('get-auth-token', event => {
|
||||
Keytar.getPassword('LBRY', 'auth_token').then(token => {
|
||||
event.sender.send('auth-token-response', token ? token.toString().trim() : null);
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("set-auth-token", (event, token) => {
|
||||
keytar.setPassword(
|
||||
"LBRY",
|
||||
"auth_token",
|
||||
token ? token.toString().trim() : null
|
||||
);
|
||||
ipcMain.on('set-auth-token', (event, token) => {
|
||||
Keytar.setPassword('LBRY', 'auth_token', token ? token.toString().trim() : null);
|
||||
});
|
||||
|
|
|
@ -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 { remote } from "electron";
|
||||
import path from "path";
|
||||
import store from 'store';
|
||||
import { remote } from 'electron';
|
||||
import path from 'path';
|
||||
import y18n from 'y18n';
|
||||
|
||||
const env = process.env.NODE_ENV || "production";
|
||||
const env = process.env.NODE_ENV || 'production';
|
||||
const config = {
|
||||
...require(`./config/${env}`),
|
||||
...import(`./config/${env}`),
|
||||
};
|
||||
const i18n = require("y18n")({
|
||||
directory: path
|
||||
.join(remote.app.getAppPath(), "/../static/locales")
|
||||
.replace(/\\/g, "\\\\"),
|
||||
const i18n = y18n({
|
||||
directory: path.join(remote.app.getAppPath(), '/../static/locales').replace(/\\/g, '\\\\'),
|
||||
updateFiles: false,
|
||||
locale: "en",
|
||||
locale: 'en',
|
||||
});
|
||||
|
||||
const logs = [];
|
||||
|
@ -26,8 +25,17 @@ const app = {
|
|||
},
|
||||
};
|
||||
|
||||
window.__ = i18n.__;
|
||||
window.__n = i18n.__n;
|
||||
// Workaround for https://github.com/electron-userland/electron-webpack/issues/52
|
||||
if (env !== 'development') {
|
||||
window.staticResourcesPath = path
|
||||
.join(remote.app.getAppPath(), '../static')
|
||||
.replace(/\\/g, '\\\\');
|
||||
} else {
|
||||
window.staticResourcesPath = '';
|
||||
}
|
||||
|
||||
global.app = app;
|
||||
module.exports = app;
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
window.__ = i18n.__;
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
window.__n = i18n.__n;
|
||||
window.app = app;
|
||||
|
|
|
@ -1,166 +1,156 @@
|
|||
export const OPEN_MODAL = "OPEN_MODAL";
|
||||
export const CLOSE_MODAL = "CLOSE_MODAL";
|
||||
export const SHOW_SNACKBAR = "SHOW_SNACKBAR";
|
||||
export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
|
||||
export const WINDOW_FOCUSED = "WINDOW_FOCUSED";
|
||||
export const DAEMON_READY = "DAEMON_READY";
|
||||
export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH";
|
||||
export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH";
|
||||
export const VOLUME_CHANGED = "VOLUME_CHANGED";
|
||||
export const OPEN_MODAL = 'OPEN_MODAL';
|
||||
export const CLOSE_MODAL = 'CLOSE_MODAL';
|
||||
export const SHOW_SNACKBAR = 'SHOW_SNACKBAR';
|
||||
export const REMOVE_SNACKBAR_SNACK = 'REMOVE_SNACKBAR_SNACK';
|
||||
export const WINDOW_FOCUSED = 'WINDOW_FOCUSED';
|
||||
export const DAEMON_READY = 'DAEMON_READY';
|
||||
export const DAEMON_VERSION_MATCH = 'DAEMON_VERSION_MATCH';
|
||||
export const DAEMON_VERSION_MISMATCH = 'DAEMON_VERSION_MISMATCH';
|
||||
export const VOLUME_CHANGED = 'VOLUME_CHANGED';
|
||||
|
||||
// Navigation
|
||||
export const CHANGE_AFTER_AUTH_PATH = "CHANGE_AFTER_AUTH_PATH";
|
||||
export const WINDOW_SCROLLED = "WINDOW_SCROLLED";
|
||||
export const HISTORY_NAVIGATE = "HISTORY_NAVIGATE";
|
||||
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
|
||||
export const WINDOW_SCROLLED = 'WINDOW_SCROLLED';
|
||||
export const HISTORY_NAVIGATE = 'HISTORY_NAVIGATE';
|
||||
|
||||
// Upgrades
|
||||
export const UPGRADE_CANCELLED = "UPGRADE_CANCELLED";
|
||||
export const DOWNLOAD_UPGRADE = "DOWNLOAD_UPGRADE";
|
||||
export const UPGRADE_DOWNLOAD_STARTED = "UPGRADE_DOWNLOAD_STARTED";
|
||||
export const UPGRADE_DOWNLOAD_COMPLETED = "UPGRADE_DOWNLOAD_COMPLETED";
|
||||
export const UPGRADE_DOWNLOAD_PROGRESSED = "UPGRADE_DOWNLOAD_PROGRESSED";
|
||||
export const CHECK_UPGRADE_AVAILABLE = "CHECK_UPGRADE_AVAILABLE";
|
||||
export const CHECK_UPGRADE_START = "CHECK_UPGRADE_START";
|
||||
export const CHECK_UPGRADE_SUCCESS = "CHECK_UPGRADE_SUCCESS";
|
||||
export const CHECK_UPGRADE_FAIL = "CHECK_UPGRADE_FAIL";
|
||||
export const CHECK_UPGRADE_SUBSCRIBE = "CHECK_UPGRADE_SUBSCRIBE";
|
||||
export const UPDATE_VERSION = "UPDATE_VERSION";
|
||||
export const UPDATE_REMOTE_VERSION = "UPDATE_REMOTE_VERSION";
|
||||
export const SKIP_UPGRADE = "SKIP_UPGRADE";
|
||||
export const START_UPGRADE = "START_UPGRADE";
|
||||
export const UPGRADE_CANCELLED = 'UPGRADE_CANCELLED';
|
||||
export const DOWNLOAD_UPGRADE = 'DOWNLOAD_UPGRADE';
|
||||
export const UPGRADE_DOWNLOAD_STARTED = 'UPGRADE_DOWNLOAD_STARTED';
|
||||
export const UPGRADE_DOWNLOAD_COMPLETED = 'UPGRADE_DOWNLOAD_COMPLETED';
|
||||
export const UPGRADE_DOWNLOAD_PROGRESSED = 'UPGRADE_DOWNLOAD_PROGRESSED';
|
||||
export const CHECK_UPGRADE_AVAILABLE = 'CHECK_UPGRADE_AVAILABLE';
|
||||
export const CHECK_UPGRADE_START = 'CHECK_UPGRADE_START';
|
||||
export const CHECK_UPGRADE_SUCCESS = 'CHECK_UPGRADE_SUCCESS';
|
||||
export const CHECK_UPGRADE_FAIL = 'CHECK_UPGRADE_FAIL';
|
||||
export const CHECK_UPGRADE_SUBSCRIBE = 'CHECK_UPGRADE_SUBSCRIBE';
|
||||
export const UPDATE_VERSION = 'UPDATE_VERSION';
|
||||
export const UPDATE_REMOTE_VERSION = 'UPDATE_REMOTE_VERSION';
|
||||
export const SKIP_UPGRADE = 'SKIP_UPGRADE';
|
||||
export const START_UPGRADE = 'START_UPGRADE';
|
||||
|
||||
// Wallet
|
||||
export const GET_NEW_ADDRESS_STARTED = "GET_NEW_ADDRESS_STARTED";
|
||||
export const GET_NEW_ADDRESS_COMPLETED = "GET_NEW_ADDRESS_COMPLETED";
|
||||
export const FETCH_TRANSACTIONS_STARTED = "FETCH_TRANSACTIONS_STARTED";
|
||||
export const FETCH_TRANSACTIONS_COMPLETED = "FETCH_TRANSACTIONS_COMPLETED";
|
||||
export const UPDATE_BALANCE = "UPDATE_BALANCE";
|
||||
export const CHECK_ADDRESS_IS_MINE_STARTED = "CHECK_ADDRESS_IS_MINE_STARTED";
|
||||
export const CHECK_ADDRESS_IS_MINE_COMPLETED =
|
||||
"CHECK_ADDRESS_IS_MINE_COMPLETED";
|
||||
export const SET_DRAFT_TRANSACTION_AMOUNT = "SET_DRAFT_TRANSACTION_AMOUNT";
|
||||
export const SET_DRAFT_TRANSACTION_ADDRESS = "SET_DRAFT_TRANSACTION_ADDRESS";
|
||||
export const SEND_TRANSACTION_STARTED = "SEND_TRANSACTION_STARTED";
|
||||
export const SEND_TRANSACTION_COMPLETED = "SEND_TRANSACTION_COMPLETED";
|
||||
export const SEND_TRANSACTION_FAILED = "SEND_TRANSACTION_FAILED";
|
||||
export const FETCH_BLOCK_SUCCESS = "FETCH_BLOCK_SUCCESS";
|
||||
export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED";
|
||||
export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED";
|
||||
export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED";
|
||||
export const GET_NEW_ADDRESS_STARTED = 'GET_NEW_ADDRESS_STARTED';
|
||||
export const GET_NEW_ADDRESS_COMPLETED = 'GET_NEW_ADDRESS_COMPLETED';
|
||||
export const FETCH_TRANSACTIONS_STARTED = 'FETCH_TRANSACTIONS_STARTED';
|
||||
export const FETCH_TRANSACTIONS_COMPLETED = 'FETCH_TRANSACTIONS_COMPLETED';
|
||||
export const UPDATE_BALANCE = 'UPDATE_BALANCE';
|
||||
export const CHECK_ADDRESS_IS_MINE_STARTED = 'CHECK_ADDRESS_IS_MINE_STARTED';
|
||||
export const CHECK_ADDRESS_IS_MINE_COMPLETED = 'CHECK_ADDRESS_IS_MINE_COMPLETED';
|
||||
export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT';
|
||||
export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS';
|
||||
export const SEND_TRANSACTION_STARTED = 'SEND_TRANSACTION_STARTED';
|
||||
export const SEND_TRANSACTION_COMPLETED = 'SEND_TRANSACTION_COMPLETED';
|
||||
export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED';
|
||||
export const FETCH_BLOCK_SUCCESS = 'FETCH_BLOCK_SUCCESS';
|
||||
export const SUPPORT_TRANSACTION_STARTED = 'SUPPORT_TRANSACTION_STARTED';
|
||||
export const SUPPORT_TRANSACTION_COMPLETED = 'SUPPORT_TRANSACTION_COMPLETED';
|
||||
export const SUPPORT_TRANSACTION_FAILED = 'SUPPORT_TRANSACTION_FAILED';
|
||||
|
||||
// Claims
|
||||
export const FETCH_FEATURED_CONTENT_STARTED = "FETCH_FEATURED_CONTENT_STARTED";
|
||||
export const FETCH_FEATURED_CONTENT_COMPLETED =
|
||||
"FETCH_FEATURED_CONTENT_COMPLETED";
|
||||
export const RESOLVE_URIS_STARTED = "RESOLVE_URIS_STARTED";
|
||||
export const RESOLVE_URIS_COMPLETED = "RESOLVE_URIS_COMPLETED";
|
||||
export const FETCH_CHANNEL_CLAIMS_STARTED = "FETCH_CHANNEL_CLAIMS_STARTED";
|
||||
export const FETCH_CHANNEL_CLAIMS_COMPLETED = "FETCH_CHANNEL_CLAIMS_COMPLETED";
|
||||
export const FETCH_CHANNEL_CLAIM_COUNT_STARTED =
|
||||
"FETCH_CHANNEL_CLAIM_COUNT_STARTED";
|
||||
export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED =
|
||||
"FETCH_CHANNEL_CLAIM_COUNT_COMPLETED";
|
||||
export const FETCH_CLAIM_LIST_MINE_STARTED = "FETCH_CLAIM_LIST_MINE_STARTED";
|
||||
export const FETCH_CLAIM_LIST_MINE_COMPLETED =
|
||||
"FETCH_CLAIM_LIST_MINE_COMPLETED";
|
||||
export const ABANDON_CLAIM_STARTED = "ABANDON_CLAIM_STARTED";
|
||||
export const ABANDON_CLAIM_SUCCEEDED = "ABANDON_CLAIM_SUCCEEDED";
|
||||
export const FETCH_CHANNEL_LIST_MINE_STARTED =
|
||||
"FETCH_CHANNEL_LIST_MINE_STARTED";
|
||||
export const FETCH_CHANNEL_LIST_MINE_COMPLETED =
|
||||
"FETCH_CHANNEL_LIST_MINE_COMPLETED";
|
||||
export const CREATE_CHANNEL_STARTED = "CREATE_CHANNEL_STARTED";
|
||||
export const CREATE_CHANNEL_COMPLETED = "CREATE_CHANNEL_COMPLETED";
|
||||
export const PUBLISH_STARTED = "PUBLISH_STARTED";
|
||||
export const PUBLISH_COMPLETED = "PUBLISH_COMPLETED";
|
||||
export const PUBLISH_FAILED = "PUBLISH_FAILED";
|
||||
export const SET_PLAYING_URI = "PLAY_URI";
|
||||
export const FETCH_FEATURED_CONTENT_STARTED = 'FETCH_FEATURED_CONTENT_STARTED';
|
||||
export const FETCH_FEATURED_CONTENT_COMPLETED = 'FETCH_FEATURED_CONTENT_COMPLETED';
|
||||
export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED';
|
||||
export const RESOLVE_URIS_COMPLETED = 'RESOLVE_URIS_COMPLETED';
|
||||
export const FETCH_CHANNEL_CLAIMS_STARTED = 'FETCH_CHANNEL_CLAIMS_STARTED';
|
||||
export const FETCH_CHANNEL_CLAIMS_COMPLETED = 'FETCH_CHANNEL_CLAIMS_COMPLETED';
|
||||
export const FETCH_CHANNEL_CLAIM_COUNT_STARTED = 'FETCH_CHANNEL_CLAIM_COUNT_STARTED';
|
||||
export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED = 'FETCH_CHANNEL_CLAIM_COUNT_COMPLETED';
|
||||
export const FETCH_CLAIM_LIST_MINE_STARTED = 'FETCH_CLAIM_LIST_MINE_STARTED';
|
||||
export const FETCH_CLAIM_LIST_MINE_COMPLETED = 'FETCH_CLAIM_LIST_MINE_COMPLETED';
|
||||
export const ABANDON_CLAIM_STARTED = 'ABANDON_CLAIM_STARTED';
|
||||
export const ABANDON_CLAIM_SUCCEEDED = 'ABANDON_CLAIM_SUCCEEDED';
|
||||
export const FETCH_CHANNEL_LIST_MINE_STARTED = 'FETCH_CHANNEL_LIST_MINE_STARTED';
|
||||
export const FETCH_CHANNEL_LIST_MINE_COMPLETED = 'FETCH_CHANNEL_LIST_MINE_COMPLETED';
|
||||
export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED';
|
||||
export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED';
|
||||
export const PUBLISH_STARTED = 'PUBLISH_STARTED';
|
||||
export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED';
|
||||
export const PUBLISH_FAILED = 'PUBLISH_FAILED';
|
||||
export const SET_PLAYING_URI = 'PLAY_URI';
|
||||
|
||||
// Files
|
||||
export const FILE_LIST_STARTED = "FILE_LIST_STARTED";
|
||||
export const FILE_LIST_SUCCEEDED = "FILE_LIST_SUCCEEDED";
|
||||
export const FETCH_FILE_INFO_STARTED = "FETCH_FILE_INFO_STARTED";
|
||||
export const FETCH_FILE_INFO_COMPLETED = "FETCH_FILE_INFO_COMPLETED";
|
||||
export const FETCH_COST_INFO_STARTED = "FETCH_COST_INFO_STARTED";
|
||||
export const FETCH_COST_INFO_COMPLETED = "FETCH_COST_INFO_COMPLETED";
|
||||
export const LOADING_VIDEO_STARTED = "LOADING_VIDEO_STARTED";
|
||||
export const LOADING_VIDEO_COMPLETED = "LOADING_VIDEO_COMPLETED";
|
||||
export const LOADING_VIDEO_FAILED = "LOADING_VIDEO_FAILED";
|
||||
export const DOWNLOADING_STARTED = "DOWNLOADING_STARTED";
|
||||
export const DOWNLOADING_PROGRESSED = "DOWNLOADING_PROGRESSED";
|
||||
export const DOWNLOADING_COMPLETED = "DOWNLOADING_COMPLETED";
|
||||
export const PLAY_VIDEO_STARTED = "PLAY_VIDEO_STARTED";
|
||||
export const FETCH_AVAILABILITY_STARTED = "FETCH_AVAILABILITY_STARTED";
|
||||
export const FETCH_AVAILABILITY_COMPLETED = "FETCH_AVAILABILITY_COMPLETED";
|
||||
export const FILE_DELETE = "FILE_DELETE";
|
||||
export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
||||
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
|
||||
export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED';
|
||||
export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED';
|
||||
export const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED';
|
||||
export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED';
|
||||
export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED';
|
||||
export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED';
|
||||
export const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED';
|
||||
export const DOWNLOADING_STARTED = 'DOWNLOADING_STARTED';
|
||||
export const DOWNLOADING_PROGRESSED = 'DOWNLOADING_PROGRESSED';
|
||||
export const DOWNLOADING_COMPLETED = 'DOWNLOADING_COMPLETED';
|
||||
export const PLAY_VIDEO_STARTED = 'PLAY_VIDEO_STARTED';
|
||||
export const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED';
|
||||
export const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED';
|
||||
export const FILE_DELETE = 'FILE_DELETE';
|
||||
|
||||
// Search
|
||||
export const SEARCH_STARTED = "SEARCH_STARTED";
|
||||
export const SEARCH_COMPLETED = "SEARCH_COMPLETED";
|
||||
export const SEARCH_CANCELLED = "SEARCH_CANCELLED";
|
||||
export const SEARCH_STARTED = 'SEARCH_STARTED';
|
||||
export const SEARCH_COMPLETED = 'SEARCH_COMPLETED';
|
||||
export const SEARCH_CANCELLED = 'SEARCH_CANCELLED';
|
||||
|
||||
// Settings
|
||||
export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED";
|
||||
export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED";
|
||||
export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED';
|
||||
export const CLIENT_SETTING_CHANGED = 'CLIENT_SETTING_CHANGED';
|
||||
|
||||
// User
|
||||
export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED";
|
||||
export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS";
|
||||
export const AUTHENTICATION_FAILURE = "AUTHENTICATION_FAILURE";
|
||||
export const USER_EMAIL_DECLINE = "USER_EMAIL_DECLINE";
|
||||
export const USER_EMAIL_NEW_STARTED = "USER_EMAIL_NEW_STARTED";
|
||||
export const USER_EMAIL_NEW_SUCCESS = "USER_EMAIL_NEW_SUCCESS";
|
||||
export const USER_EMAIL_NEW_EXISTS = "USER_EMAIL_NEW_EXISTS";
|
||||
export const USER_EMAIL_NEW_FAILURE = "USER_EMAIL_NEW_FAILURE";
|
||||
export const USER_EMAIL_VERIFY_STARTED = "USER_EMAIL_VERIFY_STARTED";
|
||||
export const USER_EMAIL_VERIFY_SUCCESS = "USER_EMAIL_VERIFY_SUCCESS";
|
||||
export const USER_EMAIL_VERIFY_FAILURE = "USER_EMAIL_VERIFY_FAILURE";
|
||||
export const USER_IDENTITY_VERIFY_STARTED = "USER_IDENTITY_VERIFY_STARTED";
|
||||
export const USER_IDENTITY_VERIFY_SUCCESS = "USER_IDENTITY_VERIFY_SUCCESS";
|
||||
export const USER_IDENTITY_VERIFY_FAILURE = "USER_IDENTITY_VERIFY_FAILURE";
|
||||
export const USER_FETCH_STARTED = "USER_FETCH_STARTED";
|
||||
export const USER_FETCH_SUCCESS = "USER_FETCH_SUCCESS";
|
||||
export const USER_FETCH_FAILURE = "USER_FETCH_FAILURE";
|
||||
export const USER_INVITE_STATUS_FETCH_STARTED =
|
||||
"USER_INVITE_STATUS_FETCH_STARTED";
|
||||
export const USER_INVITE_STATUS_FETCH_SUCCESS =
|
||||
"USER_INVITE_STATUS_FETCH_SUCCESS";
|
||||
export const USER_INVITE_STATUS_FETCH_FAILURE =
|
||||
"USER_INVITE_STATUS_FETCH_FAILURE";
|
||||
export const USER_INVITE_NEW_STARTED = "USER_INVITE_NEW_STARTED";
|
||||
export const USER_INVITE_NEW_SUCCESS = "USER_INVITE_NEW_SUCCESS";
|
||||
export const USER_INVITE_NEW_FAILURE = "USER_INVITE_NEW_FAILURE";
|
||||
export const FETCH_ACCESS_TOKEN_SUCCESS = "FETCH_ACCESS_TOKEN_SUCCESS";
|
||||
export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED';
|
||||
export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS';
|
||||
export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE';
|
||||
export const USER_EMAIL_DECLINE = 'USER_EMAIL_DECLINE';
|
||||
export const USER_EMAIL_NEW_STARTED = 'USER_EMAIL_NEW_STARTED';
|
||||
export const USER_EMAIL_NEW_SUCCESS = 'USER_EMAIL_NEW_SUCCESS';
|
||||
export const USER_EMAIL_NEW_EXISTS = 'USER_EMAIL_NEW_EXISTS';
|
||||
export const USER_EMAIL_NEW_FAILURE = 'USER_EMAIL_NEW_FAILURE';
|
||||
export const USER_EMAIL_VERIFY_STARTED = 'USER_EMAIL_VERIFY_STARTED';
|
||||
export const USER_EMAIL_VERIFY_SUCCESS = 'USER_EMAIL_VERIFY_SUCCESS';
|
||||
export const USER_EMAIL_VERIFY_FAILURE = 'USER_EMAIL_VERIFY_FAILURE';
|
||||
export const USER_IDENTITY_VERIFY_STARTED = 'USER_IDENTITY_VERIFY_STARTED';
|
||||
export const USER_IDENTITY_VERIFY_SUCCESS = 'USER_IDENTITY_VERIFY_SUCCESS';
|
||||
export const USER_IDENTITY_VERIFY_FAILURE = 'USER_IDENTITY_VERIFY_FAILURE';
|
||||
export const USER_FETCH_STARTED = 'USER_FETCH_STARTED';
|
||||
export const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS';
|
||||
export const USER_FETCH_FAILURE = 'USER_FETCH_FAILURE';
|
||||
export const USER_INVITE_STATUS_FETCH_STARTED = 'USER_INVITE_STATUS_FETCH_STARTED';
|
||||
export const USER_INVITE_STATUS_FETCH_SUCCESS = 'USER_INVITE_STATUS_FETCH_SUCCESS';
|
||||
export const USER_INVITE_STATUS_FETCH_FAILURE = 'USER_INVITE_STATUS_FETCH_FAILURE';
|
||||
export const USER_INVITE_NEW_STARTED = 'USER_INVITE_NEW_STARTED';
|
||||
export const USER_INVITE_NEW_SUCCESS = 'USER_INVITE_NEW_SUCCESS';
|
||||
export const USER_INVITE_NEW_FAILURE = 'USER_INVITE_NEW_FAILURE';
|
||||
export const FETCH_ACCESS_TOKEN_SUCCESS = 'FETCH_ACCESS_TOKEN_SUCCESS';
|
||||
|
||||
// Rewards
|
||||
export const FETCH_REWARDS_STARTED = "FETCH_REWARDS_STARTED";
|
||||
export const FETCH_REWARDS_COMPLETED = "FETCH_REWARDS_COMPLETED";
|
||||
export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED";
|
||||
export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS";
|
||||
export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE";
|
||||
export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR";
|
||||
export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED";
|
||||
export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED';
|
||||
export const FETCH_REWARDS_COMPLETED = 'FETCH_REWARDS_COMPLETED';
|
||||
export const CLAIM_REWARD_STARTED = 'CLAIM_REWARD_STARTED';
|
||||
export const CLAIM_REWARD_SUCCESS = 'CLAIM_REWARD_SUCCESS';
|
||||
export const CLAIM_REWARD_FAILURE = 'CLAIM_REWARD_FAILURE';
|
||||
export const CLAIM_REWARD_CLEAR_ERROR = 'CLAIM_REWARD_CLEAR_ERROR';
|
||||
export const FETCH_REWARD_CONTENT_COMPLETED = 'FETCH_REWARD_CONTENT_COMPLETED';
|
||||
|
||||
// Language
|
||||
export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED";
|
||||
export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED";
|
||||
export const DOWNLOAD_LANGUAGE_SUCCEEDED = 'DOWNLOAD_LANGUAGE_SUCCEEDED';
|
||||
export const DOWNLOAD_LANGUAGE_FAILED = 'DOWNLOAD_LANGUAGE_FAILED';
|
||||
|
||||
// ShapeShift
|
||||
export const GET_SUPPORTED_COINS_START = "GET_SUPPORTED_COINS_START";
|
||||
export const GET_SUPPORTED_COINS_SUCCESS = "GET_SUPPORTED_COINS_SUCCESS";
|
||||
export const GET_SUPPORTED_COINS_FAIL = "GET_SUPPORTED_COINS_FAIL";
|
||||
export const GET_COIN_STATS_START = "GET_COIN_STATS_START";
|
||||
export const GET_COIN_STATS_SUCCESS = "GET_COIN_STATS_SUCCESS";
|
||||
export const GET_COIN_STATS_FAIL = "GET_COIN_STATS_FAIL";
|
||||
export const PREPARE_SHAPE_SHIFT_START = "PREPARE_SHAPE_SHIFT_START";
|
||||
export const PREPARE_SHAPE_SHIFT_SUCCESS = "PREPARE_SHAPE_SHIFT_SUCCESS";
|
||||
export const PREPARE_SHAPE_SHIFT_FAIL = "PREPARE_SHAPE_SHIFT_FAIL";
|
||||
export const GET_ACTIVE_SHIFT_START = "GET_ACTIVE_SHIFT_START";
|
||||
export const GET_ACTIVE_SHIFT_SUCCESS = "GET_ACTIVE_SHIFT_SUCCESS";
|
||||
export const GET_ACTIVE_SHIFT_FAIL = "GET_ACTIVE_SHIFT_FAIL";
|
||||
export const CLEAR_SHAPE_SHIFT = "CLEAR_SHAPE_SHIFT";
|
||||
export const GET_SUPPORTED_COINS_START = 'GET_SUPPORTED_COINS_START';
|
||||
export const GET_SUPPORTED_COINS_SUCCESS = 'GET_SUPPORTED_COINS_SUCCESS';
|
||||
export const GET_SUPPORTED_COINS_FAIL = 'GET_SUPPORTED_COINS_FAIL';
|
||||
export const GET_COIN_STATS_START = 'GET_COIN_STATS_START';
|
||||
export const GET_COIN_STATS_SUCCESS = 'GET_COIN_STATS_SUCCESS';
|
||||
export const GET_COIN_STATS_FAIL = 'GET_COIN_STATS_FAIL';
|
||||
export const PREPARE_SHAPE_SHIFT_START = 'PREPARE_SHAPE_SHIFT_START';
|
||||
export const PREPARE_SHAPE_SHIFT_SUCCESS = 'PREPARE_SHAPE_SHIFT_SUCCESS';
|
||||
export const PREPARE_SHAPE_SHIFT_FAIL = 'PREPARE_SHAPE_SHIFT_FAIL';
|
||||
export const GET_ACTIVE_SHIFT_START = 'GET_ACTIVE_SHIFT_START';
|
||||
export const GET_ACTIVE_SHIFT_SUCCESS = 'GET_ACTIVE_SHIFT_SUCCESS';
|
||||
export const GET_ACTIVE_SHIFT_FAIL = 'GET_ACTIVE_SHIFT_FAIL';
|
||||
export const CLEAR_SHAPE_SHIFT = 'CLEAR_SHAPE_SHIFT';
|
||||
|
||||
// Subscriptions
|
||||
export const CHANNEL_SUBSCRIBE = "CHANNEL_SUBSCRIBE";
|
||||
export const CHANNEL_UNSUBSCRIBE = "CHANNEL_UNSUBSCRIBE";
|
||||
export const HAS_FETCHED_SUBSCRIPTIONS = "HAS_FETCHED_SUBSCRIPTIONS";
|
||||
export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE';
|
||||
export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE';
|
||||
export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export const FEATURED = "rocket";
|
||||
export const LOCAL = "folder";
|
||||
export const FILE = "file";
|
||||
export const HISTORY = "history";
|
||||
export const HELP_CIRCLE = "question-circle";
|
||||
export const FEATURED = 'rocket';
|
||||
export const LOCAL = 'folder';
|
||||
export const FILE = 'file';
|
||||
export const HISTORY = 'history';
|
||||
export const HELP_CIRCLE = 'question-circle';
|
||||
|
|
|
@ -1,187 +1,187 @@
|
|||
const LANGUAGES = {
|
||||
aa: ["Afar", "Afar"],
|
||||
ab: ["Abkhazian", "Аҧсуа"],
|
||||
af: ["Afrikaans", "Afrikaans"],
|
||||
ak: ["Akan", "Akana"],
|
||||
am: ["Amharic", "አማርኛ"],
|
||||
an: ["Aragonese", "Aragonés"],
|
||||
ar: ["Arabic", "العربية"],
|
||||
as: ["Assamese", "অসমীয়া"],
|
||||
av: ["Avar", "Авар"],
|
||||
ay: ["Aymara", "Aymar"],
|
||||
az: ["Azerbaijani", "Azərbaycanca / آذربايجان"],
|
||||
ba: ["Bashkir", "Башҡорт"],
|
||||
be: ["Belarusian", "Беларуская"],
|
||||
bg: ["Bulgarian", "Български"],
|
||||
bh: ["Bihari", "भोजपुरी"],
|
||||
bi: ["Bislama", "Bislama"],
|
||||
bm: ["Bambara", "Bamanankan"],
|
||||
bn: ["Bengali", "বাংলা"],
|
||||
bo: ["Tibetan", "བོད་ཡིག / Bod skad"],
|
||||
br: ["Breton", "Brezhoneg"],
|
||||
bs: ["Bosnian", "Bosanski"],
|
||||
ca: ["Catalan", "Català"],
|
||||
ce: ["Chechen", "Нохчийн"],
|
||||
ch: ["Chamorro", "Chamoru"],
|
||||
co: ["Corsican", "Corsu"],
|
||||
cr: ["Cree", "Nehiyaw"],
|
||||
cs: ["Czech", "Česky"],
|
||||
cu: ["Old Church Slavonic / Old Bulgarian", "словѣньскъ / slověnĭskŭ"],
|
||||
cv: ["Chuvash", "Чăваш"],
|
||||
cy: ["Welsh", "Cymraeg"],
|
||||
da: ["Danish", "Dansk"],
|
||||
de: ["German", "Deutsch"],
|
||||
dv: ["Divehi", "ދިވެހިބަސް"],
|
||||
dz: ["Dzongkha", "ཇོང་ཁ"],
|
||||
ee: ["Ewe", "Ɛʋɛ"],
|
||||
el: ["Greek", "Ελληνικά"],
|
||||
en: ["English", "English"],
|
||||
eo: ["Esperanto", "Esperanto"],
|
||||
es: ["Spanish", "Español"],
|
||||
et: ["Estonian", "Eesti"],
|
||||
eu: ["Basque", "Euskara"],
|
||||
fa: ["Persian", "فارسی"],
|
||||
ff: ["Peul", "Fulfulde"],
|
||||
fi: ["Finnish", "Suomi"],
|
||||
fj: ["Fijian", "Na Vosa Vakaviti"],
|
||||
fo: ["Faroese", "Føroyskt"],
|
||||
fr: ["French", "Français"],
|
||||
fy: ["West Frisian", "Frysk"],
|
||||
ga: ["Irish", "Gaeilge"],
|
||||
gd: ["Scottish Gaelic", "Gàidhlig"],
|
||||
gl: ["Galician", "Galego"],
|
||||
gn: ["Guarani", "Avañe'ẽ"],
|
||||
gu: ["Gujarati", "ગુજરાતી"],
|
||||
gv: ["Manx", "Gaelg"],
|
||||
ha: ["Hausa", "هَوُسَ"],
|
||||
he: ["Hebrew", "עברית"],
|
||||
hi: ["Hindi", "हिन्दी"],
|
||||
ho: ["Hiri Motu", "Hiri Motu"],
|
||||
hr: ["Croatian", "Hrvatski"],
|
||||
ht: ["Haitian", "Krèyol ayisyen"],
|
||||
hu: ["Hungarian", "Magyar"],
|
||||
hy: ["Armenian", "Հայերեն"],
|
||||
hz: ["Herero", "Otsiherero"],
|
||||
ia: ["Interlingua", "Interlingua"],
|
||||
id: ["Indonesian", "Bahasa Indonesia"],
|
||||
ie: ["Interlingue", "Interlingue"],
|
||||
ig: ["Igbo", "Igbo"],
|
||||
ii: ["Sichuan Yi", "ꆇꉙ / 四川彝语"],
|
||||
ik: ["Inupiak", "Iñupiak"],
|
||||
io: ["Ido", "Ido"],
|
||||
is: ["Icelandic", "Íslenska"],
|
||||
it: ["Italian", "Italiano"],
|
||||
iu: ["Inuktitut", "ᐃᓄᒃᑎᑐᑦ"],
|
||||
ja: ["Japanese", "日本語"],
|
||||
jv: ["Javanese", "Basa Jawa"],
|
||||
ka: ["Georgian", "ქართული"],
|
||||
kg: ["Kongo", "KiKongo"],
|
||||
ki: ["Kikuyu", "Gĩkũyũ"],
|
||||
kj: ["Kuanyama", "Kuanyama"],
|
||||
kk: ["Kazakh", "Қазақша"],
|
||||
kl: ["Greenlandic", "Kalaallisut"],
|
||||
km: ["Cambodian", "ភាសាខ្មែរ"],
|
||||
kn: ["Kannada", "ಕನ್ನಡ"],
|
||||
ko: ["Korean", "한국어"],
|
||||
kr: ["Kanuri", "Kanuri"],
|
||||
ks: ["Kashmiri", "कश्मीरी / كشميري"],
|
||||
ku: ["Kurdish", "Kurdî / كوردی"],
|
||||
kv: ["Komi", "Коми"],
|
||||
kw: ["Cornish", "Kernewek"],
|
||||
ky: ["Kirghiz", "Kırgızca / Кыргызча"],
|
||||
la: ["Latin", "Latina"],
|
||||
lb: ["Luxembourgish", "Lëtzebuergesch"],
|
||||
lg: ["Ganda", "Luganda"],
|
||||
li: ["Limburgian", "Limburgs"],
|
||||
ln: ["Lingala", "Lingála"],
|
||||
lo: ["Laotian", "ລາວ / Pha xa lao"],
|
||||
lt: ["Lithuanian", "Lietuvių"],
|
||||
lv: ["Latvian", "Latviešu"],
|
||||
mg: ["Malagasy", "Malagasy"],
|
||||
mh: ["Marshallese", "Kajin Majel / Ebon"],
|
||||
mi: ["Maori", "Māori"],
|
||||
mk: ["Macedonian", "Македонски"],
|
||||
ml: ["Malayalam", "മലയാളം"],
|
||||
mn: ["Mongolian", "Монгол"],
|
||||
mo: ["Moldovan", "Moldovenească"],
|
||||
mr: ["Marathi", "मराठी"],
|
||||
ms: ["Malay", "Bahasa Melayu"],
|
||||
mt: ["Maltese", "bil-Malti"],
|
||||
my: ["Burmese", "Myanmasa"],
|
||||
na: ["Nauruan", "Dorerin Naoero"],
|
||||
nd: ["North Ndebele", "Sindebele"],
|
||||
ne: ["Nepali", "नेपाली"],
|
||||
ng: ["Ndonga", "Oshiwambo"],
|
||||
nl: ["Dutch", "Nederlands"],
|
||||
nn: ["Norwegian Nynorsk", "Norsk (nynorsk)"],
|
||||
no: ["Norwegian", "Norsk (bokmål / riksmål)"],
|
||||
nr: ["South Ndebele", "isiNdebele"],
|
||||
nv: ["Navajo", "Diné bizaad"],
|
||||
ny: ["Chichewa", "Chi-Chewa"],
|
||||
oc: ["Occitan", "Occitan"],
|
||||
oj: ["Ojibwa", "ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin"],
|
||||
om: ["Oromo", "Oromoo"],
|
||||
or: ["Oriya", "ଓଡ଼ିଆ"],
|
||||
os: ["Ossetian / Ossetic", "Иронау"],
|
||||
pa: ["Panjabi / Punjabi", "ਪੰਜਾਬੀ / पंजाबी / پنجابي"],
|
||||
pi: ["Pali", "Pāli / पाऴि"],
|
||||
pl: ["Polish", "Polski"],
|
||||
ps: ["Pashto", "پښتو"],
|
||||
pt: ["Portuguese", "Português"],
|
||||
qu: ["Quechua", "Runa Simi"],
|
||||
rm: ["Raeto Romance", "Rumantsch"],
|
||||
rn: ["Kirundi", "Kirundi"],
|
||||
ro: ["Romanian", "Română"],
|
||||
ru: ["Russian", "Русский"],
|
||||
rw: ["Rwandi", "Kinyarwandi"],
|
||||
sa: ["Sanskrit", "संस्कृतम्"],
|
||||
sc: ["Sardinian", "Sardu"],
|
||||
sd: ["Sindhi", "सिनधि"],
|
||||
se: ["Northern Sami", "Sámegiella"],
|
||||
sg: ["Sango", "Sängö"],
|
||||
sh: ["Serbo-Croatian", "Srpskohrvatski / Српскохрватски"],
|
||||
si: ["Sinhalese", "සිංහල"],
|
||||
sk: ["Slovak", "Slovenčina"],
|
||||
sl: ["Slovenian", "Slovenščina"],
|
||||
sm: ["Samoan", "Gagana Samoa"],
|
||||
sn: ["Shona", "chiShona"],
|
||||
so: ["Somalia", "Soomaaliga"],
|
||||
sq: ["Albanian", "Shqip"],
|
||||
sr: ["Serbian", "Српски"],
|
||||
ss: ["Swati", "SiSwati"],
|
||||
st: ["Southern Sotho", "Sesotho"],
|
||||
su: ["Sundanese", "Basa Sunda"],
|
||||
sv: ["Swedish", "Svenska"],
|
||||
sw: ["Swahili", "Kiswahili"],
|
||||
ta: ["Tamil", "தமிழ்"],
|
||||
te: ["Telugu", "తెలుగు"],
|
||||
tg: ["Tajik", "Тоҷикӣ"],
|
||||
th: ["Thai", "ไทย / Phasa Thai"],
|
||||
ti: ["Tigrinya", "ትግርኛ"],
|
||||
tk: ["Turkmen", "Туркмен / تركمن"],
|
||||
tl: ["Tagalog / Filipino", "Tagalog"],
|
||||
tn: ["Tswana", "Setswana"],
|
||||
to: ["Tonga", "Lea Faka-Tonga"],
|
||||
tr: ["Turkish", "Türkçe"],
|
||||
ts: ["Tsonga", "Xitsonga"],
|
||||
tt: ["Tatar", "Tatarça"],
|
||||
tw: ["Twi", "Twi"],
|
||||
ty: ["Tahitian", "Reo Mā`ohi"],
|
||||
ug: ["Uyghur", "Uyƣurqə / ئۇيغۇرچە"],
|
||||
uk: ["Ukrainian", "Українська"],
|
||||
ur: ["Urdu", "اردو"],
|
||||
uz: ["Uzbek", "Ўзбек"],
|
||||
ve: ["Venda", "Tshivenḓa"],
|
||||
vi: ["Vietnamese", "Tiếng Việt"],
|
||||
vo: ["Volapük", "Volapük"],
|
||||
wa: ["Walloon", "Walon"],
|
||||
wo: ["Wolof", "Wollof"],
|
||||
xh: ["Xhosa", "isiXhosa"],
|
||||
yi: ["Yiddish", "ייִדיש"],
|
||||
yo: ["Yoruba", "Yorùbá"],
|
||||
za: ["Zhuang", "Cuengh / Tôô / 壮语"],
|
||||
zh: ["Chinese", "中文"],
|
||||
zu: ["Zulu", "isiZulu"],
|
||||
aa: ['Afar', 'Afar'],
|
||||
ab: ['Abkhazian', 'Аҧсуа'],
|
||||
af: ['Afrikaans', 'Afrikaans'],
|
||||
ak: ['Akan', 'Akana'],
|
||||
am: ['Amharic', 'አማርኛ'],
|
||||
an: ['Aragonese', 'Aragonés'],
|
||||
ar: ['Arabic', 'العربية'],
|
||||
as: ['Assamese', 'অসমীয়া'],
|
||||
av: ['Avar', 'Авар'],
|
||||
ay: ['Aymara', 'Aymar'],
|
||||
az: ['Azerbaijani', 'Azərbaycanca / آذربايجان'],
|
||||
ba: ['Bashkir', 'Башҡорт'],
|
||||
be: ['Belarusian', 'Беларуская'],
|
||||
bg: ['Bulgarian', 'Български'],
|
||||
bh: ['Bihari', 'भोजपुरी'],
|
||||
bi: ['Bislama', 'Bislama'],
|
||||
bm: ['Bambara', 'Bamanankan'],
|
||||
bn: ['Bengali', 'বাংলা'],
|
||||
bo: ['Tibetan', 'བོད་ཡིག / Bod skad'],
|
||||
br: ['Breton', 'Brezhoneg'],
|
||||
bs: ['Bosnian', 'Bosanski'],
|
||||
ca: ['Catalan', 'Català'],
|
||||
ce: ['Chechen', 'Нохчийн'],
|
||||
ch: ['Chamorro', 'Chamoru'],
|
||||
co: ['Corsican', 'Corsu'],
|
||||
cr: ['Cree', 'Nehiyaw'],
|
||||
cs: ['Czech', 'Česky'],
|
||||
cu: ['Old Church Slavonic / Old Bulgarian', 'словѣньскъ / slověnĭskŭ'],
|
||||
cv: ['Chuvash', 'Чăваш'],
|
||||
cy: ['Welsh', 'Cymraeg'],
|
||||
da: ['Danish', 'Dansk'],
|
||||
de: ['German', 'Deutsch'],
|
||||
dv: ['Divehi', 'ދިވެހިބަސް'],
|
||||
dz: ['Dzongkha', 'ཇོང་ཁ'],
|
||||
ee: ['Ewe', 'Ɛʋɛ'],
|
||||
el: ['Greek', 'Ελληνικά'],
|
||||
en: ['English', 'English'],
|
||||
eo: ['Esperanto', 'Esperanto'],
|
||||
es: ['Spanish', 'Español'],
|
||||
et: ['Estonian', 'Eesti'],
|
||||
eu: ['Basque', 'Euskara'],
|
||||
fa: ['Persian', 'فارسی'],
|
||||
ff: ['Peul', 'Fulfulde'],
|
||||
fi: ['Finnish', 'Suomi'],
|
||||
fj: ['Fijian', 'Na Vosa Vakaviti'],
|
||||
fo: ['Faroese', 'Føroyskt'],
|
||||
fr: ['French', 'Français'],
|
||||
fy: ['West Frisian', 'Frysk'],
|
||||
ga: ['Irish', 'Gaeilge'],
|
||||
gd: ['Scottish Gaelic', 'Gàidhlig'],
|
||||
gl: ['Galician', 'Galego'],
|
||||
gn: ['Guarani', "Avañe'ẽ"],
|
||||
gu: ['Gujarati', 'ગુજરાતી'],
|
||||
gv: ['Manx', 'Gaelg'],
|
||||
ha: ['Hausa', 'هَوُسَ'],
|
||||
he: ['Hebrew', 'עברית'],
|
||||
hi: ['Hindi', 'हिन्दी'],
|
||||
ho: ['Hiri Motu', 'Hiri Motu'],
|
||||
hr: ['Croatian', 'Hrvatski'],
|
||||
ht: ['Haitian', 'Krèyol ayisyen'],
|
||||
hu: ['Hungarian', 'Magyar'],
|
||||
hy: ['Armenian', 'Հայերեն'],
|
||||
hz: ['Herero', 'Otsiherero'],
|
||||
ia: ['Interlingua', 'Interlingua'],
|
||||
id: ['Indonesian', 'Bahasa Indonesia'],
|
||||
ie: ['Interlingue', 'Interlingue'],
|
||||
ig: ['Igbo', 'Igbo'],
|
||||
ii: ['Sichuan Yi', 'ꆇꉙ / 四川彝语'],
|
||||
ik: ['Inupiak', 'Iñupiak'],
|
||||
io: ['Ido', 'Ido'],
|
||||
is: ['Icelandic', 'Íslenska'],
|
||||
it: ['Italian', 'Italiano'],
|
||||
iu: ['Inuktitut', 'ᐃᓄᒃᑎᑐᑦ'],
|
||||
ja: ['Japanese', '日本語'],
|
||||
jv: ['Javanese', 'Basa Jawa'],
|
||||
ka: ['Georgian', 'ქართული'],
|
||||
kg: ['Kongo', 'KiKongo'],
|
||||
ki: ['Kikuyu', 'Gĩkũyũ'],
|
||||
kj: ['Kuanyama', 'Kuanyama'],
|
||||
kk: ['Kazakh', 'Қазақша'],
|
||||
kl: ['Greenlandic', 'Kalaallisut'],
|
||||
km: ['Cambodian', 'ភាសាខ្មែរ'],
|
||||
kn: ['Kannada', 'ಕನ್ನಡ'],
|
||||
ko: ['Korean', '한국어'],
|
||||
kr: ['Kanuri', 'Kanuri'],
|
||||
ks: ['Kashmiri', 'कश्मीरी / كشميري'],
|
||||
ku: ['Kurdish', 'Kurdî / كوردی'],
|
||||
kv: ['Komi', 'Коми'],
|
||||
kw: ['Cornish', 'Kernewek'],
|
||||
ky: ['Kirghiz', 'Kırgızca / Кыргызча'],
|
||||
la: ['Latin', 'Latina'],
|
||||
lb: ['Luxembourgish', 'Lëtzebuergesch'],
|
||||
lg: ['Ganda', 'Luganda'],
|
||||
li: ['Limburgian', 'Limburgs'],
|
||||
ln: ['Lingala', 'Lingála'],
|
||||
lo: ['Laotian', 'ລາວ / Pha xa lao'],
|
||||
lt: ['Lithuanian', 'Lietuvių'],
|
||||
lv: ['Latvian', 'Latviešu'],
|
||||
mg: ['Malagasy', 'Malagasy'],
|
||||
mh: ['Marshallese', 'Kajin Majel / Ebon'],
|
||||
mi: ['Maori', 'Māori'],
|
||||
mk: ['Macedonian', 'Македонски'],
|
||||
ml: ['Malayalam', 'മലയാളം'],
|
||||
mn: ['Mongolian', 'Монгол'],
|
||||
mo: ['Moldovan', 'Moldovenească'],
|
||||
mr: ['Marathi', 'मराठी'],
|
||||
ms: ['Malay', 'Bahasa Melayu'],
|
||||
mt: ['Maltese', 'bil-Malti'],
|
||||
my: ['Burmese', 'Myanmasa'],
|
||||
na: ['Nauruan', 'Dorerin Naoero'],
|
||||
nd: ['North Ndebele', 'Sindebele'],
|
||||
ne: ['Nepali', 'नेपाली'],
|
||||
ng: ['Ndonga', 'Oshiwambo'],
|
||||
nl: ['Dutch', 'Nederlands'],
|
||||
nn: ['Norwegian Nynorsk', 'Norsk (nynorsk)'],
|
||||
no: ['Norwegian', 'Norsk (bokmål / riksmål)'],
|
||||
nr: ['South Ndebele', 'isiNdebele'],
|
||||
nv: ['Navajo', 'Diné bizaad'],
|
||||
ny: ['Chichewa', 'Chi-Chewa'],
|
||||
oc: ['Occitan', 'Occitan'],
|
||||
oj: ['Ojibwa', 'ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin'],
|
||||
om: ['Oromo', 'Oromoo'],
|
||||
or: ['Oriya', 'ଓଡ଼ିଆ'],
|
||||
os: ['Ossetian / Ossetic', 'Иронау'],
|
||||
pa: ['Panjabi / Punjabi', 'ਪੰਜਾਬੀ / पंजाबी / پنجابي'],
|
||||
pi: ['Pali', 'Pāli / पाऴि'],
|
||||
pl: ['Polish', 'Polski'],
|
||||
ps: ['Pashto', 'پښتو'],
|
||||
pt: ['Portuguese', 'Português'],
|
||||
qu: ['Quechua', 'Runa Simi'],
|
||||
rm: ['Raeto Romance', 'Rumantsch'],
|
||||
rn: ['Kirundi', 'Kirundi'],
|
||||
ro: ['Romanian', 'Română'],
|
||||
ru: ['Russian', 'Русский'],
|
||||
rw: ['Rwandi', 'Kinyarwandi'],
|
||||
sa: ['Sanskrit', 'संस्कृतम्'],
|
||||
sc: ['Sardinian', 'Sardu'],
|
||||
sd: ['Sindhi', 'सिनधि'],
|
||||
se: ['Northern Sami', 'Sámegiella'],
|
||||
sg: ['Sango', 'Sängö'],
|
||||
sh: ['Serbo-Croatian', 'Srpskohrvatski / Српскохрватски'],
|
||||
si: ['Sinhalese', 'සිංහල'],
|
||||
sk: ['Slovak', 'Slovenčina'],
|
||||
sl: ['Slovenian', 'Slovenščina'],
|
||||
sm: ['Samoan', 'Gagana Samoa'],
|
||||
sn: ['Shona', 'chiShona'],
|
||||
so: ['Somalia', 'Soomaaliga'],
|
||||
sq: ['Albanian', 'Shqip'],
|
||||
sr: ['Serbian', 'Српски'],
|
||||
ss: ['Swati', 'SiSwati'],
|
||||
st: ['Southern Sotho', 'Sesotho'],
|
||||
su: ['Sundanese', 'Basa Sunda'],
|
||||
sv: ['Swedish', 'Svenska'],
|
||||
sw: ['Swahili', 'Kiswahili'],
|
||||
ta: ['Tamil', 'தமிழ்'],
|
||||
te: ['Telugu', 'తెలుగు'],
|
||||
tg: ['Tajik', 'Тоҷикӣ'],
|
||||
th: ['Thai', 'ไทย / Phasa Thai'],
|
||||
ti: ['Tigrinya', 'ትግርኛ'],
|
||||
tk: ['Turkmen', 'Туркмен / تركمن'],
|
||||
tl: ['Tagalog / Filipino', 'Tagalog'],
|
||||
tn: ['Tswana', 'Setswana'],
|
||||
to: ['Tonga', 'Lea Faka-Tonga'],
|
||||
tr: ['Turkish', 'Türkçe'],
|
||||
ts: ['Tsonga', 'Xitsonga'],
|
||||
tt: ['Tatar', 'Tatarça'],
|
||||
tw: ['Twi', 'Twi'],
|
||||
ty: ['Tahitian', 'Reo Mā`ohi'],
|
||||
ug: ['Uyghur', 'Uyƣurqə / ئۇيغۇرچە'],
|
||||
uk: ['Ukrainian', 'Українська'],
|
||||
ur: ['Urdu', 'اردو'],
|
||||
uz: ['Uzbek', 'Ўзбек'],
|
||||
ve: ['Venda', 'Tshivenḓa'],
|
||||
vi: ['Vietnamese', 'Tiếng Việt'],
|
||||
vo: ['Volapük', 'Volapük'],
|
||||
wa: ['Walloon', 'Walon'],
|
||||
wo: ['Wolof', 'Wollof'],
|
||||
xh: ['Xhosa', 'isiXhosa'],
|
||||
yi: ['Yiddish', 'ייִדיש'],
|
||||
yo: ['Yoruba', 'Yorùbá'],
|
||||
za: ['Zhuang', 'Cuengh / Tôô / 壮语'],
|
||||
zh: ['Chinese', '中文'],
|
||||
zu: ['Zulu', 'isiZulu'],
|
||||
};
|
||||
|
||||
export default LANGUAGES;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
export const CONFIRM_FILE_REMOVE = "confirmFileRemove";
|
||||
export const INCOMPATIBLE_DAEMON = "incompatibleDaemon";
|
||||
export const FILE_TIMEOUT = "file_timeout";
|
||||
export const DOWNLOADING = "downloading";
|
||||
export const ERROR = "error";
|
||||
export const INSUFFICIENT_CREDITS = "insufficient_credits";
|
||||
export const UPGRADE = "upgrade";
|
||||
export const WELCOME = "welcome";
|
||||
export const EMAIL_COLLECTION = "email_collection";
|
||||
export const FIRST_REWARD = "first_reward";
|
||||
export const AUTHENTICATION_FAILURE = "auth_failure";
|
||||
export const TRANSACTION_FAILED = "transaction_failed";
|
||||
export const REWARD_APPROVAL_REQUIRED = "reward_approval_required";
|
||||
export const AFFIRM_PURCHASE = "affirm_purchase";
|
||||
export const CONFIRM_CLAIM_REVOKE = "confirmClaimRevoke";
|
||||
export const CONFIRM_FILE_REMOVE = 'confirmFileRemove';
|
||||
export const INCOMPATIBLE_DAEMON = 'incompatibleDaemon';
|
||||
export const FILE_TIMEOUT = 'file_timeout';
|
||||
export const DOWNLOADING = 'downloading';
|
||||
export const ERROR = 'error';
|
||||
export const INSUFFICIENT_CREDITS = 'insufficient_credits';
|
||||
export const UPGRADE = 'upgrade';
|
||||
export const WELCOME = 'welcome';
|
||||
export const EMAIL_COLLECTION = 'email_collection';
|
||||
export const FIRST_REWARD = 'first_reward';
|
||||
export const AUTHENTICATION_FAILURE = 'auth_failure';
|
||||
export const TRANSACTION_FAILED = 'transaction_failed';
|
||||
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
|
||||
export const AFFIRM_PURCHASE = 'affirm_purchase';
|
||||
export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke';
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/* hardcoded names still exist for these in reducers/settings.js - only discovered when debugging */
|
||||
/* Many settings are stored in the localStorage by their name -
|
||||
be careful about changing the value of a settings constant, as doing so can invalidate existing settings */
|
||||
export const CREDIT_REQUIRED_ACKNOWLEDGED = "credit_required_acknowledged";
|
||||
export const NEW_USER_ACKNOWLEDGED = "welcome_acknowledged";
|
||||
export const EMAIL_COLLECTION_ACKNOWLEDGED = "email_collection_acknowledged";
|
||||
export const LANGUAGE = "language";
|
||||
export const SHOW_NSFW = "showNsfw";
|
||||
export const SHOW_UNAVAILABLE = "showUnavailable";
|
||||
export const INSTANT_PURCHASE_ENABLED = "instantPurchaseEnabled";
|
||||
export const INSTANT_PURCHASE_MAX = "instantPurchaseMax";
|
||||
export const THEME = "theme";
|
||||
export const THEMES = "themes";
|
||||
/* Many SETTINGS are stored in the localStorage by their name -
|
||||
be careful about changing the value of a SETTINGS constant, as doing so can invalidate existing SETTINGS */
|
||||
export const CREDIT_REQUIRED_ACKNOWLEDGED = 'credit_required_acknowledged';
|
||||
export const NEW_USER_ACKNOWLEDGED = 'welcome_acknowledged';
|
||||
export const EMAIL_COLLECTION_ACKNOWLEDGED = 'email_collection_acknowledged';
|
||||
export const LANGUAGE = 'language';
|
||||
export const SHOW_NSFW = 'showNsfw';
|
||||
export const SHOW_UNAVAILABLE = 'showUnavailable';
|
||||
export const INSTANT_PURCHASE_ENABLED = 'instantPurchaseEnabled';
|
||||
export const INSTANT_PURCHASE_MAX = 'instantPurchaseMax';
|
||||
export const THEME = 'theme';
|
||||
export const THEMES = 'themes';
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export const NO_DEPOSITS = "no_deposits";
|
||||
export const RECEIVED = "received";
|
||||
export const COMPLETE = "complete";
|
||||
export const NO_DEPOSITS = 'no_deposits';
|
||||
export const RECEIVED = 'received';
|
||||
export const COMPLETE = 'complete';
|
||||
|
|
|
@ -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.exports: any;
|
||||
}
|
||||
|
|
|
@ -1,87 +1,71 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "component/app/index.js";
|
||||
import SnackBar from "component/snackBar";
|
||||
import { Provider } from "react-redux";
|
||||
import store from "store.js";
|
||||
import SplashScreen from "component/splash";
|
||||
import { doDaemonReady } from "redux/actions/app";
|
||||
import { doNavigate } from "redux/actions/navigation";
|
||||
import { doDownloadLanguages } from "redux/actions/settings";
|
||||
import * as types from "constants/action_types";
|
||||
import amplitude from "amplitude-js";
|
||||
import lbry from "lbry";
|
||||
import "scss/all.scss";
|
||||
/* eslint-disable react/jsx-filename-extension */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from 'component/app';
|
||||
import SnackBar from 'component/snackBar';
|
||||
import { Provider } from 'react-redux';
|
||||
import store from 'store';
|
||||
import SplashScreen from 'component/splash';
|
||||
import { doDaemonReady } from 'redux/actions/app';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { doDownloadLanguages } from 'redux/actions/settings';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import amplitude from 'amplitude-js';
|
||||
import lbry from 'lbry';
|
||||
import 'scss/all.scss';
|
||||
import { ipcRenderer, remote, shell } from 'electron';
|
||||
|
||||
const env = process.env.NODE_ENV || "production";
|
||||
const { remote, ipcRenderer, shell } = require("electron");
|
||||
const { contextMenu } = remote.require('./main.js');
|
||||
|
||||
const contextMenu = remote.require("./main.js").contextMenu;
|
||||
const app = require("./app");
|
||||
|
||||
// Workaround for https://github.com/electron-userland/electron-webpack/issues/52
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
window.staticResourcesPath = require("path")
|
||||
.join(remote.app.getAppPath(), "../static")
|
||||
.replace(/\\/g, "\\\\");
|
||||
} else {
|
||||
window.staticResourcesPath = "";
|
||||
}
|
||||
|
||||
window.addEventListener("contextmenu", event => {
|
||||
window.addEventListener('contextmenu', event => {
|
||||
contextMenu.showContextMenu(
|
||||
remote.getCurrentWindow(),
|
||||
event.x,
|
||||
event.y,
|
||||
env === "development"
|
||||
app.env === 'development'
|
||||
);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
ipcRenderer.on("open-uri-requested", (event, uri) => {
|
||||
if (uri && uri.startsWith("lbry://")) {
|
||||
app.store.dispatch(doNavigate("/show", { uri }));
|
||||
ipcRenderer.on('open-uri-requested', (event, uri) => {
|
||||
if (uri && uri.startsWith('lbry://')) {
|
||||
app.store.dispatch(doNavigate('/show', { uri }));
|
||||
}
|
||||
});
|
||||
|
||||
ipcRenderer.on("open-menu", (event, uri) => {
|
||||
if (uri && uri.startsWith("/help")) {
|
||||
app.store.dispatch(doNavigate("/help"));
|
||||
ipcRenderer.on('open-menu', (event, uri) => {
|
||||
if (uri && uri.startsWith('/help')) {
|
||||
app.store.dispatch(doNavigate('/help'));
|
||||
}
|
||||
});
|
||||
|
||||
const dock = remote.app.dock;
|
||||
const { dock } = remote.app;
|
||||
|
||||
ipcRenderer.on("window-is-focused", (event, data) => {
|
||||
ipcRenderer.on('window-is-focused', () => {
|
||||
if (!dock) return;
|
||||
app.store.dispatch({ type: types.WINDOW_FOCUSED });
|
||||
dock.setBadge("");
|
||||
app.store.dispatch({ type: ACTIONS.WINDOW_FOCUSED });
|
||||
dock.setBadge('');
|
||||
});
|
||||
|
||||
document.addEventListener("click", event => {
|
||||
let target = event.target;
|
||||
document.addEventListener('click', event => {
|
||||
let { target } = event;
|
||||
while (target && target !== document) {
|
||||
if (target.matches("a") || target.matches("button")) {
|
||||
if (target.matches('a') || target.matches('button')) {
|
||||
// TODO: Look into using accessiblity labels (this would also make the app more accessible)
|
||||
const hrefParts = window.location.href.split("#");
|
||||
const hrefParts = window.location.href.split('#');
|
||||
const element = target.title || (target.text && target.text.trim());
|
||||
if (element) {
|
||||
amplitude.getInstance().logEvent("CLICK", {
|
||||
amplitude.getInstance().logEvent('CLICK', {
|
||||
target: element,
|
||||
location:
|
||||
hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : "/",
|
||||
location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/',
|
||||
});
|
||||
} else {
|
||||
amplitude.getInstance().logEvent("UNMARKED_CLICK", {
|
||||
location:
|
||||
hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : "/",
|
||||
amplitude.getInstance().logEvent('UNMARKED_CLICK', {
|
||||
location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/',
|
||||
});
|
||||
}
|
||||
}
|
||||
if (
|
||||
target.matches('a[href^="http"]') ||
|
||||
target.matches('a[href^="mailto"]')
|
||||
) {
|
||||
if (target.matches('a[href^="http"]') || target.matches('a[href^="mailto"]')) {
|
||||
event.preventDefault();
|
||||
shell.openExternal(target.href);
|
||||
return;
|
||||
|
@ -90,20 +74,18 @@ document.addEventListener("click", event => {
|
|||
}
|
||||
});
|
||||
|
||||
const initialState = app.store.getState();
|
||||
|
||||
const init = function() {
|
||||
const init = function initializeReactApp() {
|
||||
app.store.dispatch(doDownloadLanguages());
|
||||
|
||||
function onDaemonReady() {
|
||||
lbry.status().then(info => {
|
||||
amplitude.getInstance().init(
|
||||
// Amplitude API Key
|
||||
"0b130efdcbdbf86ec2f7f9eff354033e",
|
||||
'0b130efdcbdbf86ec2f7f9eff354033e',
|
||||
info.lbry_id,
|
||||
null,
|
||||
() => {
|
||||
window.sessionStorage.setItem("loaded", "y"); // once we've made it here once per session, we don't need to show splash again
|
||||
window.sessionStorage.setItem('loaded', 'y'); // once we've made it here once per session, we don't need to show splash again
|
||||
app.store.dispatch(doDaemonReady());
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -113,21 +95,21 @@ const init = function() {
|
|||
<SnackBar />
|
||||
</div>
|
||||
</Provider>,
|
||||
document.getElementById("app")
|
||||
document.getElementById('app')
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (window.sessionStorage.getItem("loaded") == "y") {
|
||||
if (window.sessionStorage.getItem('loaded') === 'y') {
|
||||
onDaemonReady();
|
||||
} else {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<SplashScreen onReadyToLaunch={onDaemonReady} />
|
||||
</Provider>,
|
||||
document.getElementById("app")
|
||||
document.getElementById('app')
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,76 +1,56 @@
|
|||
const jsonrpc = {};
|
||||
|
||||
jsonrpc.call = function(
|
||||
jsonrpc.call = function callJsonRpc(
|
||||
connectionString,
|
||||
method,
|
||||
params,
|
||||
callback,
|
||||
errorCallback,
|
||||
connectFailedCallback,
|
||||
timeout
|
||||
connectFailedCallback
|
||||
) {
|
||||
function checkAndParse(response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response.json();
|
||||
}
|
||||
return response
|
||||
.json()
|
||||
.then(json => {
|
||||
let error;
|
||||
if (json.error) {
|
||||
error = new Error(json.error);
|
||||
} else {
|
||||
error = new Error("Protocol error with unknown response signature");
|
||||
}
|
||||
return Promise.reject(error);
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
|
||||
function makeRequest(url, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(url, options)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
|
||||
if (timeout) {
|
||||
const e = new Error(__("Protocol request timed out"));
|
||||
setTimeout(() => reject(e), timeout);
|
||||
return response.json().then(json => {
|
||||
let error;
|
||||
if (json.error) {
|
||||
error = new Error(json.error);
|
||||
} else {
|
||||
error = new Error('Protocol error with unknown response signature');
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
const counter = parseInt(sessionStorage.getItem("JSONRPCCounter") || 0);
|
||||
const counter = parseInt(sessionStorage.getItem('JSONRPCCounter') || 0, 10);
|
||||
const url = connectionString;
|
||||
const options = {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
jsonrpc: '2.0',
|
||||
method,
|
||||
params,
|
||||
id: counter,
|
||||
}),
|
||||
};
|
||||
|
||||
sessionStorage.setItem("JSONRPCCounter", counter + 1);
|
||||
sessionStorage.setItem('JSONRPCCounter', counter + 1);
|
||||
|
||||
return fetch(url, options)
|
||||
.then(checkAndParse)
|
||||
.then(response => {
|
||||
const error =
|
||||
response.error || (response.result && response.result.error);
|
||||
const error = response.error || (response.result && response.result.error);
|
||||
|
||||
if (!error && typeof callback === "function") {
|
||||
if (!error && typeof callback === 'function') {
|
||||
return callback(response.result);
|
||||
}
|
||||
|
||||
if (error && typeof errorCallback === "function") {
|
||||
if (error && typeof errorCallback === 'function') {
|
||||
return errorCallback(error);
|
||||
}
|
||||
|
||||
const errorEvent = new CustomEvent("unhandledError", {
|
||||
const errorEvent = new CustomEvent('unhandledError', {
|
||||
detail: {
|
||||
connectionString,
|
||||
method,
|
||||
|
@ -81,22 +61,25 @@ jsonrpc.call = function(
|
|||
},
|
||||
});
|
||||
document.dispatchEvent(errorEvent);
|
||||
|
||||
return Promise.resolve();
|
||||
})
|
||||
.catch(e => {
|
||||
.catch(error => {
|
||||
if (connectFailedCallback) {
|
||||
return connectFailedCallback(e);
|
||||
return connectFailedCallback(error);
|
||||
}
|
||||
|
||||
const errorEvent = new CustomEvent("unhandledError", {
|
||||
const errorEvent = new CustomEvent('unhandledError', {
|
||||
detail: {
|
||||
connectionString,
|
||||
method,
|
||||
params,
|
||||
code: e.response && e.response.status,
|
||||
message: __("Connection to API server failed"),
|
||||
code: error.response && error.response.status,
|
||||
message: __('Connection to API server failed'),
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(errorEvent);
|
||||
return Promise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,31 @@
|
|||
import jsonrpc from "./jsonrpc.js";
|
||||
import lbryuri from "./lbryuri.js";
|
||||
import jsonrpc from 'jsonrpc';
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
const CHECK_DAEMON_STARTED_TRY_NUMBER = 200;
|
||||
|
||||
const Lbry = {
|
||||
isConnected: false,
|
||||
daemonConnectionString: 'http://localhost:5279',
|
||||
pendingPublishTimeout: 20 * 60 * 1000,
|
||||
};
|
||||
|
||||
function apiCall(method, params, resolve, reject) {
|
||||
return jsonrpc.call(Lbry.daemonConnectionString, method, params, resolve, reject, reject);
|
||||
}
|
||||
|
||||
const lbryProxy = new Proxy(Lbry, {
|
||||
get(target, name) {
|
||||
if (name in target) {
|
||||
return target[name];
|
||||
}
|
||||
|
||||
return function(params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiCall(name, params, resolve, reject);
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
function getLocal(key, fallback = undefined) {
|
||||
const itemRaw = localStorage.getItem(key);
|
||||
|
@ -10,49 +36,24 @@ function setLocal(key, value) {
|
|||
localStorage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
|
||||
const { remote, ipcRenderer } = require("electron");
|
||||
|
||||
let lbry = {
|
||||
isConnected: false,
|
||||
daemonConnectionString: "http://localhost:5279",
|
||||
pendingPublishTimeout: 20 * 60 * 1000,
|
||||
};
|
||||
|
||||
function apiCall(method, params, resolve, reject) {
|
||||
return jsonrpc.call(
|
||||
lbry.daemonConnectionString,
|
||||
method,
|
||||
params,
|
||||
resolve,
|
||||
reject,
|
||||
reject
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a publish attempt in local storage. Returns a dictionary with all the data needed to
|
||||
* needed to make a dummy claim or file info object.
|
||||
*/
|
||||
let pendingId = 0;
|
||||
function savePendingPublish({ name, channel_name }) {
|
||||
let uri;
|
||||
if (channel_name) {
|
||||
uri = lbryuri.build({ name: channel_name, path: name }, false);
|
||||
} else {
|
||||
uri = lbryuri.build({ name }, false);
|
||||
}
|
||||
++pendingId;
|
||||
const pendingPublishes = getLocal("pendingPublishes") || [];
|
||||
function savePendingPublish({ name, channelName }) {
|
||||
pendingId += 1;
|
||||
const pendingPublishes = getLocal('pendingPublishes') || [];
|
||||
const newPendingPublish = {
|
||||
name,
|
||||
channel_name,
|
||||
channelName,
|
||||
claim_id: `pending-${pendingId}`,
|
||||
txid: `pending-${pendingId}`,
|
||||
nout: 0,
|
||||
outpoint: `pending-${pendingId}:0`,
|
||||
time: Date.now(),
|
||||
};
|
||||
setLocal("pendingPublishes", [...pendingPublishes, newPendingPublish]);
|
||||
setLocal('pendingPublishes', [...pendingPublishes, newPendingPublish]);
|
||||
return newPendingPublish;
|
||||
}
|
||||
|
||||
|
@ -60,31 +61,27 @@ function savePendingPublish({ name, channel_name }) {
|
|||
* If there is a pending publish with the given name or outpoint, remove it.
|
||||
* A channel name may also be provided along with name.
|
||||
*/
|
||||
function removePendingPublishIfNeeded({ name, channel_name, outpoint }) {
|
||||
function removePendingPublishIfNeeded({ name, channelName, outpoint }) {
|
||||
function pubMatches(pub) {
|
||||
return (
|
||||
pub.outpoint === outpoint ||
|
||||
(pub.name === name &&
|
||||
(!channel_name || pub.channel_name === channel_name))
|
||||
(pub.name === name && (!channelName || pub.channel_name === channelName))
|
||||
);
|
||||
}
|
||||
|
||||
setLocal(
|
||||
"pendingPublishes",
|
||||
lbry.getPendingPublishes().filter(pub => !pubMatches(pub))
|
||||
);
|
||||
setLocal('pendingPublishes', Lbry.getPendingPublishes().filter(pub => !pubMatches(pub)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current list of pending publish attempts. Filters out any that have timed out and
|
||||
* removes them from the list.
|
||||
*/
|
||||
lbry.getPendingPublishes = function() {
|
||||
const pendingPublishes = getLocal("pendingPublishes") || [];
|
||||
Lbry.getPendingPublishes = function() {
|
||||
const pendingPublishes = getLocal('pendingPublishes') || [];
|
||||
const newPendingPublishes = pendingPublishes.filter(
|
||||
pub => Date.now() - pub.time <= lbry.pendingPublishTimeout
|
||||
pub => Date.now() - pub.time <= Lbry.pendingPublishTimeout
|
||||
);
|
||||
setLocal("pendingPublishes", newPendingPublishes);
|
||||
setLocal('pendingPublishes', newPendingPublishes);
|
||||
return newPendingPublishes;
|
||||
};
|
||||
|
||||
|
@ -92,65 +89,52 @@ lbry.getPendingPublishes = function() {
|
|||
* Gets a pending publish attempt by its name or (fake) outpoint. A channel name can also be
|
||||
* provided along withe the name. If no pending publish is found, returns null.
|
||||
*/
|
||||
function getPendingPublish({ name, channel_name, outpoint }) {
|
||||
const pendingPublishes = lbry.getPendingPublishes();
|
||||
function getPendingPublish({ name, channelName, outpoint }) {
|
||||
const pendingPublishes = Lbry.getPendingPublishes();
|
||||
return (
|
||||
pendingPublishes.find(
|
||||
pub =>
|
||||
pub.outpoint === outpoint ||
|
||||
(pub.name === name &&
|
||||
(!channel_name || pub.channel_name === channel_name))
|
||||
(pub.name === name && (!channelName || pub.channel_name === channelName))
|
||||
) || null
|
||||
);
|
||||
}
|
||||
|
||||
function pendingPublishToDummyClaim({
|
||||
channel_name,
|
||||
name,
|
||||
outpoint,
|
||||
claim_id,
|
||||
txid,
|
||||
nout,
|
||||
}) {
|
||||
return { name, outpoint, claim_id, txid, nout, channel_name };
|
||||
function pendingPublishToDummyClaim({ channelName, name, outpoint, claimId, txid, nout }) {
|
||||
return { name, outpoint, claimId, txid, nout, channelName };
|
||||
}
|
||||
|
||||
function pendingPublishToDummyFileInfo({ name, outpoint, claim_id }) {
|
||||
return { name, outpoint, claim_id, metadata: null };
|
||||
function pendingPublishToDummyFileInfo({ name, outpoint, claimId }) {
|
||||
return { name, outpoint, claimId, metadata: null };
|
||||
}
|
||||
|
||||
// core
|
||||
lbry._connectPromise = null;
|
||||
lbry.connect = function() {
|
||||
if (lbry._connectPromise === null) {
|
||||
lbry._connectPromise = new Promise((resolve, reject) => {
|
||||
Lbry.connectPromise = null;
|
||||
Lbry.connect = function() {
|
||||
if (Lbry.connectPromise === null) {
|
||||
Lbry.connectPromise = new Promise((resolve, reject) => {
|
||||
let tryNum = 0;
|
||||
|
||||
function checkDaemonStartedFailed() {
|
||||
if (tryNum <= 200) {
|
||||
// Move # of tries into constant or config option
|
||||
setTimeout(() => {
|
||||
tryNum++;
|
||||
checkDaemonStarted();
|
||||
}, tryNum < 50 ? 400 : 1000);
|
||||
} else {
|
||||
reject(new Error("Unable to connect to LBRY"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check every half second to see if the daemon is accepting connections
|
||||
function checkDaemonStarted() {
|
||||
lbry
|
||||
tryNum += 1;
|
||||
lbryProxy
|
||||
.status()
|
||||
.then(resolve)
|
||||
.catch(checkDaemonStartedFailed);
|
||||
.catch(() => {
|
||||
if (tryNum <= CHECK_DAEMON_STARTED_TRY_NUMBER) {
|
||||
setTimeout(checkDaemonStarted, tryNum < 50 ? 400 : 1000);
|
||||
} else {
|
||||
reject(new Error('Unable to connect to LBRY'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
checkDaemonStarted();
|
||||
});
|
||||
}
|
||||
|
||||
return lbry._connectPromise;
|
||||
return Lbry.connectPromise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -160,13 +144,24 @@ lbry.connect = function() {
|
|||
* This currently includes a work-around to cache the file in local storage so that the pending
|
||||
* publish can appear in the UI immediately.
|
||||
*/
|
||||
lbry.publishDeprecated = function(
|
||||
params,
|
||||
fileListedCallback,
|
||||
publishedCallback,
|
||||
errorCallback
|
||||
) {
|
||||
lbry.publish(params).then(
|
||||
Lbry.publishDeprecated = function(params, fileListedCallback, publishedCallback, errorCallback) {
|
||||
// Give a short grace period in case publish() returns right away or (more likely) gives an error
|
||||
const returnPendingTimeout = setTimeout(
|
||||
() => {
|
||||
const { name, channel_name: channelName } = params;
|
||||
if (publishedCallback || fileListedCallback) {
|
||||
savePendingPublish({
|
||||
name,
|
||||
channelName,
|
||||
});
|
||||
publishedCallback(true);
|
||||
}
|
||||
},
|
||||
2000,
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
lbryProxy.publish(params).then(
|
||||
result => {
|
||||
if (returnPendingTimeout) clearTimeout(returnPendingTimeout);
|
||||
publishedCallback(result);
|
||||
|
@ -176,66 +171,40 @@ lbry.publishDeprecated = function(
|
|||
errorCallback(err);
|
||||
}
|
||||
);
|
||||
|
||||
// Give a short grace period in case publish() returns right away or (more likely) gives an error
|
||||
const returnPendingTimeout = setTimeout(
|
||||
() => {
|
||||
if (publishedCallback) {
|
||||
savePendingPublish({
|
||||
name: params.name,
|
||||
channel_name: params.channel_name,
|
||||
});
|
||||
publishedCallback(true);
|
||||
}
|
||||
|
||||
if (fileListedCallback) {
|
||||
const { name, channel_name } = params;
|
||||
savePendingPublish({
|
||||
name: params.name,
|
||||
channel_name: params.channel_name,
|
||||
});
|
||||
fileListedCallback(true);
|
||||
}
|
||||
},
|
||||
2000,
|
||||
{ once: true }
|
||||
);
|
||||
};
|
||||
|
||||
lbry.imagePath = function(file) {
|
||||
Lbry.imagePath = function(file) {
|
||||
return `${staticResourcesPath}/img/${file}`;
|
||||
};
|
||||
|
||||
lbry.getMediaType = function(contentType, fileName) {
|
||||
Lbry.getMediaType = function(contentType, fileName) {
|
||||
if (contentType) {
|
||||
return /^[^/]+/.exec(contentType)[0];
|
||||
} else if (fileName) {
|
||||
const dotIndex = fileName.lastIndexOf(".");
|
||||
if (dotIndex == -1) {
|
||||
return "unknown";
|
||||
const dotIndex = fileName.lastIndexOf('.');
|
||||
if (dotIndex === -1) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
const ext = fileName.substr(dotIndex + 1);
|
||||
if (/^mp4|m4v|webm|flv|f4v|ogv$/i.test(ext)) {
|
||||
return "video";
|
||||
return 'video';
|
||||
} else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) {
|
||||
return "audio";
|
||||
} else if (
|
||||
/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext)
|
||||
) {
|
||||
return "document";
|
||||
return 'audio';
|
||||
} else if (/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext)) {
|
||||
return 'document';
|
||||
}
|
||||
return "unknown";
|
||||
return 'unknown';
|
||||
}
|
||||
return "unknown";
|
||||
return 'unknown';
|
||||
};
|
||||
|
||||
lbry.getAppVersionInfo = function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.once("version-info-received", (event, versionInfo) => {
|
||||
Lbry.getAppVersionInfo = function() {
|
||||
return new Promise(resolve => {
|
||||
ipcRenderer.once('version-info-received', (event, versionInfo) => {
|
||||
resolve(versionInfo);
|
||||
});
|
||||
ipcRenderer.send("version-info-requested");
|
||||
ipcRenderer.send('version-info-requested');
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -248,9 +217,9 @@ lbry.getAppVersionInfo = function() {
|
|||
* Returns results from the file_list API method, plus dummy entries for pending publishes.
|
||||
* (If a real publish with the same name is found, the pending publish will be ignored and removed.)
|
||||
*/
|
||||
lbry.file_list = function(params = {}) {
|
||||
Lbry.file_list = function(params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { name, channel_name, outpoint } = params;
|
||||
const { name, channel_name: channelName, outpoint } = params;
|
||||
|
||||
/**
|
||||
* If we're searching by outpoint, check first to see if there's a matching pending publish.
|
||||
|
@ -266,16 +235,14 @@ lbry.file_list = function(params = {}) {
|
|||
}
|
||||
|
||||
apiCall(
|
||||
"file_list",
|
||||
'file_list',
|
||||
params,
|
||||
fileInfos => {
|
||||
removePendingPublishIfNeeded({ name, channel_name, outpoint });
|
||||
removePendingPublishIfNeeded({ name, channelName, outpoint });
|
||||
|
||||
// if a naked file_list call, append the pending file infos
|
||||
if (!name && !channel_name && !outpoint) {
|
||||
const dummyFileInfos = lbry
|
||||
.getPendingPublishes()
|
||||
.map(pendingPublishToDummyFileInfo);
|
||||
if (!name && !channelName && !outpoint) {
|
||||
const dummyFileInfos = Lbry.getPendingPublishes().map(pendingPublishToDummyFileInfo);
|
||||
|
||||
resolve([...fileInfos, ...dummyFileInfos]);
|
||||
} else {
|
||||
|
@ -287,23 +254,21 @@ lbry.file_list = function(params = {}) {
|
|||
});
|
||||
};
|
||||
|
||||
lbry.claim_list_mine = function(params = {}) {
|
||||
Lbry.claim_list_mine = function(params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiCall(
|
||||
"claim_list_mine",
|
||||
'claim_list_mine',
|
||||
params,
|
||||
claims => {
|
||||
for (const { name, channel_name, txid, nout } of claims) {
|
||||
claims.forEach(({ name, channel_name: channelName, txid, nout }) => {
|
||||
removePendingPublishIfNeeded({
|
||||
name,
|
||||
channel_name,
|
||||
channelName,
|
||||
outpoint: `${txid}:${nout}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const dummyClaims = lbry
|
||||
.getPendingPublishes()
|
||||
.map(pendingPublishToDummyClaim);
|
||||
const dummyClaims = Lbry.getPendingPublishes().map(pendingPublishToDummyClaim);
|
||||
resolve([...claims, ...dummyClaims]);
|
||||
},
|
||||
reject
|
||||
|
@ -311,13 +276,13 @@ lbry.claim_list_mine = function(params = {}) {
|
|||
});
|
||||
};
|
||||
|
||||
lbry.resolve = function(params = {}) {
|
||||
Lbry.resolve = function(params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiCall(
|
||||
"resolve",
|
||||
'resolve',
|
||||
params,
|
||||
data => {
|
||||
if ("uri" in params) {
|
||||
if ('uri' in params) {
|
||||
// If only a single URI was requested, don't nest the results in an object
|
||||
resolve(data && data[params.uri] ? data[params.uri] : {});
|
||||
} else {
|
||||
|
@ -329,18 +294,4 @@ lbry.resolve = function(params = {}) {
|
|||
});
|
||||
};
|
||||
|
||||
lbry = new Proxy(lbry, {
|
||||
get(target, name) {
|
||||
if (name in target) {
|
||||
return target[name];
|
||||
}
|
||||
|
||||
return function(params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiCall(name, params, resolve, reject);
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default lbry;
|
||||
export default lbryProxy;
|
||||
|
|
|
@ -1,48 +1,46 @@
|
|||
import lbry from "./lbry.js";
|
||||
import Lbry from 'lbry';
|
||||
import querystring from 'querystring';
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
const querystring = require("querystring");
|
||||
const { ipcRenderer } = require("electron");
|
||||
|
||||
const lbryio = {
|
||||
const Lbryio = {
|
||||
enabled: true,
|
||||
_authenticationPromise: null,
|
||||
_exchangePromise: null,
|
||||
_exchangeLastFetched: null,
|
||||
authenticationPromise: null,
|
||||
exchangePromise: null,
|
||||
exchangeLastFetched: null,
|
||||
};
|
||||
|
||||
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
|
||||
? process.env.LBRY_APP_API_URL.replace(/\/*$/, "/") // exactly one slash at the end
|
||||
: "https://api.lbry.io/";
|
||||
? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end
|
||||
: 'https://api.lbry.io/';
|
||||
|
||||
const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
|
||||
|
||||
lbryio.getExchangeRates = function() {
|
||||
Lbryio.getExchangeRates = function() {
|
||||
if (
|
||||
!lbryio._exchangeLastFetched ||
|
||||
Date.now() - lbryio._exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
|
||||
!Lbryio.exchangeLastFetched ||
|
||||
Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
|
||||
) {
|
||||
lbryio._exchangePromise = new Promise((resolve, reject) => {
|
||||
lbryio
|
||||
.call("lbc", "exchange_rate", {}, "get", true)
|
||||
.then(({ lbc_usd, lbc_btc, btc_usd }) => {
|
||||
const rates = { lbc_usd, lbc_btc, btc_usd };
|
||||
Lbryio.exchangePromise = new Promise((resolve, reject) => {
|
||||
Lbryio.call('lbc', 'exchange_rate', {}, 'get', true)
|
||||
.then(({ lbc_usd: LBC_USD, lbc_btc: LBC_BTC, btc_usd: BTC_USD }) => {
|
||||
const rates = { LBC_USD, LBC_BTC, BTC_USD };
|
||||
resolve(rates);
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
lbryio._exchangeLastFetched = Date.now();
|
||||
Lbryio.exchangeLastFetched = Date.now();
|
||||
}
|
||||
return lbryio._exchangePromise;
|
||||
return Lbryio.exchangePromise;
|
||||
};
|
||||
|
||||
lbryio.call = function(resource, action, params = {}, method = "get") {
|
||||
if (!lbryio.enabled) {
|
||||
console.log(__("Internal API disabled"));
|
||||
return Promise.reject(new Error(__("LBRY internal API is disabled")));
|
||||
Lbryio.call = function(resource, action, params = {}, method = 'get') {
|
||||
if (!Lbryio.enabled) {
|
||||
console.log(__('Internal API disabled'));
|
||||
return Promise.reject(new Error(__('LBRY internal API is disabled')));
|
||||
}
|
||||
|
||||
if (!(method == "get" || method == "post")) {
|
||||
return Promise.reject(new Error(__("Invalid method")));
|
||||
if (!(method === 'get' || method === 'post')) {
|
||||
return Promise.reject(new Error(__('Invalid method')));
|
||||
}
|
||||
|
||||
function checkAndParse(response) {
|
||||
|
@ -54,7 +52,7 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
|
|||
if (json.error) {
|
||||
error = new Error(json.error);
|
||||
} else {
|
||||
error = new Error("Unknown API error signature");
|
||||
error = new Error('Unknown API error signature');
|
||||
}
|
||||
error.response = response; // this is primarily a hack used in actions/user.js
|
||||
return Promise.reject(error);
|
||||
|
@ -65,20 +63,20 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
|
|||
return fetch(url, options).then(checkAndParse);
|
||||
}
|
||||
|
||||
return lbryio.getAuthToken().then(token => {
|
||||
return Lbryio.getAuthToken().then(token => {
|
||||
const fullParams = { auth_token: token, ...params };
|
||||
const qs = querystring.stringify(fullParams);
|
||||
let url = `${CONNECTION_STRING}${resource}/${action}?${qs}`;
|
||||
|
||||
let options = {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
};
|
||||
|
||||
if (method == "post") {
|
||||
if (method === 'post') {
|
||||
options = {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: qs,
|
||||
};
|
||||
|
@ -89,35 +87,35 @@ lbryio.call = function(resource, action, params = {}, method = "get") {
|
|||
});
|
||||
};
|
||||
|
||||
lbryio._authToken = null;
|
||||
Lbryio.authToken = null;
|
||||
|
||||
lbryio.getAuthToken = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (lbryio._authToken) {
|
||||
resolve(lbryio._authToken);
|
||||
Lbryio.getAuthToken = () =>
|
||||
new Promise(resolve => {
|
||||
if (Lbryio.authToken) {
|
||||
resolve(Lbryio.authToken);
|
||||
} else {
|
||||
ipcRenderer.once("auth-token-response", (event, token) => {
|
||||
lbryio._authToken = token;
|
||||
ipcRenderer.once('auth-token-response', (event, token) => {
|
||||
Lbryio.authToken = token;
|
||||
return resolve(token);
|
||||
});
|
||||
ipcRenderer.send("get-auth-token");
|
||||
ipcRenderer.send('get-auth-token');
|
||||
}
|
||||
});
|
||||
|
||||
lbryio.setAuthToken = token => {
|
||||
lbryio._authToken = token ? token.toString().trim() : null;
|
||||
ipcRenderer.send("set-auth-token", token);
|
||||
Lbryio.setAuthToken = token => {
|
||||
Lbryio.authToken = token ? token.toString().trim() : null;
|
||||
ipcRenderer.send('set-auth-token', token);
|
||||
};
|
||||
|
||||
lbryio.getCurrentUser = () => lbryio.call("user", "me");
|
||||
Lbryio.getCurrentUser = () => Lbryio.call('user', 'me');
|
||||
|
||||
lbryio.authenticate = function() {
|
||||
if (!lbryio.enabled) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Lbryio.authenticate = function() {
|
||||
if (!Lbryio.enabled) {
|
||||
return new Promise(resolve => {
|
||||
resolve({
|
||||
id: 1,
|
||||
language: "en",
|
||||
primary_email: "disabled@lbry.io",
|
||||
language: 'en',
|
||||
primary_email: 'disabled@lbry.io',
|
||||
has_verified_email: true,
|
||||
is_identity_verified: true,
|
||||
is_reward_approved: false,
|
||||
|
@ -125,58 +123,55 @@ lbryio.authenticate = function() {
|
|||
});
|
||||
}
|
||||
|
||||
if (lbryio._authenticationPromise === null) {
|
||||
lbryio._authenticationPromise = new Promise((resolve, reject) => {
|
||||
lbryio
|
||||
.getAuthToken()
|
||||
if (Lbryio.authenticationPromise === null) {
|
||||
Lbryio.authenticationPromise = new Promise((resolve, reject) => {
|
||||
Lbryio.getAuthToken()
|
||||
.then(token => {
|
||||
if (!token || token.length > 60) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check that token works
|
||||
return lbryio
|
||||
.getCurrentUser()
|
||||
return Lbryio.getCurrentUser()
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
})
|
||||
.then(isTokenValid => {
|
||||
if (isTokenValid) {
|
||||
return;
|
||||
return reject;
|
||||
}
|
||||
|
||||
return lbry
|
||||
.status()
|
||||
return Lbry.status()
|
||||
.then(status =>
|
||||
lbryio.call(
|
||||
"user",
|
||||
"new",
|
||||
Lbryio.call(
|
||||
'user',
|
||||
'new',
|
||||
{
|
||||
auth_token: "",
|
||||
language: "en",
|
||||
auth_token: '',
|
||||
language: 'en',
|
||||
app_id: status.installation_id,
|
||||
},
|
||||
"post"
|
||||
'post'
|
||||
)
|
||||
)
|
||||
.then(response => {
|
||||
if (!response.auth_token) {
|
||||
throw new Error(__("auth_token is missing from response"));
|
||||
throw new Error(__('auth_token is missing from response'));
|
||||
}
|
||||
return lbryio.setAuthToken(response.auth_token);
|
||||
return Lbryio.setAuthToken(response.auth_token);
|
||||
});
|
||||
})
|
||||
.then(lbryio.getCurrentUser)
|
||||
.then(Lbryio.getCurrentUser)
|
||||
.then(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
return lbryio._authenticationPromise;
|
||||
return Lbryio.authenticationPromise;
|
||||
};
|
||||
|
||||
lbryio.getStripeToken = () =>
|
||||
CONNECTION_STRING.startsWith("http://localhost:")
|
||||
? "pk_test_NoL1JWL7i1ipfhVId5KfDZgo"
|
||||
: "pk_live_e8M4dRNnCCbmpZzduEUZBgJO";
|
||||
Lbryio.getStripeToken = () =>
|
||||
CONNECTION_STRING.startsWith('http://localhost:')
|
||||
? 'pk_test_NoL1JWL7i1ipfhVId5KfDZgo'
|
||||
: 'pk_live_e8M4dRNnCCbmpZzduEUZBgJO';
|
||||
|
||||
export default lbryio;
|
||||
export default Lbryio;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const CHANNEL_NAME_MIN_LEN = 1;
|
||||
const CLAIM_ID_MAX_LEN = 40;
|
||||
|
||||
const lbryuri = {};
|
||||
const Lbryuri = {};
|
||||
|
||||
lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g;
|
||||
lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
||||
Lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g;
|
||||
Lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
||||
|
||||
/**
|
||||
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
||||
|
@ -28,13 +28,13 @@ lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
|||
* - contentName (string): For anon claims, the name; for channel claims, the path
|
||||
* - channelName (string, if present): Channel name without @
|
||||
*/
|
||||
lbryuri.parse = function(uri, requireProto = false) {
|
||||
Lbryuri.parse = function(uri, requireProto = false) {
|
||||
// Break into components. Empty sub-matches are converted to null
|
||||
const componentsRegex = new RegExp(
|
||||
"^((?:lbry://)?)" + // protocol
|
||||
"([^:$#/]*)" + // name (stops at the first separator or end)
|
||||
"([:$#]?)([^/]*)" + // modifier separator, modifier (stops at the first path separator or end)
|
||||
"(/?)(.*)" // path separator, path
|
||||
'^((?:lbry://)?)' + // protocol
|
||||
'([^:$#/]*)' + // name (stops at the first separator or end)
|
||||
'([:$#]?)([^/]*)' + // modifier separator, modifier (stops at the first path separator or end)
|
||||
'(/?)(.*)' // path separator, path
|
||||
);
|
||||
const [proto, name, modSep, modVal, pathSep, path] = componentsRegex
|
||||
.exec(uri)
|
||||
|
@ -45,57 +45,54 @@ lbryuri.parse = function(uri, requireProto = false) {
|
|||
|
||||
// Validate protocol
|
||||
if (requireProto && !proto) {
|
||||
throw new Error(__("LBRY URIs must include a protocol prefix (lbry://)."));
|
||||
throw new Error(__('LBRY URIs must include a protocol prefix (lbry://).'));
|
||||
}
|
||||
|
||||
// Validate and process name
|
||||
if (!name) {
|
||||
throw new Error(__("URI does not include name."));
|
||||
throw new Error(__('URI does not include name.'));
|
||||
}
|
||||
|
||||
const isChannel = name.startsWith("@");
|
||||
const isChannel = name.startsWith('@');
|
||||
const channelName = isChannel ? name.slice(1) : name;
|
||||
|
||||
if (isChannel) {
|
||||
if (!channelName) {
|
||||
throw new Error(__("No channel name after @."));
|
||||
throw new Error(__('No channel name after @.'));
|
||||
}
|
||||
|
||||
if (channelName.length < CHANNEL_NAME_MIN_LEN) {
|
||||
throw new Error(
|
||||
__(
|
||||
`Channel names must be at least %s characters.`,
|
||||
CHANNEL_NAME_MIN_LEN
|
||||
)
|
||||
);
|
||||
throw new Error(__(`Channel names must be at least %s characters.`, CHANNEL_NAME_MIN_LEN));
|
||||
}
|
||||
|
||||
contentName = path;
|
||||
}
|
||||
|
||||
const nameBadChars = (channelName || name).match(lbryuri.REGEXP_INVALID_URI);
|
||||
const nameBadChars = (channelName || name).match(Lbryuri.REGEXP_INVALID_URI);
|
||||
if (nameBadChars) {
|
||||
throw new Error(
|
||||
__(
|
||||
`Invalid character %s in name: %s.`,
|
||||
nameBadChars.length == 1 ? "" : "s",
|
||||
nameBadChars.join(", ")
|
||||
nameBadChars.length === 1 ? '' : 's',
|
||||
nameBadChars.join(', ')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Validate and process modifier (claim ID, bid position or claim sequence)
|
||||
let claimId, claimSequence, bidPosition;
|
||||
let claimId;
|
||||
let claimSequence;
|
||||
let bidPosition;
|
||||
if (modSep) {
|
||||
if (!modVal) {
|
||||
throw new Error(__(`No modifier provided after separator %s.`, modSep));
|
||||
}
|
||||
|
||||
if (modSep == "#") {
|
||||
if (modSep === '#') {
|
||||
claimId = modVal;
|
||||
} else if (modSep == ":") {
|
||||
} else if (modSep === ':') {
|
||||
claimSequence = modVal;
|
||||
} else if (modSep == "$") {
|
||||
} else if (modSep === '$') {
|
||||
bidPosition = modVal;
|
||||
}
|
||||
}
|
||||
|
@ -109,29 +106,27 @@ lbryuri.parse = function(uri, requireProto = false) {
|
|||
}
|
||||
|
||||
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
|
||||
throw new Error(__("Claim sequence must be a number."));
|
||||
throw new Error(__('Claim sequence must be a number.'));
|
||||
}
|
||||
|
||||
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
|
||||
throw new Error(__("Bid position must be a number."));
|
||||
throw new Error(__('Bid position must be a number.'));
|
||||
}
|
||||
|
||||
// Validate and process path
|
||||
if (path) {
|
||||
if (!isChannel) {
|
||||
throw new Error(__("Only channel URIs may have a path."));
|
||||
throw new Error(__('Only channel URIs may have a path.'));
|
||||
}
|
||||
|
||||
const pathBadChars = path.match(lbryuri.REGEXP_INVALID_URI);
|
||||
const pathBadChars = path.match(Lbryuri.REGEXP_INVALID_URI);
|
||||
if (pathBadChars) {
|
||||
throw new Error(
|
||||
__(`Invalid character in path: %s`, pathBadChars.join(", "))
|
||||
);
|
||||
throw new Error(__(`Invalid character in path: %s`, pathBadChars.join(', ')));
|
||||
}
|
||||
|
||||
contentName = path;
|
||||
} else if (pathSep) {
|
||||
throw new Error(__("No path provided after /"));
|
||||
throw new Error(__('No path provided after /'));
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -140,8 +135,8 @@ lbryuri.parse = function(uri, requireProto = false) {
|
|||
isChannel,
|
||||
...(contentName ? { contentName } : {}),
|
||||
...(channelName ? { channelName } : {}),
|
||||
...(claimSequence ? { claimSequence: parseInt(claimSequence) } : {}),
|
||||
...(bidPosition ? { bidPosition: parseInt(bidPosition) } : {}),
|
||||
...(claimSequence ? { claimSequence: parseInt(claimSequence, 10) } : {}),
|
||||
...(bidPosition ? { bidPosition: parseInt(bidPosition, 10) } : {}),
|
||||
...(claimId ? { claimId } : {}),
|
||||
...(path ? { path } : {}),
|
||||
};
|
||||
|
@ -152,21 +147,13 @@ lbryuri.parse = function(uri, requireProto = false) {
|
|||
*
|
||||
* The channelName key will accept names with or without the @ prefix.
|
||||
*/
|
||||
lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) {
|
||||
let {
|
||||
name,
|
||||
claimId,
|
||||
claimSequence,
|
||||
bidPosition,
|
||||
path,
|
||||
contentName,
|
||||
channelName,
|
||||
} = uriObj;
|
||||
Lbryuri.build = function(uriObj, includeProto = true) {
|
||||
const { claimId, claimSequence, bidPosition, contentName, channelName } = uriObj;
|
||||
|
||||
let { name, path } = uriObj;
|
||||
|
||||
if (channelName) {
|
||||
const channelNameFormatted = channelName.startsWith("@")
|
||||
? channelName
|
||||
: `@${channelName}`;
|
||||
const channelNameFormatted = channelName.startsWith('@') ? channelName : `@${channelName}`;
|
||||
if (!name) {
|
||||
name = channelNameFormatted;
|
||||
} else if (name !== channelNameFormatted) {
|
||||
|
@ -187,52 +174,50 @@ lbryuri.build = function(uriObj, includeProto = true, allowExtraProps = false) {
|
|||
if (path && path !== contentName) {
|
||||
throw new Error(
|
||||
__(
|
||||
"Path and contentName do not match. Only one is required; most likely you wanted contentName."
|
||||
'Path and contentName do not match. Only one is required; most likely you wanted contentName.'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
(includeProto ? "lbry://" : "") +
|
||||
(includeProto ? 'lbry://' : '') +
|
||||
name +
|
||||
(claimId ? `#${claimId}` : "") +
|
||||
(claimSequence ? `:${claimSequence}` : "") +
|
||||
(bidPosition ? `\$${bidPosition}` : "") +
|
||||
(path ? `/${path}` : "")
|
||||
(claimId ? `#${claimId}` : '') +
|
||||
(claimSequence ? `:${claimSequence}` : '') +
|
||||
(bidPosition ? `${bidPosition}` : '') +
|
||||
(path ? `/${path}` : '')
|
||||
);
|
||||
};
|
||||
|
||||
/* Takes a parseable LBRY URI and converts it to standard, canonical format (currently this just
|
||||
* consists of adding the lbry:// prefix if needed) */
|
||||
lbryuri.normalize = function(uri) {
|
||||
Lbryuri.normalize = function(uri) {
|
||||
if (uri.match(/pending_claim/)) return uri;
|
||||
|
||||
const { name, path, bidPosition, claimSequence, claimId } = lbryuri.parse(
|
||||
uri
|
||||
);
|
||||
return lbryuri.build({ name, path, claimSequence, bidPosition, claimId });
|
||||
const { name, path, bidPosition, claimSequence, claimId } = Lbryuri.parse(uri);
|
||||
return Lbryuri.build({ name, path, claimSequence, bidPosition, claimId });
|
||||
};
|
||||
|
||||
lbryuri.isValid = function(uri) {
|
||||
Lbryuri.isValid = function(uri) {
|
||||
let parts;
|
||||
try {
|
||||
parts = lbryuri.parse(lbryuri.normalize(uri));
|
||||
parts = Lbryuri.parse(Lbryuri.normalize(uri));
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
return parts && parts.name;
|
||||
};
|
||||
|
||||
lbryuri.isValidName = function(name, checkCase = true) {
|
||||
const regexp = new RegExp("^[a-z0-9-]+$", checkCase ? "" : "i");
|
||||
Lbryuri.isValidName = function(name, checkCase = true) {
|
||||
const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i');
|
||||
return regexp.test(name);
|
||||
};
|
||||
|
||||
lbryuri.isClaimable = function(uri) {
|
||||
Lbryuri.isClaimable = function(uri) {
|
||||
let parts;
|
||||
try {
|
||||
parts = lbryuri.parse(lbryuri.normalize(uri));
|
||||
parts = Lbryuri.parse(Lbryuri.normalize(uri));
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
@ -247,5 +232,5 @@ lbryuri.isClaimable = function(uri) {
|
|||
);
|
||||
};
|
||||
|
||||
window.lbryuri = lbryuri;
|
||||
export default lbryuri;
|
||||
window.lbryuri = Lbryuri;
|
||||
export default Lbryuri;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbry from "lbry";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbry from 'lbry';
|
||||
import {
|
||||
selectUpdateUrl,
|
||||
selectUpgradeDownloadPath,
|
||||
|
@ -7,27 +7,26 @@ import {
|
|||
selectUpgradeFilename,
|
||||
selectIsUpgradeSkipped,
|
||||
selectRemoteVersion,
|
||||
} from "redux/selectors/app";
|
||||
import { doFetchDaemonSettings } from "redux/actions/settings";
|
||||
import { doBalanceSubscribe, doFetchTransactions } from "redux/actions/wallet";
|
||||
import { doAuthenticate } from "redux/actions/user";
|
||||
import { doFetchFileInfosAndPublishedClaims } from "redux/actions/file_info";
|
||||
import * as modals from "constants/modal_types";
|
||||
import { doFetchRewardedContent } from "redux/actions/content";
|
||||
import { selectCurrentModal } from "redux/selectors/app";
|
||||
selectCurrentModal,
|
||||
} from 'redux/selectors/app';
|
||||
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
||||
import { doBalanceSubscribe, doFetchTransactions } from 'redux/actions/wallet';
|
||||
import { doAuthenticate } from 'redux/actions/user';
|
||||
import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import { doFetchRewardedContent } from 'redux/actions/content';
|
||||
import { ipcRenderer, remote } from 'electron';
|
||||
import Path from 'path';
|
||||
|
||||
const { remote, ipcRenderer, shell } = require("electron");
|
||||
const path = require("path");
|
||||
|
||||
const { download } = remote.require("electron-dl");
|
||||
const fs = remote.require("fs");
|
||||
const { lbrySettings: config } = require("package.json");
|
||||
const { download } = remote.require('electron-dl');
|
||||
const Fs = remote.require('fs');
|
||||
const { lbrySettings: config } = require('package.json');
|
||||
|
||||
const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000;
|
||||
|
||||
export function doOpenModal(modal, modalProps = {}) {
|
||||
return {
|
||||
type: types.OPEN_MODAL,
|
||||
type: ACTIONS.OPEN_MODAL,
|
||||
data: {
|
||||
modal,
|
||||
modalProps,
|
||||
|
@ -37,13 +36,13 @@ export function doOpenModal(modal, modalProps = {}) {
|
|||
|
||||
export function doCloseModal() {
|
||||
return {
|
||||
type: types.CLOSE_MODAL,
|
||||
type: ACTIONS.CLOSE_MODAL,
|
||||
};
|
||||
}
|
||||
|
||||
export function doUpdateDownloadProgress(percent) {
|
||||
return {
|
||||
type: types.UPGRADE_DOWNLOAD_PROGRESSED,
|
||||
type: ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED,
|
||||
data: {
|
||||
percent,
|
||||
},
|
||||
|
@ -52,7 +51,7 @@ export function doUpdateDownloadProgress(percent) {
|
|||
|
||||
export function doSkipUpgrade() {
|
||||
return {
|
||||
type: types.SKIP_UPGRADE,
|
||||
type: ACTIONS.SKIP_UPGRADE,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -61,7 +60,7 @@ export function doStartUpgrade() {
|
|||
const state = getState();
|
||||
const upgradeDownloadPath = selectUpgradeDownloadPath(state);
|
||||
|
||||
ipcRenderer.send("upgrade", upgradeDownloadPath);
|
||||
ipcRenderer.send('upgrade', upgradeDownloadPath);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,40 +68,36 @@ export function doDownloadUpgrade() {
|
|||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
// Make a new directory within temp directory so the filename is guaranteed to be available
|
||||
const dir = fs.mkdtempSync(
|
||||
remote.app.getPath("temp") + require("path").sep
|
||||
),
|
||||
upgradeFilename = selectUpgradeFilename(state);
|
||||
const dir = Fs.mkdtempSync(remote.app.getPath('temp') + Path.sep);
|
||||
const upgradeFilename = selectUpgradeFilename(state);
|
||||
|
||||
const options = {
|
||||
onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))),
|
||||
directory: dir,
|
||||
};
|
||||
download(remote.getCurrentWindow(), selectUpdateUrl(state), options).then(
|
||||
downloadItem => {
|
||||
/**
|
||||
* TODO: get the download path directly from the download object. It should just be
|
||||
* downloadItem.getSavePath(), but the copy on the main process is being garbage collected
|
||||
* too soon.
|
||||
*/
|
||||
download(remote.getCurrentWindow(), selectUpdateUrl(state), options).then(downloadItem => {
|
||||
/**
|
||||
* TODO: get the download path directly from the download object. It should just be
|
||||
* downloadItem.getSavePath(), but the copy on the main process is being garbage collected
|
||||
* too soon.
|
||||
*/
|
||||
|
||||
dispatch({
|
||||
type: types.UPGRADE_DOWNLOAD_COMPLETED,
|
||||
data: {
|
||||
downloadItem,
|
||||
path: path.join(dir, upgradeFilename),
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
dispatch({
|
||||
type: ACTIONS.UPGRADE_DOWNLOAD_COMPLETED,
|
||||
data: {
|
||||
downloadItem,
|
||||
path: Path.join(dir, upgradeFilename),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: types.UPGRADE_DOWNLOAD_STARTED,
|
||||
type: ACTIONS.UPGRADE_DOWNLOAD_STARTED,
|
||||
});
|
||||
dispatch({
|
||||
type: types.OPEN_MODAL,
|
||||
type: ACTIONS.OPEN_MODAL,
|
||||
data: {
|
||||
modal: modals.DOWNLOADING,
|
||||
modal: MODALS.DOWNLOADING,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -127,7 +122,7 @@ export function doCancelUpgrade() {
|
|||
}
|
||||
}
|
||||
|
||||
dispatch({ type: types.UPGRADE_CANCELLED });
|
||||
dispatch({ type: ACTIONS.UPGRADE_CANCELLED });
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -135,12 +130,12 @@ export function doCheckUpgradeAvailable() {
|
|||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
dispatch({
|
||||
type: types.CHECK_UPGRADE_START,
|
||||
type: ACTIONS.CHECK_UPGRADE_START,
|
||||
});
|
||||
|
||||
const success = ({ remoteVersion, upgradeAvailable }) => {
|
||||
dispatch({
|
||||
type: types.CHECK_UPGRADE_SUCCESS,
|
||||
type: ACTIONS.CHECK_UPGRADE_SUCCESS,
|
||||
data: {
|
||||
upgradeAvailable,
|
||||
remoteVersion,
|
||||
|
@ -150,13 +145,12 @@ export function doCheckUpgradeAvailable() {
|
|||
if (
|
||||
upgradeAvailable &&
|
||||
!selectCurrentModal(state) &&
|
||||
(!selectIsUpgradeSkipped(state) ||
|
||||
remoteVersion !== selectRemoteVersion(state))
|
||||
(!selectIsUpgradeSkipped(state) || remoteVersion !== selectRemoteVersion(state))
|
||||
) {
|
||||
dispatch({
|
||||
type: types.OPEN_MODAL,
|
||||
type: ACTIONS.OPEN_MODAL,
|
||||
data: {
|
||||
modal: modals.UPGRADE,
|
||||
modal: MODALS.UPGRADE,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -164,11 +158,11 @@ export function doCheckUpgradeAvailable() {
|
|||
|
||||
const fail = () => {
|
||||
dispatch({
|
||||
type: types.CHECK_UPGRADE_FAIL,
|
||||
type: ACTIONS.CHECK_UPGRADE_FAIL,
|
||||
});
|
||||
};
|
||||
|
||||
lbry.getAppVersionInfo().then(success, fail);
|
||||
Lbry.getAppVersionInfo().then(success, fail);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -182,32 +176,31 @@ export function doCheckUpgradeSubscribe() {
|
|||
CHECK_UPGRADE_INTERVAL
|
||||
);
|
||||
dispatch({
|
||||
type: types.CHECK_UPGRADE_SUBSCRIBE,
|
||||
type: ACTIONS.CHECK_UPGRADE_SUBSCRIBE,
|
||||
data: { checkUpgradeTimer },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doCheckDaemonVersion() {
|
||||
return function(dispatch, getState) {
|
||||
lbry.version().then(({ lbrynet_version }) => {
|
||||
return function(dispatch) {
|
||||
Lbry.version().then(({ lbrynet_version: lbrynetVersion }) => {
|
||||
dispatch({
|
||||
type:
|
||||
config.lbrynetDaemonVersion == lbrynet_version
|
||||
? types.DAEMON_VERSION_MATCH
|
||||
: types.DAEMON_VERSION_MISMATCH,
|
||||
config.lbrynetDaemonVersion === lbrynetVersion
|
||||
? ACTIONS.DAEMON_VERSION_MATCH
|
||||
: ACTIONS.DAEMON_VERSION_MISMATCH,
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doAlertError(errorList) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.OPEN_MODAL,
|
||||
type: ACTIONS.OPEN_MODAL,
|
||||
data: {
|
||||
modal: modals.ERROR,
|
||||
modal: MODALS.ERROR,
|
||||
modalProps: { error: errorList },
|
||||
},
|
||||
});
|
||||
|
@ -219,7 +212,7 @@ export function doDaemonReady() {
|
|||
const state = getState();
|
||||
|
||||
dispatch(doAuthenticate());
|
||||
dispatch({ type: types.DAEMON_READY });
|
||||
dispatch({ type: ACTIONS.DAEMON_READY });
|
||||
dispatch(doFetchDaemonSettings());
|
||||
dispatch(doBalanceSubscribe());
|
||||
dispatch(doFetchFileInfosAndPublishedClaims());
|
||||
|
@ -234,19 +227,19 @@ export function doDaemonReady() {
|
|||
|
||||
export function doShowSnackBar(data) {
|
||||
return {
|
||||
type: types.SHOW_SNACKBAR,
|
||||
type: ACTIONS.SHOW_SNACKBAR,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
export function doRemoveSnackBarSnack() {
|
||||
return {
|
||||
type: types.REMOVE_SNACKBAR_SNACK,
|
||||
type: ACTIONS.REMOVE_SNACKBAR_SNACK,
|
||||
};
|
||||
}
|
||||
|
||||
export function doClearCache() {
|
||||
return function(dispatch, getState) {
|
||||
return function() {
|
||||
window.cacheStore.purge();
|
||||
|
||||
return Promise.resolve();
|
||||
|
@ -254,15 +247,15 @@ export function doClearCache() {
|
|||
}
|
||||
|
||||
export function doQuit() {
|
||||
return function(dispatch, getState) {
|
||||
return function() {
|
||||
remote.app.quit();
|
||||
};
|
||||
}
|
||||
|
||||
export function doChangeVolume(volume) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.VOLUME_CHANGED,
|
||||
type: ACTIONS.VOLUME_CHANGED,
|
||||
data: {
|
||||
volume,
|
||||
},
|
||||
|
|
|
@ -1,32 +1,27 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbry from "lbry";
|
||||
import { selectFetchingAvailability } from "redux/selectors/availability";
|
||||
|
||||
export function doFetchAvailability(uri) {
|
||||
return function(dispatch, getState) {
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function doFetchAvailability() {
|
||||
return function() {
|
||||
/*
|
||||
this is disabled atm - Jeremy
|
||||
*/
|
||||
return;
|
||||
|
||||
const state = getState();
|
||||
const alreadyFetching = !!selectFetchingAvailability(state)[uri];
|
||||
|
||||
if (!alreadyFetching) {
|
||||
dispatch({
|
||||
type: types.FETCH_AVAILABILITY_STARTED,
|
||||
data: { uri },
|
||||
});
|
||||
|
||||
lbry.get_availability({ uri }).then(availability => {
|
||||
dispatch({
|
||||
type: types.FETCH_AVAILABILITY_COMPLETED,
|
||||
data: {
|
||||
availability,
|
||||
uri,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
// const state = getState();
|
||||
// const alreadyFetching = !!selectFetchingAvailability(state)[uri];
|
||||
//
|
||||
// if (!alreadyFetching) {
|
||||
// dispatch({
|
||||
// type: ACTIONS.FETCH_AVAILABILITY_STARTED,
|
||||
// data: { uri },
|
||||
// });
|
||||
//
|
||||
// lbry.get_availability({ uri }).then(availability => {
|
||||
// dispatch({
|
||||
// type: ACTIONS.FETCH_AVAILABILITY_COMPLETED,
|
||||
// data: {
|
||||
// availability,
|
||||
// uri,
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,65 +1,63 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as settings from "constants/settings";
|
||||
import lbry from "lbry";
|
||||
import lbryio from "lbryio";
|
||||
import lbryuri from "lbryuri";
|
||||
import { makeSelectClientSetting } from "redux/selectors/settings";
|
||||
import { selectBalance, selectTransactionItems } from "redux/selectors/wallet";
|
||||
import { ipcRenderer } from 'electron';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import Lbry from 'lbry';
|
||||
import Lbryio from 'lbryio';
|
||||
import Lbryuri from 'lbryuri';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { selectBalance, selectTransactionItems } from 'redux/selectors/wallet';
|
||||
import {
|
||||
makeSelectFileInfoForUri,
|
||||
selectDownloadingByOutpoint,
|
||||
} from "redux/selectors/file_info";
|
||||
import { selectResolvingUris } from "redux/selectors/content";
|
||||
import { makeSelectCostInfoForUri } from "redux/selectors/cost_info";
|
||||
import { doAlertError, doOpenModal } from "redux/actions/app";
|
||||
import { doClaimEligiblePurchaseRewards } from "redux/actions/rewards";
|
||||
import { selectBadgeNumber } from "redux/selectors/app";
|
||||
import { selectTotalDownloadProgress } from "redux/selectors/file_info";
|
||||
import setBadge from "util/setBadge";
|
||||
import setProgressBar from "util/setProgressBar";
|
||||
import batchActions from "util/batchActions";
|
||||
import * as modals from "constants/modal_types";
|
||||
|
||||
const { ipcRenderer } = require("electron");
|
||||
selectTotalDownloadProgress,
|
||||
} from 'redux/selectors/file_info';
|
||||
import { selectResolvingUris } from 'redux/selectors/content';
|
||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
||||
import { doAlertError, doOpenModal } from 'redux/actions/app';
|
||||
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
||||
import { selectBadgeNumber } from 'redux/selectors/app';
|
||||
import setBadge from 'util/setBadge';
|
||||
import setProgressBar from 'util/setProgressBar';
|
||||
import batchActions from 'util/batchActions';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
|
||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||
|
||||
export function doResolveUris(uris) {
|
||||
return function(dispatch, getState) {
|
||||
uris = uris.map(lbryuri.normalize);
|
||||
const normalizedUris = uris.map(Lbryuri.normalize);
|
||||
const state = getState();
|
||||
|
||||
// Filter out URIs that are already resolving
|
||||
const resolvingUris = selectResolvingUris(state);
|
||||
const urisToResolve = uris.filter(uri => !resolvingUris.includes(uri));
|
||||
const urisToResolve = normalizedUris.filter(uri => !resolvingUris.includes(uri));
|
||||
|
||||
if (urisToResolve.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.RESOLVE_URIS_STARTED,
|
||||
data: { uris },
|
||||
type: ACTIONS.RESOLVE_URIS_STARTED,
|
||||
data: { uris: normalizedUris },
|
||||
});
|
||||
|
||||
const resolveInfo = {};
|
||||
lbry.resolve({ uris: urisToResolve }).then(result => {
|
||||
for (const [uri, uriResolveInfo] of Object.entries(result)) {
|
||||
Lbry.resolve({ uris: urisToResolve }).then(result => {
|
||||
Object.entries(result).forEach(([uri, uriResolveInfo]) => {
|
||||
const fallbackResolveInfo = {
|
||||
claim: null,
|
||||
claims_in_channel: null,
|
||||
claimsInChannel: null,
|
||||
certificate: null,
|
||||
};
|
||||
|
||||
const { claim, certificate, claims_in_channel } =
|
||||
uriResolveInfo && !uriResolveInfo.error
|
||||
? uriResolveInfo
|
||||
: fallbackResolveInfo;
|
||||
resolveInfo[uri] = { claim, certificate, claims_in_channel };
|
||||
}
|
||||
const { claim, certificate, claims_in_channel: claimsInChannel } =
|
||||
uriResolveInfo && !uriResolveInfo.error ? uriResolveInfo : fallbackResolveInfo;
|
||||
|
||||
resolveInfo[uri] = { claim, certificate, claimsInChannel };
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: types.RESOLVE_URIS_COMPLETED,
|
||||
type: ACTIONS.RESOLVE_URIS_COMPLETED,
|
||||
data: { resolveInfo },
|
||||
});
|
||||
});
|
||||
|
@ -71,23 +69,21 @@ export function doResolveUri(uri) {
|
|||
}
|
||||
|
||||
export function doFetchFeaturedUris() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_FEATURED_CONTENT_STARTED,
|
||||
type: ACTIONS.FETCH_FEATURED_CONTENT_STARTED,
|
||||
});
|
||||
|
||||
const success = ({ Uris }) => {
|
||||
let urisToResolve = [];
|
||||
for (const category in Uris) {
|
||||
Object.keys(Uris).forEach(category => {
|
||||
urisToResolve = [...urisToResolve, ...Uris[category]];
|
||||
}
|
||||
});
|
||||
|
||||
const actions = [
|
||||
doResolveUris(urisToResolve),
|
||||
{
|
||||
type: types.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||
type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||
data: {
|
||||
uris: Uris,
|
||||
success: true,
|
||||
|
@ -99,24 +95,22 @@ export function doFetchFeaturedUris() {
|
|||
|
||||
const failure = () => {
|
||||
dispatch({
|
||||
type: types.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||
type: ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||
data: {
|
||||
uris: {},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
lbryio.call("file", "list_homepage").then(success, failure);
|
||||
Lbryio.call('file', 'list_homepage').then(success, failure);
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchRewardedContent() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
||||
return function(dispatch) {
|
||||
const success = nameToClaimId => {
|
||||
dispatch({
|
||||
type: types.FETCH_REWARD_CONTENT_COMPLETED,
|
||||
type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED,
|
||||
data: {
|
||||
claimIds: Object.values(nameToClaimId),
|
||||
success: true,
|
||||
|
@ -126,7 +120,7 @@ export function doFetchRewardedContent() {
|
|||
|
||||
const failure = () => {
|
||||
dispatch({
|
||||
type: types.FETCH_REWARD_CONTENT_COMPLETED,
|
||||
type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED,
|
||||
data: {
|
||||
claimIds: [],
|
||||
success: false,
|
||||
|
@ -134,73 +128,69 @@ export function doFetchRewardedContent() {
|
|||
});
|
||||
};
|
||||
|
||||
lbryio.call("reward", "list_featured").then(success, failure);
|
||||
Lbryio.call('reward', 'list_featured').then(success, failure);
|
||||
};
|
||||
}
|
||||
|
||||
export function doUpdateLoadStatus(uri, outpoint) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
Lbry.file_list({
|
||||
outpoint,
|
||||
full_status: true,
|
||||
}).then(([fileInfo]) => {
|
||||
if (!fileInfo || fileInfo.written_bytes === 0) {
|
||||
// download hasn't started yet
|
||||
setTimeout(() => {
|
||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||
}, DOWNLOAD_POLL_INTERVAL);
|
||||
} else if (fileInfo.completed) {
|
||||
// TODO this isn't going to get called if they reload the client before
|
||||
// the download finished
|
||||
dispatch({
|
||||
type: ACTIONS.DOWNLOADING_COMPLETED,
|
||||
data: {
|
||||
uri,
|
||||
outpoint,
|
||||
fileInfo,
|
||||
},
|
||||
});
|
||||
|
||||
lbry
|
||||
.file_list({
|
||||
outpoint,
|
||||
full_status: true,
|
||||
})
|
||||
.then(([fileInfo]) => {
|
||||
if (!fileInfo || fileInfo.written_bytes == 0) {
|
||||
// download hasn't started yet
|
||||
setTimeout(() => {
|
||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||
}, DOWNLOAD_POLL_INTERVAL);
|
||||
} else if (fileInfo.completed) {
|
||||
// TODO this isn't going to get called if they reload the client before
|
||||
// the download finished
|
||||
dispatch({
|
||||
type: types.DOWNLOADING_COMPLETED,
|
||||
data: {
|
||||
uri,
|
||||
outpoint,
|
||||
fileInfo,
|
||||
},
|
||||
});
|
||||
const badgeNumber = selectBadgeNumber(getState());
|
||||
setBadge(badgeNumber === 0 ? '' : `${badgeNumber}`);
|
||||
|
||||
const badgeNumber = selectBadgeNumber(getState());
|
||||
setBadge(badgeNumber === 0 ? "" : `${badgeNumber}`);
|
||||
const totalProgress = selectTotalDownloadProgress(getState());
|
||||
setProgressBar(totalProgress);
|
||||
|
||||
const totalProgress = selectTotalDownloadProgress(getState());
|
||||
setProgressBar(totalProgress);
|
||||
const notif = new window.Notification('LBRY Download Complete', {
|
||||
body: fileInfo.metadata.stream.metadata.title,
|
||||
silent: false,
|
||||
});
|
||||
notif.onclick = () => {
|
||||
ipcRenderer.send('focusWindow', 'main');
|
||||
};
|
||||
} else {
|
||||
// ready to play
|
||||
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
||||
const progress = writtenBytes / totalBytes * 100;
|
||||
|
||||
const notif = new window.Notification("LBRY Download Complete", {
|
||||
body: fileInfo.metadata.stream.metadata.title,
|
||||
silent: false,
|
||||
});
|
||||
notif.onclick = () => {
|
||||
ipcRenderer.send("focusWindow", "main");
|
||||
};
|
||||
} else {
|
||||
// ready to play
|
||||
const { total_bytes, written_bytes } = fileInfo;
|
||||
const progress = written_bytes / total_bytes * 100;
|
||||
dispatch({
|
||||
type: ACTIONS.DOWNLOADING_PROGRESSED,
|
||||
data: {
|
||||
uri,
|
||||
outpoint,
|
||||
fileInfo,
|
||||
progress,
|
||||
},
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: types.DOWNLOADING_PROGRESSED,
|
||||
data: {
|
||||
uri,
|
||||
outpoint,
|
||||
fileInfo,
|
||||
progress,
|
||||
},
|
||||
});
|
||||
const totalProgress = selectTotalDownloadProgress(getState());
|
||||
setProgressBar(totalProgress);
|
||||
|
||||
const totalProgress = selectTotalDownloadProgress(getState());
|
||||
setProgressBar(totalProgress);
|
||||
|
||||
setTimeout(() => {
|
||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||
}, DOWNLOAD_POLL_INTERVAL);
|
||||
}
|
||||
});
|
||||
setTimeout(() => {
|
||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||
}, DOWNLOAD_POLL_INTERVAL);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -209,16 +199,16 @@ export function doStartDownload(uri, outpoint) {
|
|||
const state = getState();
|
||||
|
||||
if (!outpoint) {
|
||||
throw new Error("outpoint is required to begin a download");
|
||||
throw new Error('outpoint is required to begin a download');
|
||||
}
|
||||
|
||||
const { downloadingByOutpoint = {} } = state.fileInfo;
|
||||
|
||||
if (downloadingByOutpoint[outpoint]) return;
|
||||
|
||||
lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => {
|
||||
Lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => {
|
||||
dispatch({
|
||||
type: types.DOWNLOADING_STARTED,
|
||||
type: ACTIONS.DOWNLOADING_STARTED,
|
||||
data: {
|
||||
uri,
|
||||
outpoint,
|
||||
|
@ -232,50 +222,50 @@ export function doStartDownload(uri, outpoint) {
|
|||
}
|
||||
|
||||
export function doDownloadFile(uri, streamInfo) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
||||
return function(dispatch) {
|
||||
dispatch(doStartDownload(uri, streamInfo.outpoint));
|
||||
|
||||
lbryio
|
||||
.call("file", "view", {
|
||||
uri,
|
||||
outpoint: streamInfo.outpoint,
|
||||
claim_id: streamInfo.claim_id,
|
||||
})
|
||||
.catch(() => {});
|
||||
Lbryio.call('file', 'view', {
|
||||
uri,
|
||||
outpoint: streamInfo.outpoint,
|
||||
claim_id: streamInfo.claim_id,
|
||||
}).catch(() => {});
|
||||
|
||||
dispatch(doClaimEligiblePurchaseRewards());
|
||||
};
|
||||
}
|
||||
|
||||
export function doLoadVideo(uri) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
||||
export function doSetPlayingUri(uri) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.LOADING_VIDEO_STARTED,
|
||||
type: ACTIONS.SET_PLAYING_URI,
|
||||
data: { uri },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doLoadVideo(uri) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: ACTIONS.LOADING_VIDEO_STARTED,
|
||||
data: {
|
||||
uri,
|
||||
},
|
||||
});
|
||||
|
||||
lbry
|
||||
.get({ uri })
|
||||
Lbry.get({ uri })
|
||||
.then(streamInfo => {
|
||||
const timeout =
|
||||
streamInfo === null ||
|
||||
typeof streamInfo !== "object" ||
|
||||
streamInfo.error == "Timeout";
|
||||
streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
|
||||
|
||||
if (timeout) {
|
||||
dispatch(doSetPlayingUri(null));
|
||||
dispatch({
|
||||
type: types.LOADING_VIDEO_FAILED,
|
||||
type: ACTIONS.LOADING_VIDEO_FAILED,
|
||||
data: { uri },
|
||||
});
|
||||
|
||||
dispatch(doOpenModal(modals.FILE_TIMEOUT, { uri }));
|
||||
dispatch(doOpenModal(MODALS.FILE_TIMEOUT, { uri }));
|
||||
} else {
|
||||
dispatch(doDownloadFile(uri, streamInfo));
|
||||
}
|
||||
|
@ -283,7 +273,7 @@ export function doLoadVideo(uri) {
|
|||
.catch(() => {
|
||||
dispatch(doSetPlayingUri(null));
|
||||
dispatch({
|
||||
type: types.LOADING_VIDEO_FAILED,
|
||||
type: ACTIONS.LOADING_VIDEO_FAILED,
|
||||
data: { uri },
|
||||
});
|
||||
dispatch(
|
||||
|
@ -303,12 +293,11 @@ export function doPurchaseUri(uri) {
|
|||
const balance = selectBalance(state);
|
||||
const fileInfo = makeSelectFileInfoForUri(uri)(state);
|
||||
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
|
||||
const alreadyDownloading =
|
||||
fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
|
||||
const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
|
||||
|
||||
function attemptPlay(cost, instantPurchaseMax = null) {
|
||||
if (cost > 0 && (!instantPurchaseMax || cost > instantPurchaseMax)) {
|
||||
dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri }));
|
||||
dispatch(doOpenModal(MODALS.AFFIRM_PURCHASE, { uri }));
|
||||
} else {
|
||||
dispatch(doLoadVideo(uri));
|
||||
}
|
||||
|
@ -321,12 +310,14 @@ export function doPurchaseUri(uri) {
|
|||
// doLoadVideo action to reconstruct the file from the blobs
|
||||
if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri));
|
||||
|
||||
return Promise.resolve();
|
||||
Promise.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// we are already downloading the file
|
||||
if (alreadyDownloading) {
|
||||
return Promise.resolve();
|
||||
Promise.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
const costInfo = makeSelectCostInfoForUri(uri)(state);
|
||||
|
@ -334,25 +325,21 @@ export function doPurchaseUri(uri) {
|
|||
|
||||
if (cost > balance) {
|
||||
dispatch(doSetPlayingUri(null));
|
||||
dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
|
||||
return Promise.resolve();
|
||||
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||
Promise.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
cost == 0 ||
|
||||
!makeSelectClientSetting(settings.INSTANT_PURCHASE_ENABLED)(state)
|
||||
) {
|
||||
if (cost === 0 || !makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED)(state)) {
|
||||
attemptPlay(cost);
|
||||
} else {
|
||||
const instantPurchaseMax = makeSelectClientSetting(
|
||||
settings.INSTANT_PURCHASE_MAX
|
||||
)(state);
|
||||
if (instantPurchaseMax.currency == "LBC") {
|
||||
const instantPurchaseMax = makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_MAX)(state);
|
||||
if (instantPurchaseMax.currency === 'LBC') {
|
||||
attemptPlay(cost, instantPurchaseMax.amount);
|
||||
} else {
|
||||
// Need to convert currency of instant purchase maximum before trying to play
|
||||
lbryio.getExchangeRates().then(({ lbc_usd }) => {
|
||||
attemptPlay(cost, instantPurchaseMax.amount / lbc_usd);
|
||||
Lbryio.getExchangeRates().then(({ LBC_USD }) => {
|
||||
attemptPlay(cost, instantPurchaseMax.amount / LBC_USD);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -360,22 +347,22 @@ export function doPurchaseUri(uri) {
|
|||
}
|
||||
|
||||
export function doFetchClaimsByChannel(uri, page) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_CHANNEL_CLAIMS_STARTED,
|
||||
type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED,
|
||||
data: { uri, page },
|
||||
});
|
||||
|
||||
lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => {
|
||||
Lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => {
|
||||
const claimResult = result[uri] || {};
|
||||
const { claims_in_channel, returned_page } = claimResult;
|
||||
const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult;
|
||||
|
||||
dispatch({
|
||||
type: types.FETCH_CHANNEL_CLAIMS_COMPLETED,
|
||||
type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED,
|
||||
data: {
|
||||
uri,
|
||||
claims: claims_in_channel || [],
|
||||
page: returned_page || undefined,
|
||||
claims: claimsInChannel || [],
|
||||
page: returnedPage || undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -383,18 +370,18 @@ export function doFetchClaimsByChannel(uri, page) {
|
|||
}
|
||||
|
||||
export function doFetchClaimCountByChannel(uri) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_CHANNEL_CLAIM_COUNT_STARTED,
|
||||
type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_STARTED,
|
||||
data: { uri },
|
||||
});
|
||||
|
||||
lbry.claim_list_by_channel({ uri }).then(result => {
|
||||
const claimResult = result[uri],
|
||||
totalClaims = claimResult ? claimResult.claims_in_channel : 0;
|
||||
Lbry.claim_list_by_channel({ uri }).then(result => {
|
||||
const claimResult = result[uri];
|
||||
const totalClaims = claimResult ? claimResult.claims_in_channel : 0;
|
||||
|
||||
dispatch({
|
||||
type: types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED,
|
||||
type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED,
|
||||
data: {
|
||||
uri,
|
||||
totalClaims,
|
||||
|
@ -405,14 +392,14 @@ export function doFetchClaimCountByChannel(uri) {
|
|||
}
|
||||
|
||||
export function doFetchClaimListMine() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_CLAIM_LIST_MINE_STARTED,
|
||||
type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED,
|
||||
});
|
||||
|
||||
lbry.claim_list_mine().then(claims => {
|
||||
Lbry.claim_list_mine().then(claims => {
|
||||
dispatch({
|
||||
type: types.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
||||
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
||||
data: {
|
||||
claims,
|
||||
},
|
||||
|
@ -422,69 +409,59 @@ export function doFetchClaimListMine() {
|
|||
}
|
||||
|
||||
export function doPlayUri(uri) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch(doSetPlayingUri(uri));
|
||||
dispatch(doPurchaseUri(uri));
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetPlayingUri(uri) {
|
||||
return function(dispatch, getState) {
|
||||
dispatch({
|
||||
type: types.SET_PLAYING_URI,
|
||||
data: { uri },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchChannelListMine() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_CHANNEL_LIST_MINE_STARTED,
|
||||
type: ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED,
|
||||
});
|
||||
|
||||
const callback = channels => {
|
||||
dispatch({
|
||||
type: types.FETCH_CHANNEL_LIST_MINE_COMPLETED,
|
||||
type: ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED,
|
||||
data: { claims: channels },
|
||||
});
|
||||
};
|
||||
|
||||
lbry.channel_list_mine().then(callback);
|
||||
Lbry.channel_list_mine().then(callback);
|
||||
};
|
||||
}
|
||||
|
||||
export function doCreateChannel(name, amount) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.CREATE_CHANNEL_STARTED,
|
||||
type: ACTIONS.CREATE_CHANNEL_STARTED,
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
lbry
|
||||
.channel_new({
|
||||
channel_name: name,
|
||||
amount: parseFloat(amount),
|
||||
})
|
||||
.then(
|
||||
channelClaim => {
|
||||
channelClaim.name = name;
|
||||
dispatch({
|
||||
type: types.CREATE_CHANNEL_COMPLETED,
|
||||
data: { channelClaim },
|
||||
});
|
||||
resolve(channelClaim);
|
||||
},
|
||||
err => {
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
Lbry.channel_new({
|
||||
channel_name: name,
|
||||
amount: parseFloat(amount),
|
||||
}).then(
|
||||
channelClaim => {
|
||||
const newChannelClaim = channelClaim;
|
||||
newChannelClaim.name = name;
|
||||
dispatch({
|
||||
type: ACTIONS.CREATE_CHANNEL_COMPLETED,
|
||||
data: { newChannelClaim },
|
||||
});
|
||||
resolve(newChannelClaim);
|
||||
},
|
||||
error => {
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doPublish(params) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const success = claim => {
|
||||
resolve(claim);
|
||||
|
@ -497,7 +474,7 @@ export function doPublish(params) {
|
|||
};
|
||||
const failure = err => reject(err);
|
||||
|
||||
lbry.publishDeprecated(params, null, success, failure);
|
||||
Lbry.publishDeprecated(params, null, success, failure);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -507,40 +484,38 @@ export function doAbandonClaim(txid, nout) {
|
|||
const state = getState();
|
||||
const transactionItems = selectTransactionItems(state);
|
||||
const { claim_id: claimId, claim_name: name } = transactionItems.find(
|
||||
claim => claim.txid == txid && claim.nout == nout
|
||||
claim => claim.txid === txid && claim.nout === nout
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: types.ABANDON_CLAIM_STARTED,
|
||||
type: ACTIONS.ABANDON_CLAIM_STARTED,
|
||||
data: {
|
||||
claimId,
|
||||
},
|
||||
});
|
||||
|
||||
const errorCallback = error => {
|
||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||
const errorCallback = () => {
|
||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||
};
|
||||
|
||||
const successCallback = results => {
|
||||
if (results.txid) {
|
||||
dispatch({
|
||||
type: types.ABANDON_CLAIM_SUCCEEDED,
|
||||
type: ACTIONS.ABANDON_CLAIM_SUCCEEDED,
|
||||
data: {
|
||||
claimId,
|
||||
},
|
||||
});
|
||||
dispatch(doResolveUri(lbryuri.build({ name, claimId })));
|
||||
dispatch(doResolveUri(Lbryuri.build({ name, claimId })));
|
||||
dispatch(doFetchClaimListMine());
|
||||
} else {
|
||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||
}
|
||||
};
|
||||
|
||||
lbry
|
||||
.claim_abandon({
|
||||
txid,
|
||||
nout,
|
||||
})
|
||||
.then(successCallback, errorCallback);
|
||||
Lbry.claim_abandon({
|
||||
txid,
|
||||
nout,
|
||||
}).then(successCallback, errorCallback);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,31 +1,18 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbry from "lbry";
|
||||
import lbryio from "lbryio";
|
||||
import { doResolveUri } from "redux/actions/content";
|
||||
import { selectResolvingUris } from "redux/selectors/content";
|
||||
import { selectClaimsByUri } from "redux/selectors/claims";
|
||||
import { selectSettingsIsGenerous } from "redux/selectors/settings";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbryio from 'lbryio';
|
||||
import { selectClaimsByUri } from 'redux/selectors/claims';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function doFetchCostInfoForUri(uri) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState(),
|
||||
claim = selectClaimsByUri(state)[uri],
|
||||
isGenerous = selectSettingsIsGenerous(state);
|
||||
const state = getState();
|
||||
const claim = selectClaimsByUri(state)[uri];
|
||||
|
||||
if (!claim) return null;
|
||||
|
||||
function begin() {
|
||||
dispatch({
|
||||
type: types.FETCH_COST_INFO_STARTED,
|
||||
data: {
|
||||
uri,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!claim) return;
|
||||
|
||||
function resolve(costInfo) {
|
||||
dispatch({
|
||||
type: types.FETCH_COST_INFO_COMPLETED,
|
||||
type: ACTIONS.FETCH_COST_INFO_COMPLETED,
|
||||
data: {
|
||||
uri,
|
||||
costInfo,
|
||||
|
@ -33,18 +20,6 @@ export function doFetchCostInfoForUri(uri) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* "Generous" check below is disabled. We're no longer attempting to include or estimate data fees regardless of settings.
|
||||
*
|
||||
* This should be modified when lbry.stream_cost_estimate is reliable and performant.
|
||||
*/
|
||||
|
||||
/*
|
||||
lbry.stream_cost_estimate({ uri }).then(cost => {
|
||||
cacheAndResolve(cost);
|
||||
}, reject);
|
||||
*/
|
||||
|
||||
const fee =
|
||||
claim.value && claim.value.stream && claim.value.stream.metadata
|
||||
? claim.value.stream.metadata.fee
|
||||
|
@ -52,35 +27,12 @@ export function doFetchCostInfoForUri(uri) {
|
|||
|
||||
if (fee === undefined) {
|
||||
resolve({ cost: 0, includesData: true });
|
||||
} else if (fee.currency == "LBC") {
|
||||
} else if (fee.currency === 'LBC') {
|
||||
resolve({ cost: fee.amount, includesData: true });
|
||||
} else {
|
||||
// begin();
|
||||
lbryio.getExchangeRates().then(({ lbc_usd }) => {
|
||||
resolve({ cost: fee.amount / lbc_usd, includesData: true });
|
||||
Lbryio.getExchangeRates().then(({ LBC_USD }) => {
|
||||
resolve({ cost: fee.amount / LBC_USD, includesData: true });
|
||||
});
|
||||
}
|
||||
|
||||
// if (isGenerous && claim) {
|
||||
// let cost;
|
||||
// const fee = claim.value &&
|
||||
// claim.value.stream &&
|
||||
// claim.value.stream.metadata
|
||||
// ? claim.value.stream.metadata.fee
|
||||
// : undefined;
|
||||
// if (fee === undefined) {
|
||||
// resolve({ cost: 0, includesData: true });
|
||||
// } else if (fee.currency == "LBC") {
|
||||
// resolve({ cost: fee.amount, includesData: true });
|
||||
// } else {
|
||||
// // begin();
|
||||
// lbryio.getExchangeRates().then(({ lbc_usd }) => {
|
||||
// resolve({ cost: fee.amount / lbc_usd, includesData: true });
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// begin();
|
||||
// lbry.getCostInfo(uri).then(resolve);
|
||||
// }
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbry from "lbry";
|
||||
import { doFetchClaimListMine, doAbandonClaim } from "redux/actions/content";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbry from 'lbry';
|
||||
import { doFetchClaimListMine, doAbandonClaim } from 'redux/actions/content';
|
||||
import {
|
||||
selectClaimsByUri,
|
||||
selectIsFetchingClaimListMine,
|
||||
selectMyClaimsOutpoints,
|
||||
} from "redux/selectors/claims";
|
||||
} from 'redux/selectors/claims';
|
||||
import {
|
||||
selectIsFetchingFileList,
|
||||
selectFileInfosByOutpoint,
|
||||
selectUrisLoading,
|
||||
selectTotalDownloadProgress,
|
||||
} from "redux/selectors/file_info";
|
||||
import { doCloseModal } from "redux/actions/app";
|
||||
import { doNavigate, doHistoryBack } from "redux/actions/navigation";
|
||||
import setProgressBar from "util/setProgressBar";
|
||||
import batchActions from "util/batchActions";
|
||||
|
||||
const { shell } = require("electron");
|
||||
} from 'redux/selectors/file_info';
|
||||
import { doCloseModal } from 'redux/actions/app';
|
||||
import { doHistoryBack } from 'redux/actions/navigation';
|
||||
import setProgressBar from 'util/setProgressBar';
|
||||
import batchActions from 'util/batchActions';
|
||||
import { shell } from 'electron';
|
||||
|
||||
export function doFetchFileInfo(uri) {
|
||||
return function(dispatch, getState) {
|
||||
|
@ -28,15 +27,15 @@ export function doFetchFileInfo(uri) {
|
|||
|
||||
if (!alreadyFetching) {
|
||||
dispatch({
|
||||
type: types.FETCH_FILE_INFO_STARTED,
|
||||
type: ACTIONS.FETCH_FILE_INFO_STARTED,
|
||||
data: {
|
||||
outpoint,
|
||||
},
|
||||
});
|
||||
|
||||
lbry.file_list({ outpoint, full_status: true }).then(fileInfos => {
|
||||
Lbry.file_list({ outpoint, full_status: true }).then(fileInfos => {
|
||||
dispatch({
|
||||
type: types.FETCH_FILE_INFO_COMPLETED,
|
||||
type: ACTIONS.FETCH_FILE_INFO_COMPLETED,
|
||||
data: {
|
||||
outpoint,
|
||||
fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null,
|
||||
|
@ -54,12 +53,12 @@ export function doFileList() {
|
|||
|
||||
if (!isFetching) {
|
||||
dispatch({
|
||||
type: types.FILE_LIST_STARTED,
|
||||
type: ACTIONS.FILE_LIST_STARTED,
|
||||
});
|
||||
|
||||
lbry.file_list().then(fileInfos => {
|
||||
Lbry.file_list().then(fileInfos => {
|
||||
dispatch({
|
||||
type: types.FILE_LIST_SUCCEEDED,
|
||||
type: ACTIONS.FILE_LIST_SUCCEEDED,
|
||||
data: {
|
||||
fileInfos,
|
||||
},
|
||||
|
@ -69,8 +68,14 @@ export function doFileList() {
|
|||
};
|
||||
}
|
||||
|
||||
export function doOpenFileInFolder(path) {
|
||||
return function() {
|
||||
shell.showItemInFolder(path);
|
||||
};
|
||||
}
|
||||
|
||||
export function doOpenFileInShell(path) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
const success = shell.openItem(path);
|
||||
if (!success) {
|
||||
dispatch(doOpenFileInFolder(path));
|
||||
|
@ -78,17 +83,11 @@ export function doOpenFileInShell(path) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doOpenFileInFolder(path) {
|
||||
return function(dispatch, getState) {
|
||||
shell.showItemInFolder(path);
|
||||
};
|
||||
}
|
||||
|
||||
export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
||||
lbry.file_delete({
|
||||
Lbry.file_delete({
|
||||
outpoint,
|
||||
delete_from_download_dir: deleteFromComputer,
|
||||
});
|
||||
|
@ -108,7 +107,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
|||
}
|
||||
|
||||
dispatch({
|
||||
type: types.FILE_DELETE,
|
||||
type: ACTIONS.FILE_DELETE,
|
||||
data: {
|
||||
outpoint,
|
||||
},
|
||||
|
@ -119,12 +118,8 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doDeleteFileAndGoBack(
|
||||
fileInfo,
|
||||
deleteFromComputer,
|
||||
abandonClaim
|
||||
) {
|
||||
return function(dispatch, getState) {
|
||||
export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim) {
|
||||
return function(dispatch) {
|
||||
const actions = [];
|
||||
actions.push(doCloseModal());
|
||||
actions.push(doHistoryBack());
|
||||
|
@ -135,9 +130,9 @@ export function doDeleteFileAndGoBack(
|
|||
|
||||
export function doFetchFileInfosAndPublishedClaims() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState(),
|
||||
isFetchingClaimListMine = selectIsFetchingClaimListMine(state),
|
||||
isFetchingFileInfo = selectIsFetchingFileList(state);
|
||||
const state = getState();
|
||||
const isFetchingClaimListMine = selectIsFetchingClaimListMine(state);
|
||||
const isFetchingFileInfo = selectIsFetchingFileList(state);
|
||||
|
||||
if (!isFetchingClaimListMine) dispatch(doFetchClaimListMine());
|
||||
if (!isFetchingFileInfo) dispatch(doFileList());
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
import * as types from "constants/action_types";
|
||||
import {
|
||||
computePageFromPath,
|
||||
selectPageTitle,
|
||||
selectCurrentPage,
|
||||
selectCurrentParams,
|
||||
selectHistoryStack,
|
||||
selectHistoryIndex,
|
||||
} from "redux/selectors/navigation";
|
||||
import { doSearch } from "redux/actions/search";
|
||||
import { toQueryString } from "util/query_params";
|
||||
import amplitude from "amplitude-js";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import { selectHistoryStack, selectHistoryIndex } from 'redux/selectors/navigation';
|
||||
import { toQueryString } from 'util/query_params';
|
||||
import amplitude from 'amplitude-js';
|
||||
|
||||
export function doNavigate(path, params = {}, options = {}) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
@ -22,40 +14,38 @@ export function doNavigate(path, params = {}, options = {}) {
|
|||
url += `?${toQueryString(params)}`;
|
||||
}
|
||||
|
||||
const scrollY = options.scrollY;
|
||||
const { scrollY } = options;
|
||||
|
||||
amplitude.getInstance().logEvent("NAVIGATION", { destination: url });
|
||||
amplitude.getInstance().logEvent('NAVIGATION', { destination: url });
|
||||
|
||||
dispatch({
|
||||
type: types.HISTORY_NAVIGATE,
|
||||
type: ACTIONS.HISTORY_NAVIGATE,
|
||||
data: { url, index: options.index, scrollY },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doAuthNavigate(pathAfterAuth = null, params = {}) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
if (pathAfterAuth) {
|
||||
dispatch({
|
||||
type: types.CHANGE_AFTER_AUTH_PATH,
|
||||
type: ACTIONS.CHANGE_AFTER_AUTH_PATH,
|
||||
data: {
|
||||
path: `${pathAfterAuth}?${toQueryString(params)}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
dispatch(doNavigate("/auth"));
|
||||
dispatch(doNavigate('/auth'));
|
||||
};
|
||||
}
|
||||
|
||||
export function doHistoryTraverse(dispatch, state, modifier) {
|
||||
const stack = selectHistoryStack(state),
|
||||
index = selectHistoryIndex(state) + modifier;
|
||||
const stack = selectHistoryStack(state);
|
||||
const index = selectHistoryIndex(state) + modifier;
|
||||
|
||||
if (index >= 0 && index < stack.length) {
|
||||
const historyItem = stack[index];
|
||||
return dispatch(
|
||||
doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index })
|
||||
);
|
||||
dispatch(doNavigate(historyItem.path, {}, { scrollY: historyItem.scrollY, index }));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,9 +62,9 @@ export function doHistoryForward() {
|
|||
}
|
||||
|
||||
export function doRecordScroll(scroll) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.WINDOW_SCROLLED,
|
||||
type: ACTIONS.WINDOW_SCROLLED,
|
||||
data: { scrollY: scroll },
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,30 +1,26 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as modals from "constants/modal_types";
|
||||
import lbryio from "lbryio";
|
||||
import rewards from "rewards";
|
||||
import { selectUnclaimedRewardsByType } from "redux/selectors/rewards";
|
||||
import { selectUserIsRewardApproved } from "redux/selectors/user";
|
||||
import { selectClaimedRewardsById } from "../selectors/rewards";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import Lbryio from 'lbryio';
|
||||
import rewards from 'rewards';
|
||||
import { selectUnclaimedRewardsByType } from 'redux/selectors/rewards';
|
||||
import { selectUserIsRewardApproved } from 'redux/selectors/user';
|
||||
|
||||
export function doRewardList() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_REWARDS_STARTED,
|
||||
type: ACTIONS.FETCH_REWARDS_STARTED,
|
||||
});
|
||||
|
||||
lbryio
|
||||
.call("reward", "list", { multiple_rewards_per_type: true })
|
||||
Lbryio.call('reward', 'list', { multiple_rewards_per_type: true })
|
||||
.then(userRewards => {
|
||||
dispatch({
|
||||
type: types.FETCH_REWARDS_COMPLETED,
|
||||
type: ACTIONS.FETCH_REWARDS_COMPLETED,
|
||||
data: { userRewards },
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch({
|
||||
type: types.FETCH_REWARDS_COMPLETED,
|
||||
type: ACTIONS.FETCH_REWARDS_COMPLETED,
|
||||
data: { userRewards: [] },
|
||||
});
|
||||
});
|
||||
|
@ -33,10 +29,10 @@ export function doRewardList() {
|
|||
|
||||
export function doClaimRewardType(rewardType) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState(),
|
||||
rewardsByType = selectUnclaimedRewardsByType(state),
|
||||
reward = rewardsByType[rewardType],
|
||||
userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||
const state = getState();
|
||||
const rewardsByType = selectUnclaimedRewardsByType(state);
|
||||
const reward = rewardsByType[rewardType];
|
||||
const userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||
|
||||
if (!reward || reward.transaction_id) {
|
||||
// already claimed or doesn't exist, do nothing
|
||||
|
@ -44,35 +40,37 @@ export function doClaimRewardType(rewardType) {
|
|||
}
|
||||
|
||||
if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) {
|
||||
return dispatch({
|
||||
type: types.OPEN_MODAL,
|
||||
data: { modal: modals.REWARD_APPROVAL_REQUIRED },
|
||||
dispatch({
|
||||
type: ACTIONS.OPEN_MODAL,
|
||||
data: { modal: MODALS.REWARD_APPROVAL_REQUIRED },
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.CLAIM_REWARD_STARTED,
|
||||
type: ACTIONS.CLAIM_REWARD_STARTED,
|
||||
data: { reward },
|
||||
});
|
||||
|
||||
const success = reward => {
|
||||
const success = successReward => {
|
||||
dispatch({
|
||||
type: types.CLAIM_REWARD_SUCCESS,
|
||||
type: ACTIONS.CLAIM_REWARD_SUCCESS,
|
||||
data: {
|
||||
reward,
|
||||
reward: successReward,
|
||||
},
|
||||
});
|
||||
if (reward.reward_type == rewards.TYPE_CONFIRM_EMAIL) {
|
||||
if (successReward.reward_type === rewards.TYPE_CONFIRM_EMAIL) {
|
||||
dispatch({
|
||||
type: types.OPEN_MODAL,
|
||||
data: { modal: modals.FIRST_REWARD },
|
||||
type: ACTIONS.OPEN_MODAL,
|
||||
data: { modal: MODALS.FIRST_REWARD },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const failure = error => {
|
||||
dispatch({
|
||||
type: types.CLAIM_REWARD_FAILURE,
|
||||
type: ACTIONS.CLAIM_REWARD_FAILURE,
|
||||
data: { reward, error },
|
||||
});
|
||||
};
|
||||
|
@ -83,30 +81,28 @@ export function doClaimRewardType(rewardType) {
|
|||
|
||||
export function doClaimEligiblePurchaseRewards() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState(),
|
||||
rewardsByType = selectUnclaimedRewardsByType(state),
|
||||
userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||
const state = getState();
|
||||
const rewardsByType = selectUnclaimedRewardsByType(state);
|
||||
const userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||
|
||||
if (!userIsRewardApproved || !lbryio.enabled) {
|
||||
if (!userIsRewardApproved || !Lbryio.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rewardsByType[rewards.TYPE_FIRST_STREAM]) {
|
||||
dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
|
||||
} else {
|
||||
[rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(
|
||||
type => {
|
||||
dispatch(doClaimRewardType(type));
|
||||
}
|
||||
);
|
||||
[rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => {
|
||||
dispatch(doClaimRewardType(type));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function doClaimRewardClearError(reward) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.CLAIM_REWARD_CLEAR_ERROR,
|
||||
type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR,
|
||||
data: { reward },
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,30 +1,32 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbryuri from "lbryuri";
|
||||
import { doResolveUri } from "redux/actions/content";
|
||||
import { doNavigate } from "redux/actions/navigation";
|
||||
import { selectCurrentPage } from "redux/selectors/navigation";
|
||||
import batchActions from "util/batchActions";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbryuri from 'lbryuri';
|
||||
import { doResolveUri } from 'redux/actions/content';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { selectCurrentPage } from 'redux/selectors/navigation';
|
||||
import batchActions from 'util/batchActions';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function doSearch(rawQuery) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
const page = selectCurrentPage(state);
|
||||
|
||||
const query = rawQuery.replace(/^lbry:\/\//i, "");
|
||||
const query = rawQuery.replace(/^lbry:\/\//i, '');
|
||||
|
||||
if (!query) {
|
||||
return dispatch({
|
||||
type: types.SEARCH_CANCELLED,
|
||||
dispatch({
|
||||
type: ACTIONS.SEARCH_CANCELLED,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.SEARCH_STARTED,
|
||||
type: ACTIONS.SEARCH_STARTED,
|
||||
data: { query },
|
||||
});
|
||||
|
||||
if (page != "search") {
|
||||
dispatch(doNavigate("search", { query }));
|
||||
if (page !== 'search') {
|
||||
dispatch(doNavigate('search', { query }));
|
||||
} else {
|
||||
fetch(`https://lighthouse.lbry.io/search?s=${query}`)
|
||||
.then(
|
||||
|
@ -38,7 +40,7 @@ export function doSearch(rawQuery) {
|
|||
const actions = [];
|
||||
|
||||
data.forEach(result => {
|
||||
const uri = lbryuri.build({
|
||||
const uri = Lbryuri.build({
|
||||
name: result.name,
|
||||
claimId: result.claimId,
|
||||
});
|
||||
|
@ -47,7 +49,7 @@ export function doSearch(rawQuery) {
|
|||
});
|
||||
|
||||
actions.push({
|
||||
type: types.SEARCH_COMPLETED,
|
||||
type: ACTIONS.SEARCH_COMPLETED,
|
||||
data: {
|
||||
query,
|
||||
uris,
|
||||
|
@ -55,9 +57,9 @@ export function doSearch(rawQuery) {
|
|||
});
|
||||
dispatch(batchActions(...actions));
|
||||
})
|
||||
.catch(err => {
|
||||
.catch(() => {
|
||||
dispatch({
|
||||
type: types.SEARCH_CANCELLED,
|
||||
type: ACTIONS.SEARCH_CANCELLED,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as settings from "constants/settings";
|
||||
import { doAlertError } from "redux/actions/app";
|
||||
import batchActions from "util/batchActions";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
|
||||
import lbry from "lbry";
|
||||
import fs from "fs";
|
||||
import http from "http";
|
||||
import Lbry from 'lbry';
|
||||
import Fs from 'fs';
|
||||
import Http from 'http';
|
||||
|
||||
export function doFetchDaemonSettings() {
|
||||
return function(dispatch, getState) {
|
||||
lbry.settings_get().then(settings => {
|
||||
return function(dispatch) {
|
||||
Lbry.settings_get().then(settings => {
|
||||
dispatch({
|
||||
type: types.DAEMON_SETTINGS_RECEIVED,
|
||||
type: ACTIONS.DAEMON_SETTINGS_RECEIVED,
|
||||
data: {
|
||||
settings,
|
||||
},
|
||||
|
@ -21,15 +19,15 @@ export function doFetchDaemonSettings() {
|
|||
}
|
||||
|
||||
export function doSetDaemonSetting(key, value) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
const settings = {};
|
||||
settings[key] = value;
|
||||
lbry.settings_set(settings).then(settings);
|
||||
lbry.settings_get().then(settings => {
|
||||
Lbry.settings_set(settings).then(settings);
|
||||
Lbry.settings_get().then(remoteSettings => {
|
||||
dispatch({
|
||||
type: types.DAEMON_SETTINGS_RECEIVED,
|
||||
type: ACTIONS.DAEMON_SETTINGS_RECEIVED,
|
||||
data: {
|
||||
settings,
|
||||
remoteSettings,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -38,7 +36,7 @@ export function doSetDaemonSetting(key, value) {
|
|||
|
||||
export function doSetClientSetting(key, value) {
|
||||
return {
|
||||
type: types.CLIENT_SETTING_CHANGED,
|
||||
type: ACTIONS.CLIENT_SETTING_CHANGED,
|
||||
data: {
|
||||
key,
|
||||
value,
|
||||
|
@ -47,100 +45,98 @@ export function doSetClientSetting(key, value) {
|
|||
}
|
||||
|
||||
export function doGetThemes() {
|
||||
return function(dispatch, getState) {
|
||||
const themes = ["light", "dark"];
|
||||
dispatch(doSetClientSetting(settings.THEMES, themes));
|
||||
return function(dispatch) {
|
||||
const themes = ['light', 'dark'];
|
||||
dispatch(doSetClientSetting(SETTINGS.THEMES, themes));
|
||||
};
|
||||
}
|
||||
|
||||
export function doDownloadLanguage(langFile) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
const destinationPath = `${app.i18n.directory}/${langFile}`;
|
||||
const language = langFile.replace(".json", "");
|
||||
const req = http.get(
|
||||
const language = langFile.replace('.json', '');
|
||||
const errorHandler = () => {
|
||||
Fs.unlink(destinationPath, () => {}); // Delete the file async. (But we don't check the result)
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.DOWNLOAD_LANGUAGE_FAILED,
|
||||
data: { language },
|
||||
});
|
||||
};
|
||||
|
||||
const req = Http.get(
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "text/html",
|
||||
'Content-Type': 'text/html',
|
||||
},
|
||||
host: "i18n.lbry.io",
|
||||
host: 'i18n.lbry.io',
|
||||
path: `/langs/${langFile}`,
|
||||
},
|
||||
response => {
|
||||
if (response.statusCode === 200) {
|
||||
const file = fs.createWriteStream(destinationPath);
|
||||
const file = Fs.createWriteStream(destinationPath);
|
||||
|
||||
file.on("error", errorHandler);
|
||||
file.on("finish", () => {
|
||||
file.on('error', errorHandler);
|
||||
file.on('finish', () => {
|
||||
file.close();
|
||||
|
||||
// push to our local list
|
||||
dispatch({
|
||||
type: types.DOWNLOAD_LANGUAGE_SUCCEEDED,
|
||||
type: ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED,
|
||||
data: { language },
|
||||
});
|
||||
});
|
||||
|
||||
response.pipe(file);
|
||||
} else {
|
||||
errorHandler(new Error("Language request failed."));
|
||||
errorHandler(new Error('Language request failed.'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const errorHandler = err => {
|
||||
fs.unlink(destinationPath, () => {}); // Delete the file async. (But we don't check the result)
|
||||
|
||||
dispatch({
|
||||
type: types.DOWNLOAD_LANGUAGE_FAILED,
|
||||
data: { language },
|
||||
});
|
||||
};
|
||||
|
||||
req.setTimeout(30000, () => {
|
||||
req.abort();
|
||||
});
|
||||
|
||||
req.on("error", errorHandler);
|
||||
req.on('error', errorHandler);
|
||||
|
||||
req.end();
|
||||
};
|
||||
}
|
||||
|
||||
export function doDownloadLanguages() {
|
||||
return function(dispatch, getState) {
|
||||
return function() {
|
||||
// temporarily disable i18n so I can get a working build out -- Jeremy
|
||||
return;
|
||||
|
||||
if (!fs.existsSync(app.i18n.directory)) {
|
||||
fs.mkdirSync(app.i18n.directory);
|
||||
}
|
||||
|
||||
function checkStatus(response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response;
|
||||
}
|
||||
throw new Error(
|
||||
__("The list of available languages could not be retrieved.")
|
||||
);
|
||||
}
|
||||
|
||||
function parseJSON(response) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
return fetch("http://i18n.lbry.io")
|
||||
.then(checkStatus)
|
||||
.then(parseJSON)
|
||||
.then(files => {
|
||||
const actions = files.map(doDownloadLanguage);
|
||||
dispatch(batchActions(...actions));
|
||||
});
|
||||
// if (!Fs.existsSync(app.i18n.directory)) {
|
||||
// Fs.mkdirSync(app.i18n.directory);
|
||||
// }
|
||||
//
|
||||
// function checkStatus(response) {
|
||||
// if (response.status >= 200 && response.status < 300) {
|
||||
// return response;
|
||||
// }
|
||||
// throw new Error(
|
||||
// __("The list of available languages could not be retrieved.")
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// function parseJSON(response) {
|
||||
// return response.json();
|
||||
// }
|
||||
//
|
||||
// return fetch("http://i18n.lbry.io")
|
||||
// .then(checkStatus)
|
||||
// .then(parseJSON)
|
||||
// .then(files => {
|
||||
// const actions = files.map(doDownloadLanguage);
|
||||
// dispatch(batchActions(...actions));
|
||||
// });
|
||||
};
|
||||
}
|
||||
|
||||
export function doChangeLanguage(language) {
|
||||
return function(dispatch, getState) {
|
||||
dispatch(doSetClientSetting(settings.LANGUAGE, language));
|
||||
return function(dispatch) {
|
||||
dispatch(doSetClientSetting(SETTINGS.LANGUAGE, language));
|
||||
app.i18n.setLocale(language);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import Promise from "bluebird";
|
||||
import * as types from "constants/action_types";
|
||||
import { coinRegexPatterns } from "util/shape_shift";
|
||||
import Promise from 'bluebird';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import { coinRegexPatterns } from 'util/shape_shift';
|
||||
import type {
|
||||
GetSupportedCoinsSuccess,
|
||||
GetCoinStatsStart,
|
||||
|
@ -11,26 +11,26 @@ import type {
|
|||
PrepareShapeShiftFail,
|
||||
GetActiveShiftSuccess,
|
||||
GetActiveShiftFail,
|
||||
} from "redux/reducers/shape_shift";
|
||||
import type { FormikActions } from "types/common";
|
||||
} from 'redux/reducers/shape_shift';
|
||||
import type { FormikActions } from 'types/common';
|
||||
|
||||
// use promise chains instead of callbacks for shapeshift api
|
||||
const shapeShift = Promise.promisifyAll(require("shapeshift.io"));
|
||||
const shapeShift = Promise.promisifyAll(require('shapeshift.io'));
|
||||
|
||||
// All ShapeShift actions
|
||||
// Action types defined in the reducer will contain some payload
|
||||
export type Action =
|
||||
| { type: types.GET_SUPPORTED_COINS_START }
|
||||
| { type: types.GET_SUPPORTED_COINS_FAIL }
|
||||
| { type: ACTIONS.GET_SUPPORTED_COINS_START }
|
||||
| { type: ACTIONS.GET_SUPPORTED_COINS_FAIL }
|
||||
| GetSupportedCoinsSuccess
|
||||
| GetCoinStatsStart
|
||||
| { type: types.GET_COIN_STATS_START }
|
||||
| { type: ACTIONS.GET_COIN_STATS_START }
|
||||
| GetCoinStatsFail
|
||||
| GetCoinStatsSuccess
|
||||
| { type: types.PREPARE_SHAPE_SHIFT_START }
|
||||
| { type: ACTIONS.PREPARE_SHAPE_SHIFT_START }
|
||||
| PrepareShapeShiftFail
|
||||
| PrepareShapeShiftSuccess
|
||||
| { type: types.GET_ACTIVE_SHIFT_START }
|
||||
| { type: ACTIONS.GET_ACTIVE_SHIFT_START }
|
||||
| GetActiveShiftFail
|
||||
| GetActiveShiftSuccess;
|
||||
|
||||
|
@ -38,10 +38,8 @@ export type Action =
|
|||
// It would be nice to import these from types/common
|
||||
// Not sure how that would work since they rely on the Action type
|
||||
type PromiseAction = Promise<Action>;
|
||||
export type Dispatch = (action: Action | PromiseAction | Array<Action>) => any;
|
||||
type ThunkAction = (dispatch: Dispatch) => any;
|
||||
export type Dispatch = (
|
||||
action: Action | ThunkAction | PromiseAction | Array<Action>
|
||||
) => any;
|
||||
|
||||
// ShapeShift form values
|
||||
export type ShapeShiftFormValues = {
|
||||
|
@ -50,15 +48,26 @@ export type ShapeShiftFormValues = {
|
|||
receiveAddress: string,
|
||||
};
|
||||
|
||||
export const getCoinStats = (coin: string) => (dispatch: Dispatch): ThunkAction => {
|
||||
const pair = `${coin.toLowerCase()}_lbc`;
|
||||
|
||||
dispatch({ type: ACTIONS.GET_COIN_STATS_START, data: coin });
|
||||
|
||||
return shapeShift
|
||||
.marketInfoAsync(pair)
|
||||
.then(marketInfo => dispatch({ type: ACTIONS.GET_COIN_STATS_SUCCESS, data: marketInfo }))
|
||||
.catch(err => dispatch({ type: ACTIONS.GET_COIN_STATS_FAIL, data: err }));
|
||||
};
|
||||
|
||||
export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
|
||||
dispatch({ type: types.GET_SUPPORTED_COINS_START });
|
||||
dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_START });
|
||||
|
||||
return shapeShift
|
||||
.coinsAsync()
|
||||
.then(coinData => {
|
||||
let supportedCoins = [];
|
||||
Object.keys(coinData).forEach(symbol => {
|
||||
if (coinData[symbol].status === "available") {
|
||||
if (coinData[symbol].status === 'available') {
|
||||
supportedCoins.push(coinData[symbol]);
|
||||
}
|
||||
});
|
||||
|
@ -69,69 +78,43 @@ export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
|
|||
.map(coin => coin.symbol);
|
||||
|
||||
dispatch({
|
||||
type: types.GET_SUPPORTED_COINS_SUCCESS,
|
||||
type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS,
|
||||
data: supportedCoins,
|
||||
});
|
||||
dispatch(getCoinStats(supportedCoins[0]));
|
||||
})
|
||||
.catch(err =>
|
||||
dispatch({ type: types.GET_SUPPORTED_COINS_FAIL, data: err })
|
||||
);
|
||||
.catch(err => dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_FAIL, data: err }));
|
||||
};
|
||||
|
||||
export const getCoinStats = (coin: string) => (
|
||||
export const createShapeShift = (values: ShapeShiftFormValues, actions: FormikActions) => (
|
||||
dispatch: Dispatch
|
||||
): ThunkAction => {
|
||||
const pair = `${coin.toLowerCase()}_lbc`;
|
||||
|
||||
dispatch({ type: types.GET_COIN_STATS_START, data: coin });
|
||||
|
||||
return shapeShift
|
||||
.marketInfoAsync(pair)
|
||||
.then(marketInfo =>
|
||||
dispatch({ type: types.GET_COIN_STATS_SUCCESS, data: marketInfo })
|
||||
)
|
||||
.catch(err => dispatch({ type: types.GET_COIN_STATS_FAIL, data: err }));
|
||||
};
|
||||
|
||||
export const createShapeShift = (
|
||||
values: ShapeShiftFormValues,
|
||||
actions: FormikActions
|
||||
) => (dispatch: Dispatch): ThunkAction => {
|
||||
const {
|
||||
originCoin,
|
||||
returnAddress,
|
||||
receiveAddress: withdrawalAddress,
|
||||
} = values;
|
||||
const { originCoin, returnAddress, receiveAddress: withdrawalAddress } = values;
|
||||
|
||||
const pair = `${originCoin.toLowerCase()}_lbc`;
|
||||
const options = {
|
||||
returnAddress,
|
||||
};
|
||||
|
||||
dispatch({ type: types.PREPARE_SHAPE_SHIFT_START });
|
||||
dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_START });
|
||||
return shapeShift
|
||||
.shiftAsync(withdrawalAddress, pair, options)
|
||||
.then(res =>
|
||||
dispatch({ type: types.PREPARE_SHAPE_SHIFT_SUCCESS, data: res })
|
||||
)
|
||||
.then(res => dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS, data: res }))
|
||||
.catch(err => {
|
||||
dispatch({ type: types.PREPARE_SHAPE_SHIFT_FAIL, data: err });
|
||||
dispatch({ type: ACTIONS.PREPARE_SHAPE_SHIFT_FAIL, data: err });
|
||||
// for formik to stop the submit
|
||||
actions.setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
export const getActiveShift = (depositAddress: string) => (
|
||||
dispatch: Dispatch
|
||||
): ThunkAction => {
|
||||
dispatch({ type: types.GET_ACTIVE_SHIFT_START });
|
||||
export const getActiveShift = (depositAddress: string) => (dispatch: Dispatch): ThunkAction => {
|
||||
dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_START });
|
||||
|
||||
return shapeShift
|
||||
.statusAsync(depositAddress)
|
||||
.then(res => dispatch({ type: types.GET_ACTIVE_SHIFT_SUCCESS, data: res }))
|
||||
.catch(err => dispatch({ type: types.GET_ACTIVE_SHIFT_FAIL, data: err }));
|
||||
.then(res => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_SUCCESS, data: res }))
|
||||
.catch(err => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_FAIL, data: err }));
|
||||
};
|
||||
|
||||
export const clearShapeShift = () => (dispatch: Dispatch): Action =>
|
||||
dispatch({ type: types.CLEAR_SHAPE_SHIFT });
|
||||
dispatch({ type: ACTIONS.CLEAR_SHAPE_SHIFT });
|
||||
|
|
|
@ -1,27 +1,18 @@
|
|||
// @flow
|
||||
import * as actions from "constants/action_types";
|
||||
import type {
|
||||
Subscription,
|
||||
Action,
|
||||
Dispatch,
|
||||
} from "redux/reducers/subscriptions";
|
||||
import lbry from "lbry";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import type { Subscription, Dispatch } from 'redux/reducers/subscriptions';
|
||||
|
||||
export const doChannelSubscribe = (subscription: Subscription) => (
|
||||
dispatch: Dispatch
|
||||
) =>
|
||||
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) =>
|
||||
dispatch({
|
||||
type: actions.CHANNEL_SUBSCRIBE,
|
||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||
data: subscription,
|
||||
});
|
||||
|
||||
export const doChannelUnsubscribe = (subscription: Subscription) => (
|
||||
dispatch: Dispatch
|
||||
) =>
|
||||
export const doChannelUnsubscribe = (subscription: Subscription) => (dispatch: Dispatch) =>
|
||||
dispatch({
|
||||
type: actions.CHANNEL_UNSUBSCRIBE,
|
||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||
data: subscription,
|
||||
});
|
||||
|
||||
export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) =>
|
||||
dispatch({ type: actions.HAS_FETCHED_SUBSCRIPTIONS });
|
||||
dispatch({ type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS });
|
||||
|
|
|
@ -1,30 +1,54 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as modals from "constants/modal_types";
|
||||
import lbryio from "lbryio";
|
||||
import { doOpenModal, doShowSnackBar } from "redux/actions/app";
|
||||
import { doRewardList, doClaimRewardType } from "redux/actions/rewards";
|
||||
import { selectEmailToVerify, selectUser } from "redux/selectors/user";
|
||||
import rewards from "rewards";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import Lbryio from 'lbryio';
|
||||
import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
||||
import { doRewardList, doClaimRewardType } from 'redux/actions/rewards';
|
||||
import { selectEmailToVerify } from 'redux/selectors/user';
|
||||
import rewards from 'rewards';
|
||||
|
||||
export function doFetchInviteStatus() {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_STATUS_FETCH_STARTED,
|
||||
});
|
||||
|
||||
Lbryio.call('user', 'invite_status')
|
||||
.then(status => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS,
|
||||
data: {
|
||||
invitesRemaining: status.invites_remaining ? status.invites_remaining : 0,
|
||||
invitees: status.invitees,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doAuthenticate() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.AUTHENTICATION_STARTED,
|
||||
type: ACTIONS.AUTHENTICATION_STARTED,
|
||||
});
|
||||
lbryio
|
||||
.authenticate()
|
||||
Lbryio.authenticate()
|
||||
.then(user => {
|
||||
dispatch({
|
||||
type: types.AUTHENTICATION_SUCCESS,
|
||||
type: ACTIONS.AUTHENTICATION_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
dispatch(doRewardList());
|
||||
dispatch(doFetchInviteStatus());
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch(doOpenModal(modals.AUTHENTICATION_FAILURE));
|
||||
dispatch(doOpenModal(MODALS.AUTHENTICATION_FAILURE));
|
||||
dispatch({
|
||||
type: types.AUTHENTICATION_FAILURE,
|
||||
type: ACTIONS.AUTHENTICATION_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
|
@ -32,23 +56,22 @@ export function doAuthenticate() {
|
|||
}
|
||||
|
||||
export function doUserFetch() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.USER_FETCH_STARTED,
|
||||
type: ACTIONS.USER_FETCH_STARTED,
|
||||
});
|
||||
lbryio
|
||||
.getCurrentUser()
|
||||
Lbryio.getCurrentUser()
|
||||
.then(user => {
|
||||
dispatch(doRewardList());
|
||||
|
||||
dispatch({
|
||||
type: types.USER_FETCH_SUCCESS,
|
||||
type: ACTIONS.USER_FETCH_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: types.USER_FETCH_FAILURE,
|
||||
type: ACTIONS.USER_FETCH_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
|
@ -56,15 +79,15 @@ export function doUserFetch() {
|
|||
}
|
||||
|
||||
export function doUserEmailNew(email) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.USER_EMAIL_NEW_STARTED,
|
||||
type: ACTIONS.USER_EMAIL_NEW_STARTED,
|
||||
email,
|
||||
});
|
||||
|
||||
const success = () => {
|
||||
dispatch({
|
||||
type: types.USER_EMAIL_NEW_SUCCESS,
|
||||
type: ACTIONS.USER_EMAIL_NEW_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
dispatch(doUserFetch());
|
||||
|
@ -72,28 +95,20 @@ export function doUserEmailNew(email) {
|
|||
|
||||
const failure = error => {
|
||||
dispatch({
|
||||
type: types.USER_EMAIL_NEW_FAILURE,
|
||||
type: ACTIONS.USER_EMAIL_NEW_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
};
|
||||
|
||||
lbryio
|
||||
.call(
|
||||
"user_email",
|
||||
"new",
|
||||
{ email, send_verification_email: true },
|
||||
"post"
|
||||
)
|
||||
Lbryio.call('user_email', 'new', { email, send_verification_email: true }, 'post')
|
||||
.catch(error => {
|
||||
if (error.response && error.response.status == 409) {
|
||||
return lbryio
|
||||
.call(
|
||||
"user_email",
|
||||
"resend_token",
|
||||
{ email, only_if_expired: true },
|
||||
"post"
|
||||
)
|
||||
.then(success, failure);
|
||||
if (error.response && error.response.status === 409) {
|
||||
return Lbryio.call(
|
||||
'user_email',
|
||||
'resend_token',
|
||||
{ email, only_if_expired: true },
|
||||
'post'
|
||||
).then(success, failure);
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
|
@ -104,35 +119,34 @@ export function doUserEmailNew(email) {
|
|||
export function doUserEmailVerify(verificationToken) {
|
||||
return function(dispatch, getState) {
|
||||
const email = selectEmailToVerify(getState());
|
||||
verificationToken = verificationToken.toString().trim();
|
||||
const trimmedVerificationToken = verificationToken.toString().trim();
|
||||
|
||||
dispatch({
|
||||
type: types.USER_EMAIL_VERIFY_STARTED,
|
||||
code: verificationToken,
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_STARTED,
|
||||
code: trimmedVerificationToken,
|
||||
});
|
||||
|
||||
lbryio
|
||||
.call(
|
||||
"user_email",
|
||||
"confirm",
|
||||
{ verification_token: verificationToken, email },
|
||||
"post"
|
||||
)
|
||||
Lbryio.call(
|
||||
'user_email',
|
||||
'confirm',
|
||||
{ verification_token: trimmedVerificationToken, email },
|
||||
'post'
|
||||
)
|
||||
.then(userEmail => {
|
||||
if (userEmail.is_verified) {
|
||||
dispatch({
|
||||
type: types.USER_EMAIL_VERIFY_SUCCESS,
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL)),
|
||||
dispatch(doUserFetch());
|
||||
dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL));
|
||||
dispatch(doUserFetch());
|
||||
} else {
|
||||
throw new Error("Your email is still not verified."); // shouldn't happen
|
||||
throw new Error('Your email is still not verified.'); // shouldn't happen
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: types.USER_EMAIL_VERIFY_FAILURE,
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
|
@ -140,30 +154,27 @@ export function doUserEmailVerify(verificationToken) {
|
|||
}
|
||||
|
||||
export function doUserIdentityVerify(stripeToken) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.USER_IDENTITY_VERIFY_STARTED,
|
||||
type: ACTIONS.USER_IDENTITY_VERIFY_STARTED,
|
||||
token: stripeToken,
|
||||
});
|
||||
|
||||
lbryio
|
||||
.call("user", "verify_identity", { stripe_token: stripeToken }, "post")
|
||||
Lbryio.call('user', 'verify_identity', { stripe_token: stripeToken }, 'post')
|
||||
.then(user => {
|
||||
if (user.is_identity_verified) {
|
||||
dispatch({
|
||||
type: types.USER_IDENTITY_VERIFY_SUCCESS,
|
||||
type: ACTIONS.USER_IDENTITY_VERIFY_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
dispatch(doClaimRewardType(rewards.TYPE_NEW_USER));
|
||||
} else {
|
||||
throw new Error(
|
||||
"Your identity is still not verified. This should not happen."
|
||||
); // shouldn't happen
|
||||
throw new Error('Your identity is still not verified. This should not happen.'); // shouldn't happen
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: types.USER_IDENTITY_VERIFY_FAILURE,
|
||||
type: ACTIONS.USER_IDENTITY_VERIFY_FAILURE,
|
||||
data: { error: error.toString() },
|
||||
});
|
||||
});
|
||||
|
@ -171,61 +182,32 @@ export function doUserIdentityVerify(stripeToken) {
|
|||
}
|
||||
|
||||
export function doFetchAccessToken() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
const success = token =>
|
||||
dispatch({
|
||||
type: types.FETCH_ACCESS_TOKEN_SUCCESS,
|
||||
type: ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS,
|
||||
data: { token },
|
||||
});
|
||||
lbryio.getAuthToken().then(success);
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchInviteStatus() {
|
||||
return function(dispatch, getState) {
|
||||
dispatch({
|
||||
type: types.USER_INVITE_STATUS_FETCH_STARTED,
|
||||
});
|
||||
|
||||
lbryio
|
||||
.call("user", "invite_status")
|
||||
.then(status => {
|
||||
dispatch({
|
||||
type: types.USER_INVITE_STATUS_FETCH_SUCCESS,
|
||||
data: {
|
||||
invitesRemaining: status.invites_remaining
|
||||
? status.invites_remaining
|
||||
: 0,
|
||||
invitees: status.invitees,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: types.USER_INVITE_STATUS_FETCH_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
Lbryio.getAuthToken().then(success);
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserInviteNew(email) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.USER_INVITE_NEW_STARTED,
|
||||
type: ACTIONS.USER_INVITE_NEW_STARTED,
|
||||
});
|
||||
|
||||
lbryio
|
||||
.call("user", "invite", { email }, "post")
|
||||
.then(invite => {
|
||||
Lbryio.call('user', 'invite', { email }, 'post')
|
||||
.then(() => {
|
||||
dispatch({
|
||||
type: types.USER_INVITE_NEW_SUCCESS,
|
||||
type: ACTIONS.USER_INVITE_NEW_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
|
||||
dispatch(
|
||||
doShowSnackBar({
|
||||
message: __("Invite sent to %s", email),
|
||||
message: __('Invite sent to %s', email),
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -233,7 +215,7 @@ export function doUserInviteNew(email) {
|
|||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: types.USER_INVITE_NEW_FAILURE,
|
||||
type: ACTIONS.USER_INVITE_NEW_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbry from "lbry";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbry from 'lbry';
|
||||
import {
|
||||
selectDraftTransaction,
|
||||
selectDraftTransactionAmount,
|
||||
selectBalance,
|
||||
} from "redux/selectors/wallet";
|
||||
import { doOpenModal, doShowSnackBar } from "redux/actions/app";
|
||||
import { doNavigate } from "redux/actions/navigation";
|
||||
import * as modals from "constants/modal_types";
|
||||
} from 'redux/selectors/wallet';
|
||||
import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
|
||||
export function doUpdateBalance() {
|
||||
return function(dispatch, getState) {
|
||||
lbry.wallet_balance().then(balance =>
|
||||
return function(dispatch) {
|
||||
Lbry.wallet_balance().then(balance =>
|
||||
dispatch({
|
||||
type: types.UPDATE_BALANCE,
|
||||
type: ACTIONS.UPDATE_BALANCE,
|
||||
data: {
|
||||
balance,
|
||||
},
|
||||
|
@ -23,36 +23,34 @@ export function doUpdateBalance() {
|
|||
}
|
||||
|
||||
export function doBalanceSubscribe() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch(doUpdateBalance());
|
||||
setInterval(() => dispatch(doUpdateBalance()), 5000);
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchTransactions(fetch_tip_info = true) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.FETCH_TRANSACTIONS_STARTED,
|
||||
type: ACTIONS.FETCH_TRANSACTIONS_STARTED,
|
||||
});
|
||||
|
||||
lbry
|
||||
.transaction_list({ include_tip_info: fetch_tip_info })
|
||||
.then(results => {
|
||||
dispatch({
|
||||
type: types.FETCH_TRANSACTIONS_COMPLETED,
|
||||
data: {
|
||||
transactions: results,
|
||||
},
|
||||
});
|
||||
Lbry.transaction_list({ include_tip_info: fetch_tip_info }).then(results => {
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_TRANSACTIONS_COMPLETED,
|
||||
data: {
|
||||
transactions: results,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchBlock(height) {
|
||||
return function(dispatch, getState) {
|
||||
lbry.block_show({ height }).then(block => {
|
||||
return function(dispatch) {
|
||||
Lbry.block_show({ height }).then(block => {
|
||||
dispatch({
|
||||
type: types.FETCH_BLOCK_SUCCESS,
|
||||
type: ACTIONS.FETCH_BLOCK_SUCCESS,
|
||||
data: { block },
|
||||
});
|
||||
});
|
||||
|
@ -60,15 +58,15 @@ export function doFetchBlock(height) {
|
|||
}
|
||||
|
||||
export function doGetNewAddress() {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.GET_NEW_ADDRESS_STARTED,
|
||||
type: ACTIONS.GET_NEW_ADDRESS_STARTED,
|
||||
});
|
||||
|
||||
lbry.wallet_new_address().then(address => {
|
||||
localStorage.setItem("wallet_address", address);
|
||||
Lbry.wallet_new_address().then(address => {
|
||||
localStorage.setItem('wallet_address', address);
|
||||
dispatch({
|
||||
type: types.GET_NEW_ADDRESS_COMPLETED,
|
||||
type: ACTIONS.GET_NEW_ADDRESS_COMPLETED,
|
||||
data: { address },
|
||||
});
|
||||
});
|
||||
|
@ -76,16 +74,16 @@ export function doGetNewAddress() {
|
|||
}
|
||||
|
||||
export function doCheckAddressIsMine(address) {
|
||||
return function(dispatch, getState) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: types.CHECK_ADDRESS_IS_MINE_STARTED,
|
||||
type: ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED,
|
||||
});
|
||||
|
||||
lbry.wallet_is_address_mine({ address }).then(isMine => {
|
||||
Lbry.wallet_is_address_mine({ address }).then(isMine => {
|
||||
if (!isMine) dispatch(doGetNewAddress());
|
||||
|
||||
dispatch({
|
||||
type: types.CHECK_ADDRESS_IS_MINE_COMPLETED,
|
||||
type: ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -99,113 +97,111 @@ export function doSendDraftTransaction() {
|
|||
const amount = selectDraftTransactionAmount(state);
|
||||
|
||||
if (balance - amount <= 0) {
|
||||
return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
|
||||
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.SEND_TRANSACTION_STARTED,
|
||||
type: ACTIONS.SEND_TRANSACTION_STARTED,
|
||||
});
|
||||
|
||||
const successCallback = results => {
|
||||
if (results === true) {
|
||||
dispatch({
|
||||
type: types.SEND_TRANSACTION_COMPLETED,
|
||||
type: ACTIONS.SEND_TRANSACTION_COMPLETED,
|
||||
});
|
||||
dispatch(
|
||||
doShowSnackBar({
|
||||
message: __(`You sent ${amount} LBC`),
|
||||
linkText: __("History"),
|
||||
linkTarget: __("/wallet"),
|
||||
linkText: __('History'),
|
||||
linkTarget: __('/wallet'),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
dispatch({
|
||||
type: types.SEND_TRANSACTION_FAILED,
|
||||
type: ACTIONS.SEND_TRANSACTION_FAILED,
|
||||
data: { error: results },
|
||||
});
|
||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||
}
|
||||
};
|
||||
|
||||
const errorCallback = error => {
|
||||
dispatch({
|
||||
type: types.SEND_TRANSACTION_FAILED,
|
||||
type: ACTIONS.SEND_TRANSACTION_FAILED,
|
||||
data: { error: error.message },
|
||||
});
|
||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||
};
|
||||
|
||||
lbry
|
||||
.wallet_send({
|
||||
amount: draftTx.amount,
|
||||
address: draftTx.address,
|
||||
})
|
||||
.then(successCallback, errorCallback);
|
||||
Lbry.wallet_send({
|
||||
amount: draftTx.amount,
|
||||
address: draftTx.address,
|
||||
}).then(successCallback, errorCallback);
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetDraftTransactionAmount(amount) {
|
||||
return {
|
||||
type: types.SET_DRAFT_TRANSACTION_AMOUNT,
|
||||
type: ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT,
|
||||
data: { amount },
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetDraftTransactionAddress(address) {
|
||||
return {
|
||||
type: types.SET_DRAFT_TRANSACTION_ADDRESS,
|
||||
type: ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS,
|
||||
data: { address },
|
||||
};
|
||||
}
|
||||
|
||||
export function doSendSupport(amount, claim_id, uri) {
|
||||
export function doSendSupport(amount, claimId, uri) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
const balance = selectBalance(state);
|
||||
|
||||
if (balance - amount <= 0) {
|
||||
return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
|
||||
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.SUPPORT_TRANSACTION_STARTED,
|
||||
type: ACTIONS.SUPPORT_TRANSACTION_STARTED,
|
||||
});
|
||||
|
||||
const successCallback = results => {
|
||||
if (results.txid) {
|
||||
dispatch({
|
||||
type: types.SUPPORT_TRANSACTION_COMPLETED,
|
||||
type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED,
|
||||
});
|
||||
dispatch(
|
||||
doShowSnackBar({
|
||||
message: __(`You sent ${amount} LBC as support, Mahalo!`),
|
||||
linkText: __("History"),
|
||||
linkTarget: __("/wallet"),
|
||||
linkText: __('History'),
|
||||
linkTarget: __('/wallet'),
|
||||
})
|
||||
);
|
||||
dispatch(doNavigate("/show", { uri }));
|
||||
dispatch(doNavigate('/show', { uri }));
|
||||
} else {
|
||||
dispatch({
|
||||
type: types.SUPPORT_TRANSACTION_FAILED,
|
||||
type: ACTIONS.SUPPORT_TRANSACTION_FAILED,
|
||||
data: { error: results.code },
|
||||
});
|
||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||
}
|
||||
};
|
||||
|
||||
const errorCallback = error => {
|
||||
dispatch({
|
||||
type: types.SUPPORT_TRANSACTION_FAILED,
|
||||
type: ACTIONS.SUPPORT_TRANSACTION_FAILED,
|
||||
data: { error: error.code },
|
||||
});
|
||||
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
||||
};
|
||||
|
||||
lbry
|
||||
.wallet_send({
|
||||
claim_id,
|
||||
amount,
|
||||
})
|
||||
.then(successCallback, errorCallback);
|
||||
Lbry.wallet_send({
|
||||
claimId,
|
||||
amount,
|
||||
}).then(successCallback, errorCallback);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
// @flow
|
||||
|
||||
import * as types from "constants/action_types";
|
||||
import * as modalTypes from "constants/modal_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
|
||||
const { remote } = require("electron");
|
||||
const { remote } = require('electron');
|
||||
|
||||
const application = remote.app;
|
||||
const win = remote.BrowserWindow.getFocusedWindow();
|
||||
|
||||
const reducers = {};
|
||||
|
@ -41,12 +40,12 @@ const defaultState: AppState = {
|
|||
modal: null,
|
||||
modalProps: {},
|
||||
platform: process.platform,
|
||||
upgradeSkipped: sessionStorage.getItem("upgradeSkipped") === "true",
|
||||
upgradeSkipped: sessionStorage.getItem('upgradeSkipped') === 'true',
|
||||
daemonVersionMatched: null,
|
||||
daemonReady: false,
|
||||
hasSignature: false,
|
||||
badgeNumber: 0,
|
||||
volume: Number(sessionStorage.getItem("volume")) || 1,
|
||||
volume: Number(sessionStorage.getItem('volume')) || 1,
|
||||
|
||||
downloadProgress: undefined,
|
||||
upgradeDownloading: undefined,
|
||||
|
@ -57,26 +56,26 @@ const defaultState: AppState = {
|
|||
snackBar: undefined,
|
||||
};
|
||||
|
||||
reducers[types.DAEMON_READY] = function(state, action) {
|
||||
reducers[ACTIONS.DAEMON_READY] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
daemonReady: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.DAEMON_VERSION_MATCH] = function(state, action) {
|
||||
reducers[ACTIONS.DAEMON_VERSION_MATCH] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
daemonVersionMatched: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.DAEMON_VERSION_MISMATCH] = function(state, action) {
|
||||
reducers[ACTIONS.DAEMON_VERSION_MISMATCH] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
daemonVersionMatched: false,
|
||||
modal: modalTypes.INCOMPATIBLE_DAEMON,
|
||||
modal: MODALS.INCOMPATIBLE_DAEMON,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.UPGRADE_CANCELLED] = function(state, action) {
|
||||
reducers[ACTIONS.UPGRADE_CANCELLED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
downloadProgress: null,
|
||||
upgradeDownloadComplete: false,
|
||||
|
@ -84,7 +83,7 @@ reducers[types.UPGRADE_CANCELLED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
downloadPath: action.data.path,
|
||||
upgradeDownloading: false,
|
||||
|
@ -92,14 +91,14 @@ reducers[types.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.UPGRADE_DOWNLOAD_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.UPGRADE_DOWNLOAD_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
upgradeDownloading: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SKIP_UPGRADE] = function(state, action) {
|
||||
sessionStorage.setItem("upgradeSkipped", "true");
|
||||
reducers[ACTIONS.SKIP_UPGRADE] = function(state) {
|
||||
sessionStorage.setItem('upgradeSkipped', 'true');
|
||||
|
||||
return Object.assign({}, state, {
|
||||
isUpgradeSkipped: true,
|
||||
|
@ -107,46 +106,46 @@ reducers[types.SKIP_UPGRADE] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.UPDATE_VERSION] = function(state, action) {
|
||||
reducers[ACTIONS.UPDATE_VERSION] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
version: action.data.version,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CHECK_UPGRADE_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.CHECK_UPGRADE_SUCCESS] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
isUpgradeAvailable: action.data.upgradeAvailable,
|
||||
remoteVersion: action.data.remoteVersion,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) {
|
||||
reducers[ACTIONS.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
checkUpgradeTimer: action.data.checkUpgradeTimer,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.OPEN_MODAL] = function(state, action) {
|
||||
reducers[ACTIONS.OPEN_MODAL] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
modal: action.data.modal,
|
||||
modalProps: action.data.modalProps || {},
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CLOSE_MODAL] = function(state, action) {
|
||||
reducers[ACTIONS.CLOSE_MODAL] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
modal: undefined,
|
||||
modalProps: {},
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) {
|
||||
reducers[ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
downloadProgress: action.data.percent,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SHOW_SNACKBAR] = function(state, action) {
|
||||
reducers[ACTIONS.SHOW_SNACKBAR] = function(state, action) {
|
||||
const { message, linkText, linkTarget, isError } = action.data;
|
||||
const snackBar = Object.assign({}, state.snackBar);
|
||||
const snacks = Object.assign([], snackBar.snacks);
|
||||
|
@ -165,7 +164,7 @@ reducers[types.SHOW_SNACKBAR] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) {
|
||||
reducers[ACTIONS.REMOVE_SNACKBAR_SNACK] = function(state) {
|
||||
const snackBar = Object.assign({}, state.snackBar);
|
||||
const snacks = Object.assign([], snackBar.snacks);
|
||||
snacks.shift();
|
||||
|
@ -179,8 +178,8 @@ reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||
const badgeNumber = state.badgeNumber;
|
||||
reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state) {
|
||||
const { badgeNumber } = state;
|
||||
|
||||
// Don't update the badge number if the window is focused
|
||||
if (win && win.isFocused()) return Object.assign({}, state);
|
||||
|
@ -190,13 +189,13 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.WINDOW_FOCUSED] = function(state, action) {
|
||||
reducers[ACTIONS.WINDOW_FOCUSED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
badgeNumber: 0,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.VOLUME_CHANGED] = function(state, action) {
|
||||
reducers[ACTIONS.VOLUME_CHANGED] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
volume: action.data.volume,
|
||||
});
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {};
|
||||
|
||||
reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_AVAILABILITY_STARTED] = function(state, action) {
|
||||
const { uri } = action.data;
|
||||
const newFetching = Object.assign({}, state.fetching);
|
||||
|
||||
|
@ -14,7 +14,7 @@ reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_AVAILABILITY_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_AVAILABILITY_COMPLETED] = function(state, action) {
|
||||
const { uri, availability } = action.data;
|
||||
|
||||
const newFetching = Object.assign({}, state.fetching);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
|
||||
const defaultState = {};
|
||||
|
||||
reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||
const { resolveInfo } = action.data;
|
||||
const byUri = Object.assign({}, state.claimsByUri);
|
||||
const byId = Object.assign({}, state.byId);
|
||||
|
||||
for (const [uri, { certificate, claim }] of Object.entries(resolveInfo)) {
|
||||
Object.entries(resolveInfo).forEach(([uri, { certificate, claim }]) => {
|
||||
if (claim) {
|
||||
byId[claim.claim_id] = claim;
|
||||
byUri[uri] = claim.claim_id;
|
||||
|
@ -25,7 +25,7 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
|||
} else {
|
||||
byUri[uri] = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
byId,
|
||||
|
@ -33,37 +33,32 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_CLAIM_LIST_MINE_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
isFetchingClaimListMine: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
|
||||
const { claims } = action.data;
|
||||
const byUri = Object.assign({}, state.claimsByUri);
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const pendingById = Object.assign({}, state.pendingById);
|
||||
const abandoningById = Object.assign({}, state.abandoningById);
|
||||
|
||||
claims
|
||||
.filter(claim => claim.category && claim.category.match(/claim/))
|
||||
.forEach(claim => {
|
||||
byId[claim.claim_id] = claim;
|
||||
claims.filter(claim => claim.category && claim.category.match(/claim/)).forEach(claim => {
|
||||
byId[claim.claim_id] = claim;
|
||||
|
||||
const pending = Object.values(pendingById).find(
|
||||
pendingClaim =>
|
||||
pendingClaim.name == claim.name &&
|
||||
pendingClaim.channel_name == claim.channel_name
|
||||
);
|
||||
const pending = Object.values(pendingById).find(
|
||||
pendingClaim =>
|
||||
pendingClaim.name === claim.name && pendingClaim.channel_name === claim.channel_name
|
||||
);
|
||||
|
||||
if (pending) {
|
||||
delete pendingById[pending.claim_id];
|
||||
}
|
||||
});
|
||||
if (pending) {
|
||||
delete pendingById[pending.claim_id];
|
||||
}
|
||||
});
|
||||
|
||||
// Remove old timed out pending publishes
|
||||
const old = Object.values(pendingById)
|
||||
Object.values(pendingById)
|
||||
.filter(pendingClaim => Date.now() - pendingClaim.time >= 20 * 60 * 1000)
|
||||
.forEach(pendingClaim => {
|
||||
delete pendingById[pendingClaim.claim_id];
|
||||
|
@ -77,11 +72,11 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state) {
|
||||
return Object.assign({}, state, { fetchingMyChannels: true });
|
||||
};
|
||||
|
||||
reducers[types.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) {
|
||||
const { claims } = action.data;
|
||||
const myChannelClaims = new Set(state.myChannelClaims);
|
||||
const byId = Object.assign({}, state.byId);
|
||||
|
@ -98,7 +93,7 @@ reducers[types.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
|
||||
const { uri, page } = action.data;
|
||||
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
|
||||
|
||||
|
@ -109,7 +104,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
||||
const { uri, claims, page } = action.data;
|
||||
|
||||
const claimsByChannel = Object.assign({}, state.claimsByChannel);
|
||||
|
@ -139,7 +134,7 @@ reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.ABANDON_CLAIM_STARTED] = function(state, action) {
|
||||
const { claimId } = action.data;
|
||||
const abandoningById = Object.assign({}, state.abandoningById);
|
||||
|
||||
|
@ -150,7 +145,7 @@ reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
|
||||
reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
|
||||
const { claimId } = action.data;
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const claimsByUri = Object.assign({}, state.claimsByUri);
|
||||
|
@ -169,7 +164,7 @@ reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = function(state, action) {
|
||||
const { channelClaim } = action.data;
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const myChannelClaims = new Set(state.myChannelClaims);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {
|
||||
|
@ -7,13 +7,13 @@ const defaultState = {
|
|||
channelClaimCounts: {},
|
||||
};
|
||||
|
||||
reducers[types.FETCH_FEATURED_CONTENT_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_FEATURED_CONTENT_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
fetchingFeaturedContent: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
||||
const { uris, success } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
|
@ -23,42 +23,40 @@ reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) {
|
||||
const { claimIds, success } = action.data;
|
||||
reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) {
|
||||
const { claimIds } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
rewardedContentClaimIds: claimIds,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.RESOLVE_URIS_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.RESOLVE_URIS_STARTED] = function(state, action) {
|
||||
const { uris } = action.data;
|
||||
|
||||
const oldResolving = state.resolvingUris || [];
|
||||
const newResolving = Object.assign([], oldResolving);
|
||||
|
||||
for (const uri of uris) {
|
||||
uris.forEach(uri => {
|
||||
if (!newResolving.includes(uri)) {
|
||||
newResolving.push(uri);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
resolvingUris: newResolving,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||
const { resolveInfo } = action.data;
|
||||
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
|
||||
|
||||
for (const [uri, { certificate, claims_in_channel }] of Object.entries(
|
||||
resolveInfo
|
||||
)) {
|
||||
if (certificate && !isNaN(claims_in_channel)) {
|
||||
channelClaimCounts[uri] = claims_in_channel;
|
||||
Object.entries(resolveInfo).forEach(([uri, { certificate, claimsInChannel }]) => {
|
||||
if (certificate && !Number.isNaN(claimsInChannel)) {
|
||||
channelClaimCounts[uri] = claimsInChannel;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
channelClaimCounts,
|
||||
|
@ -66,12 +64,12 @@ reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.SET_PLAYING_URI] = (state, action) =>
|
||||
reducers[ACTIONS.SET_PLAYING_URI] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
playingUri: action.data.uri,
|
||||
});
|
||||
|
||||
reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
|
||||
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
|
||||
const { uri, totalClaims } = action.data;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {};
|
||||
|
||||
reducers[types.FETCH_COST_INFO_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_COST_INFO_STARTED] = function(state, action) {
|
||||
const { uri } = action.data;
|
||||
const newFetching = Object.assign({}, state.fetching);
|
||||
newFetching[uri] = true;
|
||||
|
@ -13,7 +13,7 @@ reducers[types.FETCH_COST_INFO_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_COST_INFO_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_COST_INFO_COMPLETED] = function(state, action) {
|
||||
const { uri, costInfo } = action.data;
|
||||
const newByUri = Object.assign({}, state.byUri);
|
||||
const newFetching = Object.assign({}, state.fetching);
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbryuri from "lbryuri";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {};
|
||||
|
||||
reducers[types.FILE_LIST_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FILE_LIST_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
isFetchingFileList: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FILE_LIST_SUCCEEDED] = function(state, action) {
|
||||
reducers[ACTIONS.FILE_LIST_SUCCEEDED] = function(state, action) {
|
||||
const { fileInfos } = action.data;
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint);
|
||||
|
@ -28,7 +27,7 @@ reducers[types.FILE_LIST_SUCCEEDED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_FILE_INFO_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_FILE_INFO_STARTED] = function(state, action) {
|
||||
const { outpoint } = action.data;
|
||||
const newFetching = Object.assign({}, state.fetching);
|
||||
|
||||
|
@ -39,7 +38,7 @@ reducers[types.FETCH_FILE_INFO_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_FILE_INFO_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = function(state, action) {
|
||||
const { fileInfo, outpoint } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
|
@ -54,7 +53,7 @@ reducers[types.FETCH_FILE_INFO_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.DOWNLOADING_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.DOWNLOADING_STARTED] = function(state, action) {
|
||||
const { uri, outpoint, fileInfo } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
|
@ -72,8 +71,8 @@ reducers[types.DOWNLOADING_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) {
|
||||
const { uri, outpoint, fileInfo } = action.data;
|
||||
reducers[ACTIONS.DOWNLOADING_PROGRESSED] = function(state, action) {
|
||||
const { outpoint, fileInfo } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||
|
@ -87,8 +86,8 @@ reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||
const { uri, outpoint, fileInfo } = action.data;
|
||||
reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||
const { outpoint, fileInfo } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||
|
@ -102,7 +101,7 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FILE_DELETE] = function(state, action) {
|
||||
reducers[ACTIONS.FILE_DELETE] = function(state, action) {
|
||||
const { outpoint } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
|
@ -117,7 +116,7 @@ reducers[types.FILE_DELETE] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.LOADING_VIDEO_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.LOADING_VIDEO_STARTED] = function(state, action) {
|
||||
const { uri } = action.data;
|
||||
|
||||
const newLoading = Object.assign({}, state.urisLoading);
|
||||
|
@ -129,7 +128,7 @@ reducers[types.LOADING_VIDEO_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.LOADING_VIDEO_FAILED] = function(state, action) {
|
||||
reducers[ACTIONS.LOADING_VIDEO_FAILED] = function(state, action) {
|
||||
const { uri } = action.data;
|
||||
|
||||
const newLoading = Object.assign({}, state.urisLoading);
|
||||
|
@ -141,13 +140,14 @@ reducers[types.LOADING_VIDEO_FAILED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_DATE] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_DATE] = function(state, action) {
|
||||
const { time } = action.data;
|
||||
if (time) {
|
||||
return Object.assign({}, state, {
|
||||
publishedDate: time,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
|
|
|
@ -1,38 +1,36 @@
|
|||
import * as types from "constants/action_types";
|
||||
import { parseQueryParams } from "util/query_params";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const currentPath = () => {
|
||||
const hash = document.location.hash;
|
||||
if (hash !== "") return hash.replace(/^#/, "");
|
||||
return "/discover";
|
||||
const getCurrentPath = () => {
|
||||
const { hash } = document.location;
|
||||
if (hash !== '') return hash.replace(/^#/, '');
|
||||
return '/discover';
|
||||
};
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {
|
||||
currentPath: currentPath(),
|
||||
pathAfterAuth: "/discover",
|
||||
currentPath: getCurrentPath(),
|
||||
pathAfterAuth: '/discover',
|
||||
index: 0,
|
||||
stack: [],
|
||||
};
|
||||
|
||||
reducers[types.DAEMON_READY] = function(state, action) {
|
||||
reducers[ACTIONS.DAEMON_READY] = function(state) {
|
||||
const { currentPath } = state;
|
||||
const params = parseQueryParams(currentPath.split("?")[1] || "");
|
||||
|
||||
return Object.assign({}, state, {
|
||||
stack: [{ path: currentPath, scrollY: 0 }],
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CHANGE_AFTER_AUTH_PATH] = function(state, action) {
|
||||
reducers[ACTIONS.CHANGE_AFTER_AUTH_PATH] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
pathAfterAuth: action.data.path,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.HISTORY_NAVIGATE] = (state, action) => {
|
||||
reducers[ACTIONS.HISTORY_NAVIGATE] = (state, action) => {
|
||||
const { stack, index } = state;
|
||||
const { url: path, index: newIndex, scrollY } = action.data;
|
||||
const { url: path, index: newIndex } = action.data;
|
||||
|
||||
const newState = {
|
||||
currentPath: path,
|
||||
|
@ -46,12 +44,11 @@ reducers[types.HISTORY_NAVIGATE] = (state, action) => {
|
|||
newState.index = newState.stack.length - 1;
|
||||
}
|
||||
|
||||
history.replaceState(null, null, `#${path}`); // this allows currentPath() to retain the URL on reload
|
||||
return Object.assign({}, state, newState);
|
||||
};
|
||||
|
||||
reducers[types.WINDOW_SCROLLED] = (state, action) => {
|
||||
const { stack, index } = state;
|
||||
reducers[ACTIONS.WINDOW_SCROLLED] = (state, action) => {
|
||||
const { index } = state;
|
||||
const { scrollY } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {
|
||||
|
@ -9,17 +9,17 @@ const defaultState = {
|
|||
claimErrorsByType: {},
|
||||
};
|
||||
|
||||
reducers[types.FETCH_REWARDS_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_REWARDS_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
fetching: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = function(state, action) {
|
||||
const { userRewards } = action.data;
|
||||
|
||||
let unclaimedRewards = {},
|
||||
claimedRewards = {};
|
||||
const unclaimedRewards = {};
|
||||
const claimedRewards = {};
|
||||
userRewards.forEach(reward => {
|
||||
if (reward.transaction_id) {
|
||||
claimedRewards[reward.id] = reward;
|
||||
|
@ -35,7 +35,7 @@ reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
function setClaimRewardState(state, reward, isClaiming, errorMessage = "") {
|
||||
function setClaimRewardState(state, reward, isClaiming, errorMessage = '') {
|
||||
const newClaimPendingByType = Object.assign({}, state.claimPendingByType);
|
||||
const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType);
|
||||
if (isClaiming) {
|
||||
|
@ -55,21 +55,17 @@ function setClaimRewardState(state, reward, isClaiming, errorMessage = "") {
|
|||
});
|
||||
}
|
||||
|
||||
reducers[types.CLAIM_REWARD_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.CLAIM_REWARD_STARTED] = function(state, action) {
|
||||
const { reward } = action.data;
|
||||
|
||||
return setClaimRewardState(state, reward, true, "");
|
||||
return setClaimRewardState(state, reward, true, '');
|
||||
};
|
||||
|
||||
reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = function(state, action) {
|
||||
const { reward } = action.data;
|
||||
|
||||
const unclaimedRewardsByType = Object.assign(
|
||||
{},
|
||||
state.unclaimedRewardsByType
|
||||
);
|
||||
const unclaimedRewardsByType = Object.assign({}, state.unclaimedRewardsByType);
|
||||
const existingReward = unclaimedRewardsByType[reward.reward_type];
|
||||
delete state.unclaimedRewardsByType[reward.reward_type];
|
||||
|
||||
const newReward = Object.assign({}, reward, {
|
||||
reward_title: existingReward.reward_title,
|
||||
|
@ -84,24 +80,19 @@ reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) {
|
|||
claimedRewardsById,
|
||||
});
|
||||
|
||||
return setClaimRewardState(newState, newReward, false, "");
|
||||
return setClaimRewardState(newState, newReward, false, '');
|
||||
};
|
||||
|
||||
reducers[types.CLAIM_REWARD_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.CLAIM_REWARD_FAILURE] = function(state, action) {
|
||||
const { reward, error } = action.data;
|
||||
|
||||
return setClaimRewardState(state, reward, false, error ? error.message : "");
|
||||
return setClaimRewardState(state, reward, false, error ? error.message : '');
|
||||
};
|
||||
|
||||
reducers[types.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) {
|
||||
reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) {
|
||||
const { reward } = action.data;
|
||||
|
||||
return setClaimRewardState(
|
||||
state,
|
||||
reward,
|
||||
state.claimPendingByType[reward.reward_type],
|
||||
""
|
||||
);
|
||||
return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], '');
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {
|
||||
|
@ -6,15 +6,13 @@ const defaultState = {
|
|||
searching: false,
|
||||
};
|
||||
|
||||
reducers[types.SEARCH_STARTED] = function(state, action) {
|
||||
const { query } = action.data;
|
||||
|
||||
reducers[ACTIONS.SEARCH_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
searching: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SEARCH_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.SEARCH_COMPLETED] = function(state, action) {
|
||||
const { query, uris } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
|
@ -23,7 +21,7 @@ reducers[types.SEARCH_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.SEARCH_CANCELLED] = function(state, action) {
|
||||
reducers[ACTIONS.SEARCH_CANCELLED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
searching: false,
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as settings from "constants/settings";
|
||||
import LANGUAGES from "constants/languages";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import LANGUAGES from 'constants/languages';
|
||||
|
||||
function getLocalStorageSetting(setting, fallback) {
|
||||
const localStorageVal = localStorage.getItem(`setting_${setting}`);
|
||||
|
@ -10,38 +10,30 @@ function getLocalStorageSetting(setting, fallback) {
|
|||
const reducers = {};
|
||||
const defaultState = {
|
||||
clientSettings: {
|
||||
instantPurchaseEnabled: getLocalStorageSetting(
|
||||
settings.INSTANT_PURCHASE_ENABLED,
|
||||
false
|
||||
),
|
||||
instantPurchaseMax: getLocalStorageSetting(settings.INSTANT_PURCHASE_MAX, {
|
||||
currency: "LBC",
|
||||
instantPurchaseEnabled: getLocalStorageSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, false),
|
||||
instantPurchaseMax: getLocalStorageSetting(SETTINGS.INSTANT_PURCHASE_MAX, {
|
||||
currency: 'LBC',
|
||||
amount: 0.1,
|
||||
}),
|
||||
showNsfw: getLocalStorageSetting(settings.SHOW_NSFW, false),
|
||||
showUnavailable: getLocalStorageSetting(settings.SHOW_UNAVAILABLE, true),
|
||||
welcome_acknowledged: getLocalStorageSetting(
|
||||
settings.NEW_USER_ACKNOWLEDGED,
|
||||
false
|
||||
),
|
||||
email_collection_acknowledged: getLocalStorageSetting(
|
||||
settings.EMAIL_COLLECTION_ACKNOWLEDGED
|
||||
),
|
||||
showNsfw: getLocalStorageSetting(SETTINGS.SHOW_NSFW, false),
|
||||
showUnavailable: getLocalStorageSetting(SETTINGS.SHOW_UNAVAILABLE, true),
|
||||
welcome_acknowledged: getLocalStorageSetting(SETTINGS.NEW_USER_ACKNOWLEDGED, false),
|
||||
email_collection_acknowledged: getLocalStorageSetting(SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED),
|
||||
credit_required_acknowledged: false, // this needs to be re-acknowledged every run
|
||||
language: getLocalStorageSetting(settings.LANGUAGE, "en"),
|
||||
theme: getLocalStorageSetting(settings.THEME, "light"),
|
||||
themes: getLocalStorageSetting(settings.THEMES, []),
|
||||
language: getLocalStorageSetting(SETTINGS.LANGUAGE, 'en'),
|
||||
theme: getLocalStorageSetting(SETTINGS.THEME, 'light'),
|
||||
themes: getLocalStorageSetting(SETTINGS.THEMES, []),
|
||||
},
|
||||
languages: {},
|
||||
};
|
||||
|
||||
reducers[types.DAEMON_SETTINGS_RECEIVED] = function(state, action) {
|
||||
reducers[ACTIONS.DAEMON_SETTINGS_RECEIVED] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
daemonSettings: action.data.settings,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) {
|
||||
reducers[ACTIONS.CLIENT_SETTING_CHANGED] = function(state, action) {
|
||||
const { key, value } = action.data;
|
||||
const clientSettings = Object.assign({}, state.clientSettings);
|
||||
|
||||
|
@ -55,16 +47,14 @@ reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
|
||||
reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
|
||||
const languages = Object.assign({}, state.languages);
|
||||
const language = action.data.language;
|
||||
const { language } = action.data;
|
||||
|
||||
const langCode = language.substring(0, 2);
|
||||
|
||||
if (LANGUAGES[langCode]) {
|
||||
languages[language] = `${LANGUAGES[langCode][0]} (${
|
||||
LANGUAGES[langCode][1]
|
||||
})`;
|
||||
languages[language] = `${LANGUAGES[langCode][0]} (${LANGUAGES[langCode][1]})`;
|
||||
} else {
|
||||
languages[langCode] = langCode;
|
||||
}
|
||||
|
@ -72,7 +62,7 @@ reducers[types.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) {
|
|||
return Object.assign({}, state, { languages });
|
||||
};
|
||||
|
||||
reducers[types.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) {
|
||||
reducers[ACTIONS.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) {
|
||||
const languages = Object.assign({}, state.languages);
|
||||
delete languages[action.data.language];
|
||||
return Object.assign({}, state, { languages });
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import { handleActions } from "util/redux-utils";
|
||||
import * as actions from "constants/action_types";
|
||||
import * as statuses from "constants/shape_shift";
|
||||
import handleActions from 'util/redux-utils';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as STATUSES from 'constants/shape_shift';
|
||||
|
||||
export type ShapeShiftState = {
|
||||
loading: boolean,
|
||||
|
@ -24,40 +24,6 @@ export type ShapeShiftState = {
|
|||
shapeShiftRate: ?number,
|
||||
};
|
||||
|
||||
// All ShapeShift actions that will have some payload
|
||||
export type GetSupportedCoinsSuccess = {
|
||||
type: actions.GET_SUPPORTED_COINS_SUCCESS,
|
||||
data: Array<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
|
||||
// Defined for actions that contain an object in the payload
|
||||
type ShapeShiftMarketInfo = {
|
||||
|
@ -78,6 +44,40 @@ type ShapeShiftErrorResponse = {
|
|||
message: string,
|
||||
};
|
||||
|
||||
// All ShapeShift actions that will have some payload
|
||||
export type GetSupportedCoinsSuccess = {
|
||||
type: ACTIONS.GET_SUPPORTED_COINS_SUCCESS,
|
||||
data: Array<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 = {
|
||||
loading: true,
|
||||
updating: false,
|
||||
|
@ -98,14 +98,12 @@ const defaultState: ShapeShiftState = {
|
|||
|
||||
export default handleActions(
|
||||
{
|
||||
[actions.GET_SUPPORTED_COINS_START]: (
|
||||
state: ShapeShiftState
|
||||
): ShapeShiftState => ({
|
||||
[ACTIONS.GET_SUPPORTED_COINS_START]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||
...state,
|
||||
loading: true,
|
||||
error: undefined,
|
||||
}),
|
||||
[actions.GET_SUPPORTED_COINS_SUCCESS]: (
|
||||
[ACTIONS.GET_SUPPORTED_COINS_SUCCESS]: (
|
||||
state: ShapeShiftState,
|
||||
action: GetSupportedCoinsSuccess
|
||||
): ShapeShiftState => {
|
||||
|
@ -116,15 +114,13 @@ export default handleActions(
|
|||
shiftSupportedCoins,
|
||||
};
|
||||
},
|
||||
[actions.GET_SUPPORTED_COINS_FAIL]: (
|
||||
state: ShapeShiftState
|
||||
): ShapeShiftState => ({
|
||||
[ACTIONS.GET_SUPPORTED_COINS_FAIL]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||
...state,
|
||||
loading: false,
|
||||
error: "Error getting available coins",
|
||||
error: 'Error getting available coins',
|
||||
}),
|
||||
|
||||
[actions.GET_COIN_STATS_START]: (
|
||||
[ACTIONS.GET_COIN_STATS_START]: (
|
||||
state: ShapeShiftState,
|
||||
action: GetCoinStatsStart
|
||||
): ShapeShiftState => {
|
||||
|
@ -135,7 +131,7 @@ export default handleActions(
|
|||
originCoin: coin,
|
||||
};
|
||||
},
|
||||
[actions.GET_COIN_STATS_SUCCESS]: (
|
||||
[ACTIONS.GET_COIN_STATS_SUCCESS]: (
|
||||
state: ShapeShiftState,
|
||||
action: GetCoinStatsSuccess
|
||||
): ShapeShiftState => {
|
||||
|
@ -148,14 +144,12 @@ export default handleActions(
|
|||
originCoinDepositMax: marketInfo.limit,
|
||||
// this will come in scientific notation
|
||||
// toFixed shows the real number, then regex to remove trailing zeros
|
||||
originCoinDepositMin: marketInfo.minimum
|
||||
.toFixed(10)
|
||||
.replace(/\.?0+$/, ""),
|
||||
originCoinDepositMin: marketInfo.minimum.toFixed(10).replace(/\.?0+$/, ''),
|
||||
originCoinDepositFee: marketInfo.minerFee,
|
||||
shapeShiftRate: marketInfo.rate,
|
||||
};
|
||||
},
|
||||
[actions.GET_COIN_STATS_FAIL]: (
|
||||
[ACTIONS.GET_COIN_STATS_FAIL]: (
|
||||
state: ShapeShiftState,
|
||||
action: GetCoinStatsFail
|
||||
): ShapeShiftState => {
|
||||
|
@ -167,13 +161,11 @@ export default handleActions(
|
|||
};
|
||||
},
|
||||
|
||||
[actions.PREPARE_SHAPE_SHIFT_START]: (
|
||||
state: ShapeShiftState
|
||||
): ShapeShiftState => ({
|
||||
[ACTIONS.PREPARE_SHAPE_SHIFT_START]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||
...state,
|
||||
error: undefined,
|
||||
}),
|
||||
[actions.PREPARE_SHAPE_SHIFT_SUCCESS]: (
|
||||
[ACTIONS.PREPARE_SHAPE_SHIFT_SUCCESS]: (
|
||||
state: ShapeShiftState,
|
||||
action: PrepareShapeShiftSuccess
|
||||
) => {
|
||||
|
@ -185,13 +177,10 @@ export default handleActions(
|
|||
shiftCoinType: activeShiftInfo.depositType,
|
||||
shiftReturnAddress: activeShiftInfo.returnAddress,
|
||||
shiftOrderId: activeShiftInfo.orderId,
|
||||
shiftState: statuses.NO_DEPOSITS,
|
||||
shiftState: STATUSES.NO_DEPOSITS,
|
||||
};
|
||||
},
|
||||
[actions.PREPARE_SHAPE_SHIFT_FAIL]: (
|
||||
state: ShapeShiftState,
|
||||
action: PrepareShapeShiftFail
|
||||
) => {
|
||||
[ACTIONS.PREPARE_SHAPE_SHIFT_FAIL]: (state: ShapeShiftState, action: PrepareShapeShiftFail) => {
|
||||
const error: ShapeShiftErrorResponse = action.data;
|
||||
return {
|
||||
...state,
|
||||
|
@ -199,7 +188,7 @@ export default handleActions(
|
|||
};
|
||||
},
|
||||
|
||||
[actions.CLEAR_SHAPE_SHIFT]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||
[ACTIONS.CLEAR_SHAPE_SHIFT]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||
...state,
|
||||
loading: false,
|
||||
updating: false,
|
||||
|
@ -211,14 +200,12 @@ export default handleActions(
|
|||
originCoin: state.shiftSupportedCoins[0],
|
||||
}),
|
||||
|
||||
[actions.GET_ACTIVE_SHIFT_START]: (
|
||||
state: ShapeShiftState
|
||||
): ShapeShiftState => ({
|
||||
[ACTIONS.GET_ACTIVE_SHIFT_START]: (state: ShapeShiftState): ShapeShiftState => ({
|
||||
...state,
|
||||
error: undefined,
|
||||
updating: true,
|
||||
}),
|
||||
[actions.GET_ACTIVE_SHIFT_SUCCESS]: (
|
||||
[ACTIONS.GET_ACTIVE_SHIFT_SUCCESS]: (
|
||||
state: ShapeShiftState,
|
||||
action: GetActiveShiftSuccess
|
||||
): ShapeShiftState => {
|
||||
|
@ -229,7 +216,7 @@ export default handleActions(
|
|||
shiftState: status,
|
||||
};
|
||||
},
|
||||
[actions.GET_ACTIVE_SHIFT_FAIL]: (
|
||||
[ACTIONS.GET_ACTIVE_SHIFT_FAIL]: (
|
||||
state: ShapeShiftState,
|
||||
action: GetActiveShiftFail
|
||||
): ShapeShiftState => {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
// @flow
|
||||
import * as actions from "constants/action_types";
|
||||
import { handleActions } from "util/redux-utils";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import handleActions from 'util/redux-utils';
|
||||
|
||||
export type Subscription = {
|
||||
channelName: string,
|
||||
uri: string,
|
||||
};
|
||||
|
||||
// Subscription redux types
|
||||
export type SubscriptionState = {
|
||||
|
@ -8,30 +13,22 @@ export type SubscriptionState = {
|
|||
hasFetchedSubscriptions: boolean,
|
||||
};
|
||||
|
||||
export type Subscription = {
|
||||
channelName: string,
|
||||
uri: string,
|
||||
};
|
||||
|
||||
// Subscription action types
|
||||
type doChannelSubscribe = {
|
||||
type: actions.CHANNEL_SUBSCRIBE,
|
||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||
data: Subscription,
|
||||
};
|
||||
|
||||
type doChannelUnsubscribe = {
|
||||
type: actions.CHANNEL_UNSUBSCRIBE,
|
||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||
data: Subscription,
|
||||
};
|
||||
|
||||
type HasFetchedSubscriptions = {
|
||||
type: actions.HAS_FETCHED_SUBSCRIPTIONS,
|
||||
type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS,
|
||||
};
|
||||
|
||||
export type Action =
|
||||
| doChannelSubscribe
|
||||
| doChannelUnsubscribe
|
||||
| HasFetchedSubscriptions;
|
||||
export type Action = doChannelSubscribe | doChannelUnsubscribe | HasFetchedSubscriptions;
|
||||
export type Dispatch = (action: Action) => any;
|
||||
|
||||
const defaultState = {
|
||||
|
@ -41,7 +38,7 @@ const defaultState = {
|
|||
|
||||
export default handleActions(
|
||||
{
|
||||
[actions.CHANNEL_SUBSCRIBE]: (
|
||||
[ACTIONS.CHANNEL_SUBSCRIBE]: (
|
||||
state: SubscriptionState,
|
||||
action: doChannelSubscribe
|
||||
): SubscriptionState => {
|
||||
|
@ -54,7 +51,7 @@ export default handleActions(
|
|||
subscriptions: newSubscriptions,
|
||||
};
|
||||
},
|
||||
[actions.CHANNEL_UNSUBSCRIBE]: (
|
||||
[ACTIONS.CHANNEL_UNSUBSCRIBE]: (
|
||||
state: SubscriptionState,
|
||||
action: doChannelUnsubscribe
|
||||
): SubscriptionState => {
|
||||
|
@ -62,20 +59,14 @@ export default handleActions(
|
|||
|
||||
const newSubscriptions = state.subscriptions
|
||||
.slice()
|
||||
.filter(
|
||||
subscription =>
|
||||
subscription.channelName !== subscriptionToRemove.channelName
|
||||
);
|
||||
.filter(subscription => subscription.channelName !== subscriptionToRemove.channelName);
|
||||
|
||||
return {
|
||||
...state,
|
||||
subscriptions: newSubscriptions,
|
||||
};
|
||||
},
|
||||
[actions.HAS_FETCHED_SUBSCRIPTIONS]: (
|
||||
state: SubscriptionState,
|
||||
action: HasFetchedSubscriptions
|
||||
): SubscriptionState => ({
|
||||
[ACTIONS.HAS_FETCHED_SUBSCRIPTIONS]: (state: SubscriptionState): SubscriptionState => ({
|
||||
...state,
|
||||
hasFetchedSubscriptions: true,
|
||||
}),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
|
||||
|
@ -6,9 +6,9 @@ const defaultState = {
|
|||
authenticationIsPending: false,
|
||||
userIsPending: false,
|
||||
emailNewIsPending: false,
|
||||
emailNewErrorMessage: "",
|
||||
emailToVerify: "",
|
||||
inviteNewErrorMessage: "",
|
||||
emailNewErrorMessage: '',
|
||||
emailToVerify: '',
|
||||
inviteNewErrorMessage: '',
|
||||
inviteNewIsPending: false,
|
||||
inviteStatusIsPending: false,
|
||||
invitesRemaining: undefined,
|
||||
|
@ -16,7 +16,7 @@ const defaultState = {
|
|||
user: undefined,
|
||||
};
|
||||
|
||||
reducers[types.AUTHENTICATION_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.AUTHENTICATION_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
authenticationIsPending: true,
|
||||
userIsPending: true,
|
||||
|
@ -24,7 +24,7 @@ reducers[types.AUTHENTICATION_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.AUTHENTICATION_SUCCESS] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
authenticationIsPending: false,
|
||||
userIsPending: false,
|
||||
|
@ -32,7 +32,7 @@ reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.AUTHENTICATION_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.AUTHENTICATION_FAILURE] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
authenticationIsPending: false,
|
||||
userIsPending: false,
|
||||
|
@ -40,35 +40,35 @@ reducers[types.AUTHENTICATION_FAILURE] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_FETCH_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.USER_FETCH_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
userIsPending: true,
|
||||
user: defaultState.user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_FETCH_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.USER_FETCH_SUCCESS] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
userIsPending: false,
|
||||
user: action.data.user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_FETCH_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.USER_FETCH_FAILURE] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
userIsPending: true,
|
||||
user: null,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_NEW_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
emailNewIsPending: true,
|
||||
emailNewErrorMessage: "",
|
||||
emailNewErrorMessage: '',
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
|
||||
const user = Object.assign({}, state.user);
|
||||
user.primary_email = action.data.email;
|
||||
return Object.assign({}, state, {
|
||||
|
@ -78,68 +78,67 @@ reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) {
|
||||
const user = Object.assign({}, state.user);
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_EXISTS] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
emailToVerify: action.data.email,
|
||||
emailNewIsPending: false,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_NEW_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_FAILURE] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
emailNewIsPending: false,
|
||||
emailNewErrorMessage: action.data.error,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_VERIFY_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.USER_EMAIL_VERIFY_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
emailVerifyIsPending: true,
|
||||
emailVerifyErrorMessage: "",
|
||||
emailVerifyErrorMessage: '',
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) {
|
||||
const user = Object.assign({}, state.user);
|
||||
user.primary_email = action.data.email;
|
||||
return Object.assign({}, state, {
|
||||
emailToVerify: "",
|
||||
emailToVerify: '',
|
||||
emailVerifyIsPending: false,
|
||||
user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_EMAIL_VERIFY_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.USER_EMAIL_VERIFY_FAILURE] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
emailVerifyIsPending: false,
|
||||
emailVerifyErrorMessage: action.data.error,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_IDENTITY_VERIFY_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.USER_IDENTITY_VERIFY_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
identityVerifyIsPending: true,
|
||||
identityVerifyErrorMessage: "",
|
||||
identityVerifyErrorMessage: '',
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
identityVerifyIsPending: false,
|
||||
identityVerifyErrorMessage: "",
|
||||
identityVerifyErrorMessage: '',
|
||||
user: action.data.user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
identityVerifyIsPending: false,
|
||||
identityVerifyErrorMessage: action.data.error,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) {
|
||||
const { token } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
|
@ -147,13 +146,13 @@ reducers[types.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_INVITE_STATUS_FETCH_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
inviteStatusIsPending: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
inviteStatusIsPending: false,
|
||||
invitesRemaining: action.data.invitesRemaining,
|
||||
|
@ -161,28 +160,28 @@ reducers[types.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_INVITE_NEW_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.USER_INVITE_NEW_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
inviteNewIsPending: true,
|
||||
inviteNewErrorMessage: "",
|
||||
inviteNewErrorMessage: '',
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_INVITE_NEW_SUCCESS] = function(state, action) {
|
||||
reducers[ACTIONS.USER_INVITE_NEW_SUCCESS] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
inviteNewIsPending: false,
|
||||
inviteNewErrorMessage: "",
|
||||
inviteNewErrorMessage: '',
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_INVITE_NEW_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.USER_INVITE_NEW_FAILURE] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
inviteNewIsPending: false,
|
||||
inviteNewErrorMessage: action.data.error.message,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.USER_INVITE_STATUS_FETCH_FAILURE] = function(state, action) {
|
||||
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
inviteStatusIsPending: false,
|
||||
invitesRemaining: null,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as types from "constants/action_types";
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const address = localStorage.getItem("receiveAddress");
|
||||
const receiveAddress = localStorage.getItem('receiveAddress');
|
||||
const buildDraftTransaction = () => ({
|
||||
amount: undefined,
|
||||
address: undefined,
|
||||
|
@ -12,19 +12,19 @@ const defaultState = {
|
|||
blocks: {},
|
||||
transactions: {},
|
||||
fetchingTransactions: false,
|
||||
receiveAddress: address,
|
||||
receiveAddress,
|
||||
gettingNewAddress: false,
|
||||
draftTransaction: buildDraftTransaction(),
|
||||
sendingSupport: false,
|
||||
};
|
||||
|
||||
reducers[types.FETCH_TRANSACTIONS_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_TRANSACTIONS_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
fetchingTransactions: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
|
||||
const byId = Object.assign({}, state.transactions);
|
||||
|
||||
const { transactions } = action.data;
|
||||
|
@ -39,41 +39,41 @@ reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.GET_NEW_ADDRESS_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.GET_NEW_ADDRESS_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
gettingNewAddress: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.GET_NEW_ADDRESS_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.GET_NEW_ADDRESS_COMPLETED] = function(state, action) {
|
||||
const { address } = action.data;
|
||||
|
||||
localStorage.setItem("receiveAddress", address);
|
||||
localStorage.setItem('receiveAddress', address);
|
||||
return Object.assign({}, state, {
|
||||
gettingNewAddress: false,
|
||||
receiveAddress: address,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.UPDATE_BALANCE] = function(state, action) {
|
||||
reducers[ACTIONS.UPDATE_BALANCE] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
balance: action.data.balance,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CHECK_ADDRESS_IS_MINE_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
checkingAddressOwnership: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
checkingAddressOwnership: false,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) {
|
||||
reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) {
|
||||
const oldDraft = state.draftTransaction;
|
||||
const newDraft = Object.assign({}, oldDraft, {
|
||||
amount: parseFloat(action.data.amount),
|
||||
|
@ -84,7 +84,7 @@ reducers[types.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) {
|
||||
reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) {
|
||||
const oldDraft = state.draftTransaction;
|
||||
const newDraft = Object.assign({}, oldDraft, {
|
||||
address: action.data.address,
|
||||
|
@ -95,7 +95,7 @@ reducers[types.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.SEND_TRANSACTION_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.SEND_TRANSACTION_STARTED] = function(state) {
|
||||
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
||||
sending: true,
|
||||
});
|
||||
|
@ -105,13 +105,13 @@ reducers[types.SEND_TRANSACTION_STARTED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.SEND_TRANSACTION_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.SEND_TRANSACTION_COMPLETED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
draftTransaction: buildDraftTransaction(),
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) {
|
||||
reducers[ACTIONS.SEND_TRANSACTION_FAILED] = function(state, action) {
|
||||
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
||||
sending: false,
|
||||
error: action.data.error,
|
||||
|
@ -122,28 +122,28 @@ reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) {
|
||||
reducers[ACTIONS.SUPPORT_TRANSACTION_STARTED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
sendingSupport: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) {
|
||||
reducers[ACTIONS.SUPPORT_TRANSACTION_COMPLETED] = function(state) {
|
||||
return Object.assign({}, state, {
|
||||
sendingSupport: false,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) {
|
||||
reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
error: action.data.error,
|
||||
sendingSupport: false,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.FETCH_BLOCK_SUCCESS] = (state, action) => {
|
||||
const { block, block: { height } } = action.data,
|
||||
blocks = Object.assign({}, state.blocks);
|
||||
reducers[ACTIONS.FETCH_BLOCK_SUCCESS] = (state, action) => {
|
||||
const { block, block: { height } } = action.data;
|
||||
const blocks = Object.assign({}, state.blocks);
|
||||
|
||||
blocks[height] = block;
|
||||
|
||||
|
|
|
@ -1,32 +1,26 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
export const _selectState = state => state.app || {};
|
||||
export const selectState = state => state.app || {};
|
||||
|
||||
export const selectPlatform = createSelector(
|
||||
_selectState,
|
||||
state => state.platform
|
||||
);
|
||||
export const selectPlatform = createSelector(selectState, state => state.platform);
|
||||
|
||||
export const selectUpdateUrl = createSelector(selectPlatform, platform => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return "https://lbry.io/get/lbry.dmg";
|
||||
case "linux":
|
||||
return "https://lbry.io/get/lbry.deb";
|
||||
case "win32":
|
||||
return "https://lbry.io/get/lbry.exe";
|
||||
case 'darwin':
|
||||
return 'https://lbry.io/get/lbry.dmg';
|
||||
case 'linux':
|
||||
return 'https://lbry.io/get/lbry.deb';
|
||||
case 'win32':
|
||||
return 'https://lbry.io/get/lbry.exe';
|
||||
default:
|
||||
throw "Unknown platform";
|
||||
throw Error('Unknown platform');
|
||||
}
|
||||
});
|
||||
|
||||
export const selectRemoteVersion = createSelector(
|
||||
_selectState,
|
||||
state => state.remoteVersion
|
||||
);
|
||||
export const selectRemoteVersion = createSelector(selectState, state => state.remoteVersion);
|
||||
|
||||
export const selectIsUpgradeAvailable = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.isUpgradeAvailable
|
||||
);
|
||||
|
||||
|
@ -35,81 +29,54 @@ export const selectUpgradeFilename = createSelector(
|
|||
selectRemoteVersion,
|
||||
(platform, version) => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
case 'darwin':
|
||||
return `LBRY_${version}.dmg`;
|
||||
case "linux":
|
||||
case 'linux':
|
||||
return `LBRY_${version}_amd64.deb`;
|
||||
case "win32":
|
||||
case 'win32':
|
||||
return `LBRY_${version}.exe`;
|
||||
default:
|
||||
throw "Unknown platform";
|
||||
throw Error('Unknown platform');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const selectCurrentModal = createSelector(
|
||||
_selectState,
|
||||
state => state.modal
|
||||
);
|
||||
export const selectCurrentModal = createSelector(selectState, state => state.modal);
|
||||
|
||||
export const selectDownloadProgress = createSelector(
|
||||
_selectState,
|
||||
state => state.downloadProgress
|
||||
);
|
||||
export const selectDownloadProgress = createSelector(selectState, state => state.downloadProgress);
|
||||
|
||||
export const selectDownloadComplete = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.upgradeDownloadCompleted
|
||||
);
|
||||
|
||||
export const selectIsUpgradeSkipped = createSelector(
|
||||
_selectState,
|
||||
state => state.isUpgradeSkipped
|
||||
);
|
||||
export const selectIsUpgradeSkipped = createSelector(selectState, state => state.isUpgradeSkipped);
|
||||
|
||||
export const selectUpgradeDownloadPath = createSelector(
|
||||
_selectState,
|
||||
state => state.downloadPath
|
||||
);
|
||||
export const selectUpgradeDownloadPath = createSelector(selectState, state => state.downloadPath);
|
||||
|
||||
export const selectUpgradeDownloadItem = createSelector(
|
||||
_selectState,
|
||||
state => state.downloadItem
|
||||
);
|
||||
export const selectUpgradeDownloadItem = createSelector(selectState, state => state.downloadItem);
|
||||
|
||||
export const selectModalProps = createSelector(
|
||||
_selectState,
|
||||
state => state.modalProps
|
||||
);
|
||||
export const selectModalProps = createSelector(selectState, state => state.modalProps);
|
||||
|
||||
export const selectDaemonReady = createSelector(
|
||||
_selectState,
|
||||
state => state.daemonReady
|
||||
);
|
||||
export const selectDaemonReady = createSelector(selectState, state => state.daemonReady);
|
||||
|
||||
export const selectDaemonVersionMatched = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.daemonVersionMatched
|
||||
);
|
||||
|
||||
export const selectSnackBar = createSelector(
|
||||
_selectState,
|
||||
state => state.snackBar || {}
|
||||
);
|
||||
export const selectSnackBar = createSelector(selectState, state => state.snackBar || {});
|
||||
|
||||
export const selectSnackBarSnacks = createSelector(
|
||||
selectSnackBar,
|
||||
snackBar => snackBar.snacks || []
|
||||
);
|
||||
|
||||
export const selectBadgeNumber = createSelector(
|
||||
_selectState,
|
||||
state => state.badgeNumber
|
||||
);
|
||||
export const selectBadgeNumber = createSelector(selectState, state => state.badgeNumber);
|
||||
|
||||
export const selectCurrentLanguage = createSelector(
|
||||
_selectState,
|
||||
() => app.i18n.getLocale() || "en"
|
||||
selectState,
|
||||
() => app.i18n.getLocale() || 'en'
|
||||
);
|
||||
|
||||
export const selectVolume = createSelector(_selectState, state => state.volume);
|
||||
export const selectVolume = createSelector(selectState, state => state.volume);
|
||||
|
|
|
@ -1,22 +1,7 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const _selectState = state => state.availability;
|
||||
const selectState = state => state.availability;
|
||||
|
||||
export const selectAvailabilityByUri = createSelector(
|
||||
_selectState,
|
||||
state => state.byUri || {}
|
||||
);
|
||||
const selectFetchingAvailability = createSelector(selectState, state => state.fetching || {});
|
||||
|
||||
export const makeSelectIsAvailableForUri = uri =>
|
||||
createSelector(
|
||||
selectAvailabilityByUri,
|
||||
byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0)
|
||||
);
|
||||
|
||||
export const selectFetchingAvailability = createSelector(
|
||||
_selectState,
|
||||
state => state.fetching || {}
|
||||
);
|
||||
|
||||
export const makeSelectFetchingAvailabilityForUri = uri =>
|
||||
createSelector(selectFetchingAvailability, byUri => byUri && byUri[uri]);
|
||||
export { selectFetchingAvailability as default };
|
||||
|
|
|
@ -1,77 +1,79 @@
|
|||
import { createSelector } from "reselect";
|
||||
import lbryuri from "lbryuri";
|
||||
import { makeSelectCurrentParam } from "./navigation";
|
||||
import { createSelector } from 'reselect';
|
||||
import Lbryuri from 'lbryuri';
|
||||
import { makeSelectCurrentParam } from 'redux/selectors/navigation';
|
||||
|
||||
const _selectState = state => state.claims || {};
|
||||
const selectState = state => state.claims || {};
|
||||
|
||||
export const selectClaimsById = createSelector(
|
||||
_selectState,
|
||||
state => state.byId || {}
|
||||
);
|
||||
export const selectClaimsById = createSelector(selectState, state => state.byId || {});
|
||||
|
||||
export const selectClaimsByUri = createSelector(
|
||||
_selectState,
|
||||
selectClaimsById,
|
||||
(state, byId) => {
|
||||
const byUri = state.claimsByUri || {};
|
||||
const claims = {};
|
||||
export const selectClaimsByUri = createSelector(selectState, selectClaimsById, (state, byId) => {
|
||||
const byUri = state.claimsByUri || {};
|
||||
const claims = {};
|
||||
|
||||
Object.keys(byUri).forEach(uri => {
|
||||
const claimId = byUri[uri];
|
||||
Object.keys(byUri).forEach(uri => {
|
||||
const claimId = byUri[uri];
|
||||
|
||||
// NOTE returning a null claim allows us to differentiate between an
|
||||
// undefined (never fetched claim) and one which just doesn't exist. Not
|
||||
// the cleanest solution but couldn't think of anything better right now
|
||||
if (claimId === null) {
|
||||
claims[uri] = null;
|
||||
} else {
|
||||
const claim = byId[claimId];
|
||||
// NOTE returning a null claim allows us to differentiate between an
|
||||
// undefined (never fetched claim) and one which just doesn't exist. Not
|
||||
// the cleanest solution but couldn't think of anything better right now
|
||||
if (claimId === null) {
|
||||
claims[uri] = null;
|
||||
} else {
|
||||
const claim = byId[claimId];
|
||||
|
||||
claims[uri] = claim;
|
||||
}
|
||||
});
|
||||
claims[uri] = claim;
|
||||
}
|
||||
});
|
||||
|
||||
return claims;
|
||||
}
|
||||
);
|
||||
return claims;
|
||||
});
|
||||
|
||||
export const selectAllClaimsByChannel = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.claimsByChannel || {}
|
||||
);
|
||||
|
||||
export const makeSelectClaimForUri = uri =>
|
||||
createSelector(
|
||||
selectClaimsByUri,
|
||||
claims => claims && claims[lbryuri.normalize(uri)]
|
||||
);
|
||||
createSelector(selectClaimsByUri, claims => claims && claims[Lbryuri.normalize(uri)]);
|
||||
|
||||
export const selectMyClaimsRaw = createSelector(selectState, state => state.myClaims);
|
||||
|
||||
export const selectAbandoningIds = createSelector(selectState, state =>
|
||||
Object.keys(state.abandoningById || {})
|
||||
);
|
||||
|
||||
export const selectMyActiveClaims = createSelector(
|
||||
selectMyClaimsRaw,
|
||||
selectAbandoningIds,
|
||||
(claims, abandoningIds) =>
|
||||
new Set(
|
||||
claims &&
|
||||
claims
|
||||
.map(claim => claim.claim_id)
|
||||
.filter(claimId => Object.keys(abandoningIds).indexOf(claimId) === -1)
|
||||
)
|
||||
);
|
||||
|
||||
export const makeSelectClaimIsMine = rawUri => {
|
||||
const uri = lbryuri.normalize(rawUri);
|
||||
const uri = Lbryuri.normalize(rawUri);
|
||||
return createSelector(
|
||||
selectClaimsByUri,
|
||||
selectMyActiveClaims,
|
||||
(claims, myClaims) =>
|
||||
claims &&
|
||||
claims[uri] &&
|
||||
claims[uri].claim_id &&
|
||||
myClaims.has(claims[uri].claim_id)
|
||||
claims && claims[uri] && claims[uri].claim_id && myClaims.has(claims[uri].claim_id)
|
||||
);
|
||||
};
|
||||
|
||||
export const selectAllFetchingChannelClaims = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.fetchingChannelClaims || {}
|
||||
);
|
||||
|
||||
export const makeSelectFetchingChannelClaims = uri =>
|
||||
createSelector(
|
||||
selectAllFetchingChannelClaims,
|
||||
fetching => fetching && fetching[uri]
|
||||
);
|
||||
createSelector(selectAllFetchingChannelClaims, fetching => fetching && fetching[uri]);
|
||||
|
||||
export const makeSelectClaimsInChannelForCurrentPage = uri => {
|
||||
const pageSelector = makeSelectCurrentParam("page");
|
||||
const pageSelector = makeSelectCurrentParam('page');
|
||||
|
||||
return createSelector(
|
||||
selectClaimsById,
|
||||
|
@ -90,53 +92,27 @@ export const makeSelectClaimsInChannelForCurrentPage = uri => {
|
|||
|
||||
export const makeSelectMetadataForUri = uri =>
|
||||
createSelector(makeSelectClaimForUri(uri), claim => {
|
||||
const metadata =
|
||||
claim && claim.value && claim.value.stream && claim.value.stream.metadata;
|
||||
const metadata = claim && claim.value && claim.value.stream && claim.value.stream.metadata;
|
||||
|
||||
const value = metadata || (claim === undefined ? undefined : null);
|
||||
return value;
|
||||
});
|
||||
|
||||
export const makeSelectTitleForUri = uri =>
|
||||
createSelector(
|
||||
makeSelectMetadataForUri(uri),
|
||||
metadata => metadata && metadata.title
|
||||
);
|
||||
createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title);
|
||||
|
||||
export const makeSelectContentTypeForUri = uri =>
|
||||
createSelector(makeSelectClaimForUri(uri), claim => {
|
||||
const source =
|
||||
claim && claim.value && claim.value.stream && claim.value.stream.source;
|
||||
const source = claim && claim.value && claim.value.stream && claim.value.stream.source;
|
||||
return source ? source.contentType : undefined;
|
||||
});
|
||||
|
||||
export const selectIsFetchingClaimListMine = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => !!state.isFetchingClaimListMine
|
||||
);
|
||||
|
||||
export const selectMyClaimsRaw = createSelector(
|
||||
_selectState,
|
||||
state => state.myClaims
|
||||
);
|
||||
|
||||
export const selectAbandoningIds = createSelector(_selectState, state =>
|
||||
Object.keys(state.abandoningById || {})
|
||||
);
|
||||
|
||||
export const selectMyActiveClaims = createSelector(
|
||||
selectMyClaimsRaw,
|
||||
selectAbandoningIds,
|
||||
(claims, abandoningIds) =>
|
||||
new Set(
|
||||
claims &&
|
||||
claims
|
||||
.map(claim => claim.claim_id)
|
||||
.filter(claimId => Object.keys(abandoningIds).indexOf(claimId) === -1)
|
||||
)
|
||||
);
|
||||
|
||||
export const selectPendingClaims = createSelector(_selectState, state =>
|
||||
export const selectPendingClaims = createSelector(selectState, state =>
|
||||
Object.values(state.pendingById || {})
|
||||
);
|
||||
|
||||
|
@ -151,46 +127,38 @@ export const selectMyClaims = createSelector(
|
|||
myClaimIds.forEach(id => {
|
||||
const claim = byId[id];
|
||||
|
||||
if (claim && abandoningIds.indexOf(id) == -1) claims.push(claim);
|
||||
if (claim && abandoningIds.indexOf(id) === -1) claims.push(claim);
|
||||
});
|
||||
|
||||
return [...claims, ...pendingClaims];
|
||||
}
|
||||
);
|
||||
|
||||
export const selectMyClaimsWithoutChannels = createSelector(
|
||||
selectMyClaims,
|
||||
myClaims => myClaims.filter(claim => !claim.name.match(/^@/))
|
||||
export const selectMyClaimsWithoutChannels = createSelector(selectMyClaims, myClaims =>
|
||||
myClaims.filter(claim => !claim.name.match(/^@/))
|
||||
);
|
||||
|
||||
export const selectAllMyClaimsByOutpoint = createSelector(
|
||||
selectMyClaimsRaw,
|
||||
claims =>
|
||||
new Set(
|
||||
claims && claims.length
|
||||
? claims.map(claim => `${claim.txid}:${claim.nout}`)
|
||||
: null
|
||||
)
|
||||
new Set(claims && claims.length ? claims.map(claim => `${claim.txid}:${claim.nout}`) : null)
|
||||
);
|
||||
|
||||
export const selectMyClaimsOutpoints = createSelector(
|
||||
selectMyClaims,
|
||||
myClaims => {
|
||||
const outpoints = [];
|
||||
export const selectMyClaimsOutpoints = createSelector(selectMyClaims, myClaims => {
|
||||
const outpoints = [];
|
||||
|
||||
myClaims.forEach(claim => outpoints.push(`${claim.txid}:${claim.nout}`));
|
||||
myClaims.forEach(claim => outpoints.push(`${claim.txid}:${claim.nout}`));
|
||||
|
||||
return outpoints;
|
||||
}
|
||||
);
|
||||
return outpoints;
|
||||
});
|
||||
|
||||
export const selectFetchingMyChannels = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => !!state.fetchingMyChannels
|
||||
);
|
||||
|
||||
export const selectMyChannelClaims = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
selectClaimsById,
|
||||
(state, byId) => {
|
||||
const ids = state.myChannelClaims || [];
|
||||
|
|
|
@ -1,35 +1,26 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
export const _selectState = state => state.content || {};
|
||||
export const selectState = state => state.content || {};
|
||||
|
||||
export const selectFeaturedUris = createSelector(
|
||||
_selectState,
|
||||
state => state.featuredUris
|
||||
);
|
||||
export const selectFeaturedUris = createSelector(selectState, state => state.featuredUris);
|
||||
|
||||
export const selectFetchingFeaturedUris = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => !!state.fetchingFeaturedContent
|
||||
);
|
||||
|
||||
export const selectResolvingUris = createSelector(
|
||||
_selectState,
|
||||
state => state.resolvingUris || []
|
||||
);
|
||||
export const selectResolvingUris = createSelector(selectState, state => state.resolvingUris || []);
|
||||
|
||||
export const selectPlayingUri = createSelector(
|
||||
_selectState,
|
||||
state => state.playingUri
|
||||
);
|
||||
export const selectPlayingUri = createSelector(selectState, state => state.playingUri);
|
||||
|
||||
export const makeSelectIsUriResolving = uri =>
|
||||
createSelector(
|
||||
selectResolvingUris,
|
||||
resolvingUris => resolvingUris && resolvingUris.indexOf(uri) != -1
|
||||
resolvingUris => resolvingUris && resolvingUris.indexOf(uri) !== -1
|
||||
);
|
||||
|
||||
export const selectChannelClaimCounts = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.channelClaimCounts || {}
|
||||
);
|
||||
|
||||
|
@ -43,6 +34,6 @@ export const makeSelectTotalPagesForChannel = uri =>
|
|||
);
|
||||
|
||||
export const selectRewardContentClaimIds = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.rewardedContentClaimIds
|
||||
);
|
||||
|
|
|
@ -1,33 +1,20 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { selectCurrentParams } from "redux/selectors/navigation";
|
||||
import { createSelector } from 'reselect';
|
||||
import { selectCurrentParams } from 'redux/selectors/navigation';
|
||||
|
||||
export const _selectState = state => state.costInfo || {};
|
||||
export const selectState = state => state.costInfo || {};
|
||||
|
||||
export const selectAllCostInfoByUri = createSelector(
|
||||
_selectState,
|
||||
state => state.byUri || {}
|
||||
);
|
||||
export const selectAllCostInfoByUri = createSelector(selectState, state => state.byUri || {});
|
||||
|
||||
export const makeSelectCostInfoForUri = uri =>
|
||||
createSelector(
|
||||
selectAllCostInfoByUri,
|
||||
costInfos => costInfos && costInfos[uri]
|
||||
);
|
||||
createSelector(selectAllCostInfoByUri, costInfos => costInfos && costInfos[uri]);
|
||||
|
||||
export const selectCostForCurrentPageUri = createSelector(
|
||||
selectAllCostInfoByUri,
|
||||
selectCurrentParams,
|
||||
(costInfo, params) =>
|
||||
params.uri && costInfo[params.uri] ? costInfo[params.uri].cost : undefined
|
||||
(costInfo, params) => (params.uri && costInfo[params.uri] ? costInfo[params.uri].cost : undefined)
|
||||
);
|
||||
|
||||
export const selectFetchingCostInfo = createSelector(
|
||||
_selectState,
|
||||
state => state.fetching || {}
|
||||
);
|
||||
export const selectFetchingCostInfo = createSelector(selectState, state => state.fetching || {});
|
||||
|
||||
export const makeSelectFetchingCostInfoForUri = uri =>
|
||||
createSelector(
|
||||
selectFetchingCostInfo,
|
||||
fetchingByUri => fetchingByUri && fetchingByUri[uri]
|
||||
);
|
||||
createSelector(selectFetchingCostInfo, fetchingByUri => fetchingByUri && fetchingByUri[uri]);
|
||||
|
|
|
@ -1,45 +1,39 @@
|
|||
import lbry from "lbry";
|
||||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
selectClaimsByUri,
|
||||
selectIsFetchingClaimListMine,
|
||||
selectMyClaims,
|
||||
selectMyClaimsOutpoints,
|
||||
} from "redux/selectors/claims";
|
||||
} from 'redux/selectors/claims';
|
||||
|
||||
export const _selectState = state => state.fileInfo || {};
|
||||
export const selectState = state => state.fileInfo || {};
|
||||
|
||||
export const selectFileInfosByOutpoint = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.byOutpoint || {}
|
||||
);
|
||||
|
||||
export const selectIsFetchingFileList = createSelector(
|
||||
_selectState,
|
||||
state => !!state.isFetchingFileList
|
||||
selectState,
|
||||
state => state.isFetchingFileList
|
||||
);
|
||||
|
||||
export const selectIsFetchingFileListDownloadedOrPublished = createSelector(
|
||||
selectIsFetchingFileList,
|
||||
selectIsFetchingClaimListMine,
|
||||
(isFetchingFileList, isFetchingClaimListMine) =>
|
||||
isFetchingFileList || isFetchingClaimListMine
|
||||
(isFetchingFileList, isFetchingClaimListMine) => isFetchingFileList || isFetchingClaimListMine
|
||||
);
|
||||
|
||||
export const makeSelectFileInfoForUri = uri =>
|
||||
createSelector(
|
||||
selectClaimsByUri,
|
||||
selectFileInfosByOutpoint,
|
||||
(claims, byOutpoint) => {
|
||||
const claim = claims[uri],
|
||||
outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
|
||||
createSelector(selectClaimsByUri, selectFileInfosByOutpoint, (claims, byOutpoint) => {
|
||||
const claim = claims[uri];
|
||||
const outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
|
||||
|
||||
return outpoint ? byOutpoint[outpoint] : undefined;
|
||||
}
|
||||
);
|
||||
return outpoint ? byOutpoint[outpoint] : undefined;
|
||||
});
|
||||
|
||||
export const selectDownloadingByOutpoint = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.downloadingByOutpoint || {}
|
||||
);
|
||||
|
||||
|
@ -53,17 +47,13 @@ export const makeSelectDownloadingForUri = uri =>
|
|||
}
|
||||
);
|
||||
|
||||
export const selectUrisLoading = createSelector(
|
||||
_selectState,
|
||||
state => state.urisLoading || {}
|
||||
);
|
||||
export const selectUrisLoading = createSelector(selectState, state => state.urisLoading || {});
|
||||
|
||||
export const makeSelectLoadingForUri = uri =>
|
||||
createSelector(selectUrisLoading, byUri => byUri && byUri[uri]);
|
||||
|
||||
export const selectFileInfosPendingPublish = createSelector(
|
||||
_selectState,
|
||||
state => Object.values(state.pendingByOutpoint || {})
|
||||
export const selectFileInfosPendingPublish = createSelector(selectState, state =>
|
||||
Object.values(state.pendingByOutpoint || {})
|
||||
);
|
||||
|
||||
export const selectFileInfosDownloaded = createSelector(
|
||||
|
@ -141,18 +131,15 @@ export const selectDownloadingFileInfos = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
export const selectTotalDownloadProgress = createSelector(
|
||||
selectDownloadingFileInfos,
|
||||
fileInfos => {
|
||||
const progress = [];
|
||||
export const selectTotalDownloadProgress = createSelector(selectDownloadingFileInfos, fileInfos => {
|
||||
const progress = [];
|
||||
|
||||
fileInfos.forEach(fileInfo => {
|
||||
progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100);
|
||||
});
|
||||
fileInfos.forEach(fileInfo => {
|
||||
progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100);
|
||||
});
|
||||
|
||||
const totalProgress = progress.reduce((a, b) => a + b, 0);
|
||||
const totalProgress = progress.reduce((a, b) => a + b, 0);
|
||||
|
||||
if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
|
||||
return -1;
|
||||
}
|
||||
);
|
||||
if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
|
||||
return -1;
|
||||
});
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { parseQueryParams, toQueryString } from "util/query_params";
|
||||
import * as settings from "constants/settings.js";
|
||||
import lbryuri from "lbryuri";
|
||||
import { createSelector } from 'reselect';
|
||||
import { parseQueryParams, toQueryString } from 'util/query_params';
|
||||
import Lbryuri from 'lbryuri';
|
||||
|
||||
export const _selectState = state => state.navigation || {};
|
||||
export const selectState = state => state.navigation || {};
|
||||
|
||||
export const selectCurrentPath = createSelector(
|
||||
_selectState,
|
||||
state => state.currentPath
|
||||
);
|
||||
export const selectCurrentPath = createSelector(selectState, state => state.currentPath);
|
||||
|
||||
export const computePageFromPath = path =>
|
||||
path.replace(/^\//, "").split("?")[0];
|
||||
export const computePageFromPath = path => path.replace(/^\//, '').split('?')[0];
|
||||
|
||||
export const selectCurrentPage = createSelector(selectCurrentPath, path =>
|
||||
computePageFromPath(path)
|
||||
|
@ -21,50 +16,47 @@ export const selectCurrentParams = createSelector(selectCurrentPath, path => {
|
|||
if (path === undefined) return {};
|
||||
if (!path.match(/\?/)) return {};
|
||||
|
||||
return parseQueryParams(path.split("?")[1]);
|
||||
return parseQueryParams(path.split('?')[1]);
|
||||
});
|
||||
|
||||
export const makeSelectCurrentParam = param =>
|
||||
createSelector(
|
||||
selectCurrentParams,
|
||||
params => (params ? params[param] : undefined)
|
||||
);
|
||||
createSelector(selectCurrentParams, params => (params ? params[param] : undefined));
|
||||
|
||||
export const selectHeaderLinks = createSelector(selectCurrentPage, page => {
|
||||
// This contains intentional fall throughs
|
||||
switch (page) {
|
||||
case "wallet":
|
||||
case "history":
|
||||
case "send":
|
||||
case "getcredits":
|
||||
case "invite":
|
||||
case "rewards":
|
||||
case "backup":
|
||||
case 'wallet':
|
||||
case 'history':
|
||||
case 'send':
|
||||
case 'getcredits':
|
||||
case 'invite':
|
||||
case 'rewards':
|
||||
case 'backup':
|
||||
return {
|
||||
wallet: __("Overview"),
|
||||
getcredits: __("Get Credits"),
|
||||
send: __("Send / Receive"),
|
||||
rewards: __("Rewards"),
|
||||
invite: __("Invites"),
|
||||
history: __("History"),
|
||||
wallet: __('Overview'),
|
||||
getcredits: __('Get Credits'),
|
||||
send: __('Send / Receive'),
|
||||
rewards: __('Rewards'),
|
||||
invite: __('Invites'),
|
||||
history: __('History'),
|
||||
};
|
||||
case "downloaded":
|
||||
case "published":
|
||||
case 'downloaded':
|
||||
case 'published':
|
||||
return {
|
||||
downloaded: __("Downloaded"),
|
||||
published: __("Published"),
|
||||
downloaded: __('Downloaded'),
|
||||
published: __('Published'),
|
||||
};
|
||||
case "settings":
|
||||
case "help":
|
||||
case 'settings':
|
||||
case 'help':
|
||||
return {
|
||||
settings: __("Settings"),
|
||||
help: __("Help"),
|
||||
settings: __('Settings'),
|
||||
help: __('Help'),
|
||||
};
|
||||
case "discover":
|
||||
case "subscriptions":
|
||||
case 'discover':
|
||||
case 'subscriptions':
|
||||
return {
|
||||
discover: __("Discover"),
|
||||
subscriptions: __("Subscriptions"),
|
||||
discover: __('Discover'),
|
||||
subscriptions: __('Subscriptions'),
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
|
@ -76,86 +68,72 @@ export const selectPageTitle = createSelector(
|
|||
selectCurrentParams,
|
||||
(page, params) => {
|
||||
switch (page) {
|
||||
case "settings":
|
||||
return __("Settings");
|
||||
case "report":
|
||||
return __("Report");
|
||||
case "wallet":
|
||||
return __("Wallet");
|
||||
case "send":
|
||||
return __("Send or Receive LBRY Credits");
|
||||
case "getcredits":
|
||||
return __("Get LBRY Credits");
|
||||
case "backup":
|
||||
return __("Backup Your Wallet");
|
||||
case "rewards":
|
||||
return __("Rewards");
|
||||
case "invite":
|
||||
return __("Invites");
|
||||
case "start":
|
||||
return __("Start");
|
||||
case "publish":
|
||||
return params.id ? __("Edit") : __("Publish");
|
||||
case "help":
|
||||
return __("Help");
|
||||
case "developer":
|
||||
return __("Developer");
|
||||
case "show": {
|
||||
const parts = [lbryuri.normalize(params.uri)];
|
||||
case 'settings':
|
||||
return __('Settings');
|
||||
case 'report':
|
||||
return __('Report');
|
||||
case 'wallet':
|
||||
return __('Wallet');
|
||||
case 'send':
|
||||
return __('Send or Receive LBRY Credits');
|
||||
case 'getcredits':
|
||||
return __('Get LBRY Credits');
|
||||
case 'backup':
|
||||
return __('Backup Your Wallet');
|
||||
case 'rewards':
|
||||
return __('Rewards');
|
||||
case 'invite':
|
||||
return __('Invites');
|
||||
case 'start':
|
||||
return __('Start');
|
||||
case 'publish':
|
||||
return params.id ? __('Edit') : __('Publish');
|
||||
case 'help':
|
||||
return __('Help');
|
||||
case 'developer':
|
||||
return __('Developer');
|
||||
case 'show': {
|
||||
const parts = [Lbryuri.normalize(params.uri)];
|
||||
// If the params has any keys other than "uri"
|
||||
if (Object.keys(params).length > 1) {
|
||||
parts.push(toQueryString(Object.assign({}, params, { uri: null })));
|
||||
}
|
||||
return parts.join("?");
|
||||
return parts.join('?');
|
||||
}
|
||||
case "downloaded":
|
||||
return __("Downloads & Purchases");
|
||||
case "published":
|
||||
return __("Publishes");
|
||||
case "search":
|
||||
return params.query
|
||||
? __("Search results for %s", params.query)
|
||||
: __("Search");
|
||||
case "subscriptions":
|
||||
return __("Your Subscriptions");
|
||||
case "discover":
|
||||
case 'downloaded':
|
||||
return __('Downloads & Purchases');
|
||||
case 'published':
|
||||
return __('Publications');
|
||||
case 'search':
|
||||
return params.query ? __('Search results for %s', params.query) : __('Search');
|
||||
case 'subscriptions':
|
||||
return __('Your Subscriptions');
|
||||
case 'discover':
|
||||
case false:
|
||||
case null:
|
||||
case "":
|
||||
return "";
|
||||
case '':
|
||||
return '';
|
||||
default:
|
||||
return page[0].toUpperCase() + (page.length > 0 ? page.substr(1) : "");
|
||||
return page[0].toUpperCase() + (page.length > 0 ? page.substr(1) : '');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const selectPathAfterAuth = createSelector(
|
||||
_selectState,
|
||||
state => state.pathAfterAuth
|
||||
);
|
||||
export const selectPathAfterAuth = createSelector(selectState, state => state.pathAfterAuth);
|
||||
|
||||
export const selectIsBackDisabled = createSelector(
|
||||
_selectState,
|
||||
state => state.index === 0
|
||||
);
|
||||
export const selectIsBackDisabled = createSelector(selectState, state => state.index === 0);
|
||||
|
||||
export const selectIsForwardDisabled = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.index === state.stack.length - 1
|
||||
);
|
||||
|
||||
export const selectHistoryIndex = createSelector(
|
||||
_selectState,
|
||||
state => state.index
|
||||
);
|
||||
export const selectHistoryIndex = createSelector(selectState, state => state.index);
|
||||
|
||||
export const selectHistoryStack = createSelector(
|
||||
_selectState,
|
||||
state => state.stack
|
||||
);
|
||||
export const selectHistoryStack = createSelector(selectState, state => state.stack);
|
||||
|
||||
// returns current page attributes (scrollY, path)
|
||||
export const selectActiveHistoryEntry = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.stack[state.index]
|
||||
);
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { selectUser } from "redux/selectors/user";
|
||||
import rewards from "rewards";
|
||||
import { createSelector } from 'reselect';
|
||||
import REWARDS from 'rewards';
|
||||
|
||||
const _selectState = state => state.rewards || {};
|
||||
const selectState = state => state.rewards || {};
|
||||
|
||||
export const selectUnclaimedRewardsByType = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.unclaimedRewardsByType
|
||||
);
|
||||
|
||||
export const selectClaimedRewardsById = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.claimedRewardsById
|
||||
);
|
||||
|
||||
|
@ -19,13 +18,12 @@ export const selectClaimedRewards = createSelector(
|
|||
byId => Object.values(byId) || []
|
||||
);
|
||||
|
||||
export const selectClaimedRewardsByTransactionId = createSelector(
|
||||
selectClaimedRewards,
|
||||
rewards =>
|
||||
rewards.reduce((map, reward) => {
|
||||
map[reward.transaction_id] = reward;
|
||||
return map;
|
||||
}, {})
|
||||
export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedRewards, rewards =>
|
||||
rewards.reduce((mapParam, reward) => {
|
||||
const map = mapParam;
|
||||
map[reward.transaction_id] = reward;
|
||||
return map;
|
||||
}, {})
|
||||
);
|
||||
|
||||
export const selectUnclaimedRewards = createSelector(
|
||||
|
@ -33,38 +31,20 @@ export const selectUnclaimedRewards = createSelector(
|
|||
byType =>
|
||||
Object.values(byType).sort(
|
||||
(a, b) =>
|
||||
rewards.SORT_ORDER.indexOf(a.reward_type) <
|
||||
rewards.SORT_ORDER.indexOf(b.reward_type)
|
||||
REWARDS.SORT_ORDER.indexOf(a.reward_type) < REWARDS.SORT_ORDER.indexOf(b.reward_type)
|
||||
? -1
|
||||
: 1
|
||||
) || []
|
||||
);
|
||||
|
||||
export const selectIsRewardEligible = createSelector(
|
||||
selectUser,
|
||||
user => user.can_claim_rewards
|
||||
export const selectFetchingRewards = createSelector(selectState, state => !!state.fetching);
|
||||
|
||||
export const selectUnclaimedRewardValue = createSelector(selectUnclaimedRewards, rewards =>
|
||||
rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
|
||||
);
|
||||
|
||||
export const selectFetchingRewards = createSelector(
|
||||
_selectState,
|
||||
state => !!state.fetching
|
||||
);
|
||||
|
||||
export const selectUnclaimedRewardValue = createSelector(
|
||||
selectUnclaimedRewards,
|
||||
rewards => rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
|
||||
);
|
||||
|
||||
export const selectHasClaimedReward = (state, props) => {
|
||||
const reward = selectRewardsByType(state)[props.reward_type];
|
||||
return reward && reward.transaction_id !== "";
|
||||
};
|
||||
|
||||
export const makeSelectHasClaimedReward = () =>
|
||||
createSelector(selectHasClaimedReward, claimed => claimed);
|
||||
|
||||
export const selectClaimsPendingByType = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.claimPendingByType
|
||||
);
|
||||
|
||||
|
@ -75,7 +55,7 @@ export const makeSelectIsRewardClaimPending = () =>
|
|||
createSelector(selectIsClaimRewardPending, isClaiming => isClaiming);
|
||||
|
||||
export const selectClaimErrorsByType = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.claimErrorsByType
|
||||
);
|
||||
|
||||
|
@ -85,14 +65,9 @@ const selectClaimRewardError = (state, props) =>
|
|||
export const makeSelectClaimRewardError = () =>
|
||||
createSelector(selectClaimRewardError, errorMessage => errorMessage);
|
||||
|
||||
const selectRewardByType = (state, props) =>
|
||||
selectUnclaimedRewardsByType(state)[props.reward_type];
|
||||
const selectRewardByType = (state, props) => selectUnclaimedRewardsByType(state)[props.reward_type];
|
||||
|
||||
export const makeSelectRewardByType = () =>
|
||||
createSelector(selectRewardByType, reward => reward);
|
||||
export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward);
|
||||
|
||||
export const makeSelectRewardAmountByType = () =>
|
||||
createSelector(
|
||||
selectRewardByType,
|
||||
reward => (reward ? reward.reward_amount : 0)
|
||||
);
|
||||
createSelector(selectRewardByType, reward => (reward ? reward.reward_amount : 0));
|
||||
|
|
|
@ -1,40 +1,34 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
selectPageTitle,
|
||||
selectCurrentPage,
|
||||
selectCurrentParams,
|
||||
} from "redux/selectors/navigation";
|
||||
} from 'redux/selectors/navigation';
|
||||
|
||||
export const _selectState = state => state.search || {};
|
||||
export const selectState = state => state.search || {};
|
||||
|
||||
export const selectSearchQuery = createSelector(
|
||||
selectCurrentPage,
|
||||
selectCurrentParams,
|
||||
(page, params) => (page === "search" ? params && params.query : null)
|
||||
(page, params) => (page === 'search' ? params && params.query : null)
|
||||
);
|
||||
|
||||
export const selectIsSearching = createSelector(
|
||||
_selectState,
|
||||
state => !!state.searching
|
||||
);
|
||||
export const selectIsSearching = createSelector(selectState, state => !!state.searching);
|
||||
|
||||
export const selectSearchUrisByQuery = createSelector(
|
||||
_selectState,
|
||||
state => state.urisByQuery
|
||||
);
|
||||
export const selectSearchUrisByQuery = createSelector(selectState, state => state.urisByQuery);
|
||||
|
||||
export const makeSelectSearchUris = query =>
|
||||
// replace statement below is kind of ugly, and repeated in doSearch action
|
||||
createSelector(
|
||||
selectSearchUrisByQuery,
|
||||
byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, "") : query]
|
||||
byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '') : query]
|
||||
);
|
||||
|
||||
export const selectWunderBarAddress = createSelector(
|
||||
selectCurrentPage,
|
||||
selectPageTitle,
|
||||
selectSearchQuery,
|
||||
(page, title, query) => (page != "search" ? title : query || title)
|
||||
(page, title, query) => (page !== 'search' ? title : query || title)
|
||||
);
|
||||
|
||||
export const selectWunderBarIcon = createSelector(
|
||||
|
@ -42,44 +36,44 @@ export const selectWunderBarIcon = createSelector(
|
|||
selectCurrentParams,
|
||||
(page, params) => {
|
||||
switch (page) {
|
||||
case "auth":
|
||||
return "icon-user";
|
||||
case "settings":
|
||||
return "icon-gear";
|
||||
case "help":
|
||||
return "icon-question";
|
||||
case "report":
|
||||
return "icon-file";
|
||||
case "downloaded":
|
||||
return "icon-folder";
|
||||
case "published":
|
||||
return "icon-folder";
|
||||
case "history":
|
||||
return "icon-history";
|
||||
case "send":
|
||||
return "icon-send";
|
||||
case "rewards":
|
||||
return "icon-rocket";
|
||||
case "invite":
|
||||
return "icon-envelope-open";
|
||||
case "getcredits":
|
||||
return "icon-shopping-cart";
|
||||
case "wallet":
|
||||
case "backup":
|
||||
return "icon-bank";
|
||||
case "show":
|
||||
return "icon-file";
|
||||
case "publish":
|
||||
return params.id ? __("icon-pencil") : __("icon-upload");
|
||||
case "developer":
|
||||
return "icon-code";
|
||||
case "discover":
|
||||
case "search":
|
||||
return "icon-search";
|
||||
case "subscriptions":
|
||||
return "icon-th-list";
|
||||
case 'auth':
|
||||
return 'icon-user';
|
||||
case 'settings':
|
||||
return 'icon-gear';
|
||||
case 'help':
|
||||
return 'icon-question';
|
||||
case 'report':
|
||||
return 'icon-file';
|
||||
case 'downloaded':
|
||||
return 'icon-folder';
|
||||
case 'published':
|
||||
return 'icon-folder';
|
||||
case 'history':
|
||||
return 'icon-history';
|
||||
case 'send':
|
||||
return 'icon-send';
|
||||
case 'rewards':
|
||||
return 'icon-rocket';
|
||||
case 'invite':
|
||||
return 'icon-envelope-open';
|
||||
case 'getcredits':
|
||||
return 'icon-shopping-cart';
|
||||
case 'wallet':
|
||||
case 'backup':
|
||||
return 'icon-bank';
|
||||
case 'show':
|
||||
return 'icon-file';
|
||||
case 'publish':
|
||||
return params.id ? __('icon-pencil') : __('icon-upload');
|
||||
case 'developer':
|
||||
return 'icon-code';
|
||||
case 'discover':
|
||||
case 'search':
|
||||
return 'icon-search';
|
||||
case 'subscriptions':
|
||||
return 'icon-th-list';
|
||||
default:
|
||||
return "icon-file";
|
||||
return 'icon-file';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
import * as settings from "constants/settings";
|
||||
import { createSelector } from "reselect";
|
||||
import path from "path";
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const _selectState = state => state.settings || {};
|
||||
const selectState = state => state.settings || {};
|
||||
|
||||
export const selectDaemonSettings = createSelector(
|
||||
_selectState,
|
||||
state => state.daemonSettings
|
||||
);
|
||||
export const selectDaemonSettings = createSelector(selectState, state => state.daemonSettings);
|
||||
|
||||
export const selectClientSettings = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.clientSettings || {}
|
||||
);
|
||||
|
||||
export const makeSelectClientSetting = setting =>
|
||||
createSelector(
|
||||
selectClientSettings,
|
||||
settings => (settings ? settings[setting] : undefined)
|
||||
);
|
||||
createSelector(selectClientSettings, settings => (settings ? settings[setting] : undefined));
|
||||
|
||||
export const selectSettingsIsGenerous = createSelector(
|
||||
selectDaemonSettings,
|
||||
|
@ -26,14 +19,11 @@ export const selectSettingsIsGenerous = createSelector(
|
|||
);
|
||||
|
||||
// refactor me
|
||||
export const selectShowNsfw = makeSelectClientSetting(settings.SHOW_NSFW);
|
||||
export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW);
|
||||
|
||||
export const selectLanguages = createSelector(
|
||||
_selectState,
|
||||
state => state.languages || {}
|
||||
);
|
||||
export const selectLanguages = createSelector(selectState, state => state.languages || {});
|
||||
|
||||
export const selectThemePath = createSelector(
|
||||
makeSelectClientSetting(settings.THEME),
|
||||
theme => `${staticResourcesPath}/themes/${theme || "light"}.css`
|
||||
makeSelectClientSetting(SETTINGS.THEME),
|
||||
theme => `${staticResourcesPath}/themes/${theme || 'light'}.css`
|
||||
);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const _selectState = state => state.shapeShift;
|
||||
const selectState = state => state.shapeShift;
|
||||
|
||||
export const selectShapeShift = createSelector(_selectState, state => ({
|
||||
export const selectShapeShift = createSelector(selectState, state => ({
|
||||
...state,
|
||||
}));
|
||||
|
||||
export { selectShapeShift as default };
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
import * as settings from "constants/settings";
|
||||
import { createSelector } from "reselect";
|
||||
import { selectAllClaimsByChannel, selectClaimsById } from "./claims";
|
||||
import { createSelector } from 'reselect';
|
||||
import { selectAllClaimsByChannel, selectClaimsById } from './claims';
|
||||
|
||||
// get the entire subscriptions state
|
||||
const _selectState = state => state.subscriptions || {};
|
||||
const selectState = state => state.subscriptions || {};
|
||||
|
||||
// list of saved channel names and uris
|
||||
export const selectSubscriptions = createSelector(
|
||||
_selectState,
|
||||
state => state.subscriptions
|
||||
);
|
||||
export const selectSubscriptions = createSelector(selectState, state => state.subscriptions);
|
||||
|
||||
export const selectSubscriptionsFromClaims = createSelector(
|
||||
selectAllClaimsByChannel,
|
||||
|
@ -29,7 +25,7 @@ export const selectSubscriptionsFromClaims = createSelector(
|
|||
// if subscribed channel has content
|
||||
if (channelIds[subscription.uri]) {
|
||||
// This will need to be more robust, we will want to be able to load more than the first page
|
||||
const pageOneChannelIds = channelIds[subscription.uri]["1"];
|
||||
const pageOneChannelIds = channelIds[subscription.uri]['1'];
|
||||
|
||||
// we have the channel ids and the corresponding claims
|
||||
// loop over the list of ids and grab the claim
|
||||
|
@ -40,9 +36,7 @@ export const selectSubscriptionsFromClaims = createSelector(
|
|||
}
|
||||
|
||||
// all we really need is a uri for each claim
|
||||
channelClaims = channelClaims.map(
|
||||
claim => `${claim.name}#${claim.claim_id}`
|
||||
);
|
||||
channelClaims = channelClaims.map(claim => `${claim.name}#${claim.claim_id}`);
|
||||
|
||||
fetchedSubscriptions.push({
|
||||
claims: channelClaims,
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
export const _selectState = state => state.user || {};
|
||||
export const selectState = state => state.user || {};
|
||||
|
||||
export const selectAuthenticationIsPending = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.authenticationIsPending
|
||||
);
|
||||
|
||||
export const selectUserIsPending = createSelector(
|
||||
_selectState,
|
||||
state => state.userIsPending
|
||||
);
|
||||
export const selectUserIsPending = createSelector(selectState, state => state.userIsPending);
|
||||
|
||||
export const selectUser = createSelector(_selectState, state => state.user);
|
||||
export const selectUser = createSelector(selectState, state => state.user);
|
||||
|
||||
export const selectUserEmail = createSelector(
|
||||
selectUser,
|
||||
|
@ -20,7 +17,7 @@ export const selectUserEmail = createSelector(
|
|||
);
|
||||
|
||||
export const selectEmailToVerify = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
selectUserEmail,
|
||||
(state, userEmail) => state.emailToVerify || userEmail
|
||||
);
|
||||
|
@ -31,32 +28,32 @@ export const selectUserIsRewardApproved = createSelector(
|
|||
);
|
||||
|
||||
export const selectEmailNewIsPending = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.emailNewIsPending
|
||||
);
|
||||
|
||||
export const selectEmailNewErrorMessage = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.emailNewErrorMessage
|
||||
);
|
||||
|
||||
export const selectEmailVerifyIsPending = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.emailVerifyIsPending
|
||||
);
|
||||
|
||||
export const selectEmailVerifyErrorMessage = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.emailVerifyErrorMessage
|
||||
);
|
||||
|
||||
export const selectIdentityVerifyIsPending = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.identityVerifyIsPending
|
||||
);
|
||||
|
||||
export const selectIdentityVerifyErrorMessage = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.identityVerifyErrorMessage
|
||||
);
|
||||
|
||||
|
@ -65,37 +62,31 @@ export const selectUserIsVerificationCandidate = createSelector(
|
|||
user => user && (!user.has_verified_email || !user.is_identity_verified)
|
||||
);
|
||||
|
||||
export const selectAccessToken = createSelector(
|
||||
_selectState,
|
||||
state => state.accessToken
|
||||
);
|
||||
export const selectAccessToken = createSelector(selectState, state => state.accessToken);
|
||||
|
||||
export const selectUserInviteStatusIsPending = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.inviteStatusIsPending
|
||||
);
|
||||
|
||||
export const selectUserInvitesRemaining = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.invitesRemaining
|
||||
);
|
||||
|
||||
export const selectUserInvitees = createSelector(
|
||||
_selectState,
|
||||
state => state.invitees
|
||||
);
|
||||
export const selectUserInvitees = createSelector(selectState, state => state.invitees);
|
||||
|
||||
export const selectUserInviteStatusFailed = createSelector(
|
||||
selectUserInvitesRemaining,
|
||||
inviteStatus => selectUserInvitesRemaining === null
|
||||
() => selectUserInvitesRemaining === null
|
||||
);
|
||||
|
||||
export const selectUserInviteNewIsPending = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.inviteNewIsPending
|
||||
);
|
||||
|
||||
export const selectUserInviteNewErrorMessage = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.inviteNewErrorMessage
|
||||
);
|
||||
|
|
|
@ -1,99 +1,81 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
export const _selectState = state => state.wallet || {};
|
||||
export const selectState = state => state.wallet || {};
|
||||
|
||||
export const selectBalance = createSelector(
|
||||
_selectState,
|
||||
state => state.balance
|
||||
);
|
||||
export const selectBalance = createSelector(selectState, state => state.balance);
|
||||
|
||||
export const selectTransactionsById = createSelector(
|
||||
_selectState,
|
||||
state => state.transactions
|
||||
);
|
||||
export const selectTransactionsById = createSelector(selectState, state => state.transactions);
|
||||
|
||||
export const selectTransactionItems = createSelector(
|
||||
selectTransactionsById,
|
||||
byId => {
|
||||
const items = [];
|
||||
export const selectTransactionItems = createSelector(selectTransactionsById, byId => {
|
||||
const items = [];
|
||||
|
||||
Object.keys(byId).forEach(txid => {
|
||||
const tx = byId[txid];
|
||||
Object.keys(byId).forEach(txid => {
|
||||
const tx = byId[txid];
|
||||
|
||||
// ignore dust/fees
|
||||
// it is fee only txn if all infos are also empty
|
||||
if (
|
||||
Math.abs(tx.value) === Math.abs(tx.fee) &&
|
||||
tx.claim_info.length == 0 &&
|
||||
tx.support_info.length == 0 &&
|
||||
tx.update_info.length == 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// ignore dust/fees
|
||||
// it is fee only txn if all infos are also empty
|
||||
if (
|
||||
Math.abs(tx.value) === Math.abs(tx.fee) &&
|
||||
tx.claim_info.length === 0 &&
|
||||
tx.support_info.length === 0 &&
|
||||
tx.update_info.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const append = [];
|
||||
const append = [];
|
||||
|
||||
append.push(
|
||||
...tx.claim_info.map(item =>
|
||||
Object.assign({}, tx, item, {
|
||||
type: item.claim_name[0] === '@' ? 'channel' : 'publish',
|
||||
})
|
||||
)
|
||||
);
|
||||
append.push(
|
||||
...tx.support_info.map(item =>
|
||||
Object.assign({}, tx, item, {
|
||||
type: !item.is_tip ? 'support' : 'tip',
|
||||
})
|
||||
)
|
||||
);
|
||||
append.push(...tx.update_info.map(item => Object.assign({}, tx, item, { type: 'update' })));
|
||||
|
||||
if (!append.length) {
|
||||
append.push(
|
||||
...tx.claim_info.map(item =>
|
||||
Object.assign({}, tx, item, {
|
||||
type: item.claim_name[0] === "@" ? "channel" : "publish",
|
||||
})
|
||||
)
|
||||
);
|
||||
append.push(
|
||||
...tx.support_info.map(item =>
|
||||
Object.assign({}, tx, item, {
|
||||
type: !item.is_tip ? "support" : "tip",
|
||||
})
|
||||
)
|
||||
);
|
||||
append.push(
|
||||
...tx.update_info.map(item =>
|
||||
Object.assign({}, tx, item, { type: "update" })
|
||||
)
|
||||
);
|
||||
|
||||
if (!append.length) {
|
||||
append.push(
|
||||
Object.assign({}, tx, {
|
||||
type: tx.value < 0 ? "spend" : "receive",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
items.push(
|
||||
...append.map(item => {
|
||||
// value on transaction, amount on outpoint
|
||||
// amount is always positive, but should match sign of value
|
||||
const amount = parseFloat(
|
||||
item.balance_delta ? item.balance_delta : item.value
|
||||
);
|
||||
|
||||
return {
|
||||
txid,
|
||||
date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null,
|
||||
amount,
|
||||
fee: amount < 0 ? -1 * tx.fee / append.length : 0,
|
||||
claim_id: item.claim_id,
|
||||
claim_name: item.claim_name,
|
||||
type: item.type || "send",
|
||||
nout: item.nout,
|
||||
};
|
||||
Object.assign({}, tx, {
|
||||
type: tx.value < 0 ? 'spend' : 'receive',
|
||||
})
|
||||
);
|
||||
});
|
||||
return items.reverse();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export const selectRecentTransactions = createSelector(
|
||||
selectTransactionItems,
|
||||
transactions => {
|
||||
const threshold = new Date();
|
||||
threshold.setDate(threshold.getDate() - 7);
|
||||
return transactions.filter(transaction => transaction.date > threshold);
|
||||
}
|
||||
);
|
||||
items.push(
|
||||
...append.map(item => {
|
||||
// value on transaction, amount on outpoint
|
||||
// amount is always positive, but should match sign of value
|
||||
const amount = parseFloat(item.balance_delta ? item.balance_delta : item.value);
|
||||
|
||||
return {
|
||||
txid,
|
||||
date: tx.timestamp ? new Date(Number(tx.timestamp) * 1000) : null,
|
||||
amount,
|
||||
fee: amount < 0 ? -1 * tx.fee / append.length : 0,
|
||||
claim_id: item.claim_id,
|
||||
claim_name: item.claim_name,
|
||||
type: item.type || 'send',
|
||||
nout: item.nout,
|
||||
};
|
||||
})
|
||||
);
|
||||
});
|
||||
return items.reverse();
|
||||
});
|
||||
|
||||
export const selectRecentTransactions = createSelector(selectTransactionItems, transactions => {
|
||||
const threshold = new Date();
|
||||
threshold.setDate(threshold.getDate() - 7);
|
||||
return transactions.filter(transaction => transaction.date > threshold);
|
||||
});
|
||||
|
||||
export const selectHasTransactions = createSelector(
|
||||
selectTransactionItems,
|
||||
|
@ -101,27 +83,21 @@ export const selectHasTransactions = createSelector(
|
|||
);
|
||||
|
||||
export const selectIsFetchingTransactions = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.fetchingTransactions
|
||||
);
|
||||
|
||||
export const selectIsSendingSupport = createSelector(
|
||||
_selectState,
|
||||
state => state.sendingSupport
|
||||
);
|
||||
export const selectIsSendingSupport = createSelector(selectState, state => state.sendingSupport);
|
||||
|
||||
export const selectReceiveAddress = createSelector(
|
||||
_selectState,
|
||||
state => state.receiveAddress
|
||||
);
|
||||
export const selectReceiveAddress = createSelector(selectState, state => state.receiveAddress);
|
||||
|
||||
export const selectGettingNewAddress = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.gettingNewAddress
|
||||
);
|
||||
|
||||
export const selectDraftTransaction = createSelector(
|
||||
_selectState,
|
||||
selectState,
|
||||
state => state.draftTransaction || {}
|
||||
);
|
||||
|
||||
|
@ -140,11 +116,10 @@ export const selectDraftTransactionError = createSelector(
|
|||
draft => draft.error
|
||||
);
|
||||
|
||||
export const selectBlocks = createSelector(_selectState, state => state.blocks);
|
||||
export const selectBlocks = createSelector(selectState, state => state.blocks);
|
||||
|
||||
export const makeSelectBlockDate = block =>
|
||||
createSelector(
|
||||
selectBlocks,
|
||||
blocks =>
|
||||
blocks && blocks[block] ? new Date(blocks[block].time * 1000) : undefined
|
||||
blocks => (blocks && blocks[block] ? new Date(blocks[block].time * 1000) : undefined)
|
||||
);
|
||||
|
|
|
@ -1,53 +1,32 @@
|
|||
import lbry from "lbry";
|
||||
import lbryio from "lbryio";
|
||||
import { doShowSnackBar } from "redux/actions/app";
|
||||
import Lbry from 'lbry';
|
||||
import Lbryio from 'lbryio';
|
||||
import { doShowSnackBar } from 'redux/actions/app';
|
||||
|
||||
function rewardMessage(type, amount) {
|
||||
return {
|
||||
new_developer: __(
|
||||
"You earned %s for registering as a new developer.",
|
||||
amount
|
||||
),
|
||||
new_user: __("You earned %s LBC new user reward.", amount),
|
||||
confirm_email: __(
|
||||
"You earned %s LBC for verifying your email address.",
|
||||
amount
|
||||
),
|
||||
new_channel: __(
|
||||
"You earned %s LBC for creating a publisher identity.",
|
||||
amount
|
||||
),
|
||||
first_stream: __(
|
||||
"You earned %s LBC for streaming your first video.",
|
||||
amount
|
||||
),
|
||||
many_downloads: __(
|
||||
"You earned %s LBC for downloading a bunch of things.",
|
||||
amount
|
||||
),
|
||||
first_publish: __(
|
||||
"You earned %s LBC for making your first publication.",
|
||||
amount
|
||||
),
|
||||
featured_download: __(
|
||||
"You earned %s LBC for watching a featured download.",
|
||||
amount
|
||||
),
|
||||
referral: __("You earned %s LBC for referring someone.", amount),
|
||||
new_developer: __('You earned %s for registering as a new developer.', amount),
|
||||
new_user: __('You earned %s LBC new user reward.', amount),
|
||||
confirm_email: __('You earned %s LBC for verifying your email address.', amount),
|
||||
new_channel: __('You earned %s LBC for creating a publisher identity.', amount),
|
||||
first_stream: __('You earned %s LBC for streaming your first video.', amount),
|
||||
many_downloads: __('You earned %s LBC for downloading a bunch of things.', amount),
|
||||
first_publish: __('You earned %s LBC for making your first publication.', amount),
|
||||
featured_download: __('You earned %s LBC for watching a featured download.', amount),
|
||||
referral: __('You earned %s LBC for referring someone.', amount),
|
||||
}[type];
|
||||
}
|
||||
|
||||
const rewards = {};
|
||||
|
||||
rewards.TYPE_NEW_DEVELOPER = "new_developer";
|
||||
rewards.TYPE_NEW_USER = "new_user";
|
||||
rewards.TYPE_CONFIRM_EMAIL = "verified_email";
|
||||
rewards.TYPE_FIRST_CHANNEL = "new_channel";
|
||||
rewards.TYPE_FIRST_STREAM = "first_stream";
|
||||
rewards.TYPE_MANY_DOWNLOADS = "many_downloads";
|
||||
rewards.TYPE_FIRST_PUBLISH = "first_publish";
|
||||
rewards.TYPE_FEATURED_DOWNLOAD = "featured_download";
|
||||
rewards.TYPE_REFERRAL = "referral";
|
||||
rewards.TYPE_NEW_DEVELOPER = 'new_developer';
|
||||
rewards.TYPE_NEW_USER = 'new_user';
|
||||
rewards.TYPE_CONFIRM_EMAIL = 'verified_email';
|
||||
rewards.TYPE_FIRST_CHANNEL = 'new_channel';
|
||||
rewards.TYPE_FIRST_STREAM = 'first_stream';
|
||||
rewards.TYPE_MANY_DOWNLOADS = 'many_downloads';
|
||||
rewards.TYPE_FIRST_PUBLISH = 'first_publish';
|
||||
rewards.TYPE_FEATURED_DOWNLOAD = 'featured_download';
|
||||
rewards.TYPE_REFERRAL = 'referral';
|
||||
rewards.SORT_ORDER = [
|
||||
rewards.TYPE_NEW_USER,
|
||||
rewards.TYPE_CONFIRM_EMAIL,
|
||||
|
@ -62,18 +41,18 @@ rewards.SORT_ORDER = [
|
|||
|
||||
rewards.claimReward = function(type) {
|
||||
function requestReward(resolve, reject, params) {
|
||||
if (!lbryio.enabled) {
|
||||
reject(new Error(__("Rewards are not enabled.")));
|
||||
if (!Lbryio.enabled) {
|
||||
reject(new Error(__('Rewards are not enabled.')));
|
||||
return;
|
||||
}
|
||||
lbryio.call("reward", "new", params, "post").then(reward => {
|
||||
Lbryio.call('reward', 'new', params, 'post').then(reward => {
|
||||
const message = rewardMessage(type, reward.reward_amount);
|
||||
|
||||
// Display global notice
|
||||
const action = doShowSnackBar({
|
||||
message,
|
||||
linkText: __("Show All"),
|
||||
linkTarget: "/rewards",
|
||||
linkText: __('Show All'),
|
||||
linkTarget: '/rewards',
|
||||
isError: false,
|
||||
});
|
||||
window.app.store.dispatch(action);
|
||||
|
@ -85,7 +64,7 @@ rewards.claimReward = function(type) {
|
|||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
lbry.wallet_unused_address().then(address => {
|
||||
Lbry.wallet_unused_address().then(address => {
|
||||
const params = {
|
||||
reward_type: type,
|
||||
wallet_address: address,
|
||||
|
@ -93,42 +72,38 @@ rewards.claimReward = function(type) {
|
|||
|
||||
switch (type) {
|
||||
case rewards.TYPE_FIRST_CHANNEL:
|
||||
lbry
|
||||
.claim_list_mine()
|
||||
Lbry.claim_list_mine()
|
||||
.then(claims => {
|
||||
const claim = claims
|
||||
.reverse()
|
||||
.find(
|
||||
claim =>
|
||||
claim.name.length &&
|
||||
claim.name[0] == "@" &&
|
||||
claim.txid.length &&
|
||||
claim.category == "claim"
|
||||
foundClaim =>
|
||||
foundClaim.name.length &&
|
||||
foundClaim.name[0] === '@' &&
|
||||
foundClaim.txid.length &&
|
||||
foundClaim.category === 'claim'
|
||||
);
|
||||
if (claim) {
|
||||
params.transaction_id = claim.txid;
|
||||
requestReward(resolve, reject, params);
|
||||
} else {
|
||||
reject(
|
||||
new Error(__("Please create a channel identity first."))
|
||||
);
|
||||
reject(new Error(__('Please create a channel identity first.')));
|
||||
}
|
||||
})
|
||||
.catch(reject);
|
||||
break;
|
||||
|
||||
case rewards.TYPE_FIRST_PUBLISH:
|
||||
lbry
|
||||
.claim_list_mine()
|
||||
Lbry.claim_list_mine()
|
||||
.then(claims => {
|
||||
const claim = claims
|
||||
.reverse()
|
||||
.find(
|
||||
claim =>
|
||||
claim.name.length &&
|
||||
claim.name[0] != "@" &&
|
||||
claim.txid.length &&
|
||||
claim.category == "claim"
|
||||
foundClaim =>
|
||||
foundClaim.name.length &&
|
||||
foundClaim.name[0] !== '@' &&
|
||||
foundClaim.txid.length &&
|
||||
foundClaim.category === 'claim'
|
||||
);
|
||||
if (claim) {
|
||||
params.transaction_id = claim.txid;
|
||||
|
@ -138,12 +113,10 @@ rewards.claimReward = function(type) {
|
|||
claims.length
|
||||
? new Error(
|
||||
__(
|
||||
"Please publish something and wait for confirmation by the network to claim this reward."
|
||||
'Please publish something and wait for confirmation by the network to claim this reward.'
|
||||
)
|
||||
)
|
||||
: new Error(
|
||||
__("Please publish something to claim this reward.")
|
||||
)
|
||||
: new Error(__('Please publish something to claim this reward.'))
|
||||
);
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700);
|
||||
|
||||
html
|
||||
{
|
||||
html {
|
||||
height: 100%;
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
body {
|
||||
color: var(--text-color);
|
||||
font-family: 'Roboto', sans-serif;
|
||||
line-height: var(--font-line-height);
|
||||
|
@ -19,30 +17,25 @@ body
|
|||
color: var(--text-selection-color);
|
||||
}
|
||||
|
||||
#window
|
||||
{
|
||||
#window {
|
||||
min-height: 100vh;
|
||||
background: var(--window-bg);
|
||||
}
|
||||
|
||||
.credit-amount--indicator
|
||||
{
|
||||
.credit-amount--indicator {
|
||||
font-weight: 500;
|
||||
color: var(--color-money);
|
||||
}
|
||||
.credit-amount--fee
|
||||
{
|
||||
.credit-amount--fee {
|
||||
font-size: 0.9em;
|
||||
color: var(--color-meta-light);
|
||||
}
|
||||
|
||||
.credit-amount--bold
|
||||
{
|
||||
.credit-amount--bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#main-content
|
||||
{
|
||||
#main-content {
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -58,8 +51,7 @@ body
|
|||
margin-right: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
main.main--single-column
|
||||
{
|
||||
main.main--single-column {
|
||||
width: $width-page-constrained;
|
||||
}
|
||||
|
||||
|
@ -76,7 +68,7 @@ body
|
|||
background: url('../../../static/img/busy.gif') no-repeat center center;
|
||||
width: $width;
|
||||
height: $spacing-vertical;
|
||||
content: "";
|
||||
content: '';
|
||||
left: 50%;
|
||||
margin-left: -1 / 2 * $width;
|
||||
display: inline-block;
|
||||
|
@ -93,30 +85,37 @@ h2 {
|
|||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
h3 { font-size: 1.4em; }
|
||||
h3 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
h5 { font-size: 1.1em; }
|
||||
sup, sub {
|
||||
vertical-align: baseline;
|
||||
position: relative;
|
||||
h5 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
sup,
|
||||
sub {
|
||||
vertical-align: baseline;
|
||||
position: relative;
|
||||
}
|
||||
sup {
|
||||
top: -0.4em;
|
||||
}
|
||||
sub {
|
||||
top: 0.4em;
|
||||
}
|
||||
sup { top: -0.4em; }
|
||||
sub { top: 0.4em; }
|
||||
|
||||
code {
|
||||
font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace;
|
||||
background-color: var(--color-bg-alt);
|
||||
}
|
||||
|
||||
p
|
||||
{
|
||||
p {
|
||||
margin-bottom: 0.8em;
|
||||
&:last-child
|
||||
{
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
@ -137,8 +136,7 @@ p
|
|||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.busy-indicator
|
||||
{
|
||||
.busy-indicator {
|
||||
background: url('../../../static/img/busy.gif') no-repeat center center;
|
||||
display: inline-block;
|
||||
margin: -1em 0;
|
||||
|
@ -146,30 +144,26 @@ p
|
|||
min-height: 8px;
|
||||
vertical-align: middle;
|
||||
padding: 0 30px;
|
||||
&:last-child
|
||||
{
|
||||
&:last-child {
|
||||
padding-right: 2px;
|
||||
}
|
||||
&:first-child
|
||||
{
|
||||
&:first-child {
|
||||
padding-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.help {
|
||||
font-size: .85em;
|
||||
font-size: 0.85em;
|
||||
color: var(--color-help);
|
||||
}
|
||||
|
||||
.meta
|
||||
{
|
||||
.meta {
|
||||
font-size: 0.9em;
|
||||
color: var(--color-meta-light);
|
||||
}
|
||||
|
||||
.empty
|
||||
{
|
||||
color:var(--color-meta-light);
|
||||
.empty {
|
||||
color: var(--color-meta-light);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
@ -185,7 +179,6 @@ p
|
|||
display: block;
|
||||
margin-bottom: $spacing-vertical * 2/3;
|
||||
|
||||
|
||||
text-align: right;
|
||||
line-height: 1;
|
||||
font-size: 0.85em;
|
||||
|
@ -196,7 +189,6 @@ section.section-spaced {
|
|||
margin-bottom: $spacing-vertical;
|
||||
}
|
||||
|
||||
.text-center
|
||||
{
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
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
|
||||
{
|
||||
margin:0;
|
||||
padding:0;
|
||||
body,
|
||||
div,
|
||||
dl,
|
||||
dt,
|
||||
dd,
|
||||
ul,
|
||||
ol,
|
||||
li,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
pre,
|
||||
code,
|
||||
form,
|
||||
fieldset,
|
||||
legend,
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
p,
|
||||
blockquote,
|
||||
th,
|
||||
td,
|
||||
iframe {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
:focus
|
||||
{
|
||||
:focus {
|
||||
outline: 0;
|
||||
}
|
||||
input::-webkit-search-cancel-button {
|
||||
/* Remove default */
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
table
|
||||
{
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing:0;
|
||||
border-spacing: 0;
|
||||
}
|
||||
fieldset, img, iframe
|
||||
{
|
||||
border: 0;
|
||||
fieldset,
|
||||
img,
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
font-weight:normal;
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul
|
||||
{
|
||||
ol,
|
||||
ul {
|
||||
list-style-position: inside;
|
||||
> li {
|
||||
list-style-position: inside;
|
||||
> li { list-style-position: inside; }
|
||||
}
|
||||
}
|
||||
input, textarea, select
|
||||
{
|
||||
font-family:inherit;
|
||||
font-size:inherit;
|
||||
font-weight:inherit;
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
border: 0 none;
|
||||
}
|
||||
img {
|
||||
|
@ -42,8 +73,7 @@ img {
|
|||
vertical-align: middle;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
a
|
||||
{
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
|
@ -6,28 +6,27 @@ $width-page-constrained: 800px;
|
|||
$text-color: #000;
|
||||
|
||||
:root {
|
||||
|
||||
/* Colors */
|
||||
--color-brand: #155B4A;
|
||||
--color-primary: #155B4A;
|
||||
--color-primary-light: saturate(lighten(#155B4A, 50%), 20%);
|
||||
--color-light-alt: hsl(hue(#155B4A), 15, 85);
|
||||
--color-dark-overlay: rgba(32,32,32,0.9);
|
||||
--color-brand: #155b4a;
|
||||
--color-primary: #155b4a;
|
||||
--color-primary-light: saturate(lighten(#155b4a, 50%), 20%);
|
||||
--color-light-alt: hsl(hue(#155b4a), 15, 85);
|
||||
--color-dark-overlay: rgba(32, 32, 32, 0.9);
|
||||
--color-help: rgba(0, 0, 0, 0.54);
|
||||
--color-notice: #8a6d3b;
|
||||
--color-error: #a94442;
|
||||
--color-load-screen-text: #c3c3c3;
|
||||
--color-meta-light: #505050;
|
||||
--color-money: #216C2A;
|
||||
--color-money: #216c2a;
|
||||
--color-download: rgba(0, 0, 0, 0.75);
|
||||
--color-canvas: #f5f5f5;
|
||||
--color-bg: #ffffff;
|
||||
--color-bg-alt: #D9D9D9;
|
||||
--color-bg-alt: #d9d9d9;
|
||||
|
||||
/* Misc */
|
||||
--content-max-width: 1000px;
|
||||
--nsfw-blur-intensity: 20px;
|
||||
--height-video-embedded: $width-page-constrained * 9 / 16 ;
|
||||
--height-video-embedded: $width-page-constrained * 9 / 16;
|
||||
|
||||
/* Font */
|
||||
--font-size: 16px;
|
||||
|
@ -35,20 +34,21 @@ $text-color: #000;
|
|||
--font-size-subtext-multiple: 0.82;
|
||||
|
||||
/* Shadows */
|
||||
--box-shadow-layer: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
||||
--box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12);
|
||||
--box-shadow-layer: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
|
||||
--box-shadow-focus: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2),
|
||||
2px 3px 7px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
/* Transition */
|
||||
--transition-duration: .225s;
|
||||
--transition-duration: 0.225s;
|
||||
--transition-type: ease;
|
||||
|
||||
/* Text */
|
||||
--text-color: $text-color;
|
||||
--text-help-color: #EEE;
|
||||
--text-help-color: #eee;
|
||||
--text-max-width: 660px;
|
||||
--text-link-padding: 4px;
|
||||
--text-selection-bg: rgba(saturate(lighten(#155B4A, 20%), 20%), 1); // temp color
|
||||
--text-selection-color: #FFF;
|
||||
--text-selection-bg: rgba(saturate(lighten(#155b4a, 20%), 20%), 1); // temp color
|
||||
--text-selection-color: #fff;
|
||||
|
||||
/* Window */
|
||||
--window-bg: var(--color-canvas);
|
||||
|
@ -72,7 +72,7 @@ $text-color: #000;
|
|||
|
||||
/* input:hover */
|
||||
--input-hover-border-color: rgba(0, 0, 0, 0.87);
|
||||
/* input:placeholder */
|
||||
/* input:placeholder */
|
||||
--input-placeholder-color: rgba(0, 0, 0, 0.42);
|
||||
--input-placeholder-opacity: 1;
|
||||
|
||||
|
@ -82,9 +82,9 @@ $text-color: #000;
|
|||
|
||||
/* Button */
|
||||
--button-bg: var(--color-bg-alt);
|
||||
--button-color: #FFF;
|
||||
--button-color: #fff;
|
||||
--button-primary-bg: var(--color-primary);
|
||||
--button-primary-color: #FFF;
|
||||
--button-primary-color: #fff;
|
||||
--button-padding: $spacing-vertical * 2/3;
|
||||
--button-height: $spacing-vertical * 1.5;
|
||||
--button-intra-margin: $spacing-vertical;
|
||||
|
@ -93,14 +93,14 @@ $text-color: #000;
|
|||
/* Header */
|
||||
--header-bg: var(--color-bg);
|
||||
--header-color: #666;
|
||||
--header-active-color: rgba(0,0,0, 0.85);
|
||||
--header-active-color: rgba(0, 0, 0, 0.85);
|
||||
--header-height: $spacing-vertical * 2.5;
|
||||
--header-button-bg: transparent; //var(--button-bg);
|
||||
--header-button-hover-bg: rgba(100, 100, 100, 0.15);
|
||||
|
||||
/* Header -> search */
|
||||
--search-bg: rgba(255, 255, 255, 0.7);
|
||||
--search-border:1px solid #ccc;
|
||||
--search-border: 1px solid #ccc;
|
||||
--search-color: #666;
|
||||
--search-active-color: var(--header-active-color);
|
||||
--search-active-shadow: 0 0 3px 0px var(--text-selection-bg);
|
||||
|
@ -130,7 +130,7 @@ $text-color: #000;
|
|||
/* Modal */
|
||||
--modal-width: 440px;
|
||||
--modal-bg: var(--color-bg);
|
||||
--modal-overlay-bg: rgba(#F5F5F5, 0.75); // --color-canvas: #F5F5F5
|
||||
--modal-overlay-bg: rgba(#f5f5f5, 0.75); // --color-canvas: #F5F5F5
|
||||
--modal-border: 1px solid rgb(204, 204, 204);
|
||||
|
||||
/* Menu */
|
||||
|
@ -146,7 +146,7 @@ $text-color: #000;
|
|||
|
||||
/* Scrollbar */
|
||||
--scrollbar-radius: 10px;
|
||||
--scrollbar-thumb-bg: rgba(0, 0, 0, 0.20);
|
||||
--scrollbar-thumb-bg: rgba(0, 0, 0, 0.2);
|
||||
--scrollbar-thumb-hover-bg: rgba(0, 0, 0, 0.35);
|
||||
--scrollbar-thumb-active-bg: var(--color-primary);
|
||||
--scrollbar-track-bg: transparent;
|
||||
|
@ -156,6 +156,5 @@ $text-color: #000;
|
|||
|
||||
/* Animation :) */
|
||||
--animation-duration: 0.3s;
|
||||
--animation-style: cubic-bezier(.55,0,.1,1);
|
||||
|
||||
--animation-style: cubic-bezier(0.55, 0, 0.1, 1);
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
@charset "UTF-8";
|
||||
@import "_reset";
|
||||
@import "_vars";
|
||||
@import "_icons";
|
||||
@import "_gui";
|
||||
@import "component/_table";
|
||||
@import "component/_button.scss";
|
||||
@import "component/_card.scss";
|
||||
@import "component/_file-download.scss";
|
||||
@import "component/_file-selector.scss";
|
||||
@import "component/_file-tile.scss";
|
||||
@import "component/_form-field.scss";
|
||||
@import "component/_header.scss";
|
||||
@import "component/_menu.scss";
|
||||
@import "component/_tooltip.scss";
|
||||
@import "component/_load-screen.scss";
|
||||
@import "component/_channel-indicator.scss";
|
||||
@import "component/_notice.scss";
|
||||
@import "component/_modal.scss";
|
||||
@import "component/_snack-bar.scss";
|
||||
@import "component/_video.scss";
|
||||
@import "component/_pagination.scss";
|
||||
@import "component/_markdown-editor.scss";
|
||||
@import "component/_scrollbar.scss";
|
||||
@import "component/_tabs.scss";
|
||||
@import "component/_divider.scss";
|
||||
@import "component/_checkbox.scss";
|
||||
@import "component/_radio.scss";
|
||||
@import "component/_shapeshift.scss";
|
||||
@import "component/_spinner.scss";
|
||||
@import "page/_show.scss";
|
||||
@import '_reset';
|
||||
@import '_vars';
|
||||
@import '_icons';
|
||||
@import '_gui';
|
||||
@import 'component/_table';
|
||||
@import 'component/_button.scss';
|
||||
@import 'component/_card.scss';
|
||||
@import 'component/_file-download.scss';
|
||||
@import 'component/_file-selector.scss';
|
||||
@import 'component/_file-tile.scss';
|
||||
@import 'component/_form-field.scss';
|
||||
@import 'component/_header.scss';
|
||||
@import 'component/_menu.scss';
|
||||
@import 'component/_tooltip.scss';
|
||||
@import 'component/_load-screen.scss';
|
||||
@import 'component/_channel-indicator.scss';
|
||||
@import 'component/_notice.scss';
|
||||
@import 'component/_modal.scss';
|
||||
@import 'component/_snack-bar.scss';
|
||||
@import 'component/_video.scss';
|
||||
@import 'component/_pagination.scss';
|
||||
@import 'component/_markdown-editor.scss';
|
||||
@import 'component/_scrollbar.scss';
|
||||
@import 'component/_tabs.scss';
|
||||
@import 'component/_divider.scss';
|
||||
@import 'component/_checkbox.scss';
|
||||
@import 'component/_radio.scss';
|
||||
@import 'component/_shapeshift.scss';
|
||||
@import 'component/_spinner.scss';
|
||||
@import 'page/_show.scss';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "../mixin/link.scss";
|
||||
@import '../mixin/link.scss';
|
||||
|
||||
$button-focus-shift: 12%;
|
||||
|
||||
|
@ -6,14 +6,13 @@ $button-focus-shift: 12%;
|
|||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
+ .button-set-item
|
||||
{
|
||||
+ .button-set-item {
|
||||
margin-left: var(--button-intra-margin);
|
||||
}
|
||||
}
|
||||
|
||||
.button-block, .faux-button-block
|
||||
{
|
||||
.button-block,
|
||||
.faux-button-block {
|
||||
display: inline-block;
|
||||
height: var(--button-height);
|
||||
line-height: var(--button-height);
|
||||
|
@ -22,26 +21,21 @@ $button-focus-shift: 12%;
|
|||
text-align: center;
|
||||
border-radius: var(--button-radius);
|
||||
text-transform: uppercase;
|
||||
.icon
|
||||
{
|
||||
.icon {
|
||||
top: 0em;
|
||||
}
|
||||
.icon:first-child
|
||||
{
|
||||
.icon:first-child {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.icon:last-child
|
||||
{
|
||||
.icon:last-child {
|
||||
padding-left: 5px;
|
||||
}
|
||||
.icon:only-child
|
||||
{
|
||||
.icon:only-child {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
.button-block
|
||||
{
|
||||
.button-block {
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
|
@ -57,9 +51,7 @@ $button-focus-shift: 12%;
|
|||
}
|
||||
}
|
||||
|
||||
.button-primary
|
||||
{
|
||||
|
||||
.button-primary {
|
||||
color: var(--button-primary-color);
|
||||
background-color: var(--button-primary-bg);
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
|
@ -70,14 +62,12 @@ $button-focus-shift: 12%;
|
|||
//box-shadow: $box-shadow-focus;
|
||||
}
|
||||
}
|
||||
.button-alt
|
||||
{
|
||||
.button-alt {
|
||||
background-color: var(--button-bg);
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
}
|
||||
|
||||
.button-text
|
||||
{
|
||||
.button-text {
|
||||
@include text-link();
|
||||
display: inline-block;
|
||||
|
||||
|
@ -85,17 +75,15 @@ $button-focus-shift: 12%;
|
|||
margin: 0 var(--text-link-padding);
|
||||
}
|
||||
}
|
||||
.button-text-help
|
||||
{
|
||||
.button-text-help {
|
||||
@include text-link(var(--text-help-color));
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.button--flat
|
||||
{
|
||||
.button--flat {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.button--submit {
|
||||
font-family: inherit;
|
||||
line-height: 0;
|
||||
font-family: inherit;
|
||||
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
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.card--obscured
|
||||
{
|
||||
.card--obscured {
|
||||
position: relative;
|
||||
}
|
||||
.card--obscured .card__inner {
|
||||
filter: blur( var(--nsfw-blur-intensity) );
|
||||
filter: blur(var(--nsfw-blur-intensity));
|
||||
}
|
||||
.card__title-primary,
|
||||
.card__title-identity,
|
||||
|
@ -52,7 +51,6 @@
|
|||
margin-top: var(--card-margin);
|
||||
margin-bottom: var(--card-margin);
|
||||
user-select: none;
|
||||
|
||||
}
|
||||
.card__actions--bottom {
|
||||
margin-top: $spacing-vertical * 1/3;
|
||||
|
@ -88,7 +86,7 @@
|
|||
$font-size-subtext-multiple: 0.82;
|
||||
.card__subtext {
|
||||
color: var(--color-meta-light);
|
||||
font-size: calc( var(--font-size-subtext-multiple) * 1.0em );
|
||||
font-size: calc(var(--font-size-subtext-multiple) * 1em);
|
||||
margin-top: $spacing-vertical * 1/3;
|
||||
margin-bottom: $spacing-vertical * 1/3;
|
||||
}
|
||||
|
@ -96,7 +94,9 @@ $font-size-subtext-multiple: 0.82;
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
.card__subtext--two-lines {
|
||||
height: calc( var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2); /*this is so one line text still has the proper height*/
|
||||
height: calc(
|
||||
var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2
|
||||
); /*this is so one line text still has the proper height*/
|
||||
}
|
||||
.card-overlay {
|
||||
position: absolute;
|
||||
|
@ -117,7 +117,7 @@ $font-size-subtext-multiple: 0.82;
|
|||
cursor: pointer;
|
||||
}
|
||||
.card--link {
|
||||
transition: transform 0.2s var(--animation-style);
|
||||
transition: transform 0.2s var(--animation-style);
|
||||
}
|
||||
.card--link:hover {
|
||||
position: relative;
|
||||
|
@ -126,7 +126,7 @@ $font-size-subtext-multiple: 0.82;
|
|||
transform: scale(var(--card-link-scaling)) translateX(var(--card-hover-translate));
|
||||
transform-origin: 50% 50%;
|
||||
overflow-x: visible;
|
||||
overflow-y: visible
|
||||
overflow-y: visible;
|
||||
}
|
||||
.card--link:hover ~ .card--link {
|
||||
transform: translateX(calc(var(--card-hover-translate) * 2));
|
||||
|
@ -139,49 +139,49 @@ $font-size-subtext-multiple: 0.82;
|
|||
}
|
||||
|
||||
.card__media--autothumb {
|
||||
position: relative
|
||||
position: relative;
|
||||
}
|
||||
.card__media--autothumb.purple {
|
||||
background-color: #9c27b0
|
||||
background-color: #9c27b0;
|
||||
}
|
||||
.card__media--autothumb.red {
|
||||
background-color: #e53935
|
||||
background-color: #e53935;
|
||||
}
|
||||
.card__media--autothumb.pink {
|
||||
background-color: #e91e63
|
||||
background-color: #e91e63;
|
||||
}
|
||||
.card__media--autothumb.indigo {
|
||||
background-color: #3f51b5
|
||||
background-color: #3f51b5;
|
||||
}
|
||||
.card__media--autothumb.blue {
|
||||
background-color: #2196f3
|
||||
background-color: #2196f3;
|
||||
}
|
||||
.card__media--autothumb.light-blue {
|
||||
background-color: #039be5
|
||||
background-color: #039be5;
|
||||
}
|
||||
.card__media--autothumb.cyan {
|
||||
background-color: #00acc1
|
||||
background-color: #00acc1;
|
||||
}
|
||||
.card__media--autothumb.teal {
|
||||
background-color: #009688
|
||||
background-color: #009688;
|
||||
}
|
||||
.card__media--autothumb.green {
|
||||
background-color: #43a047
|
||||
background-color: #43a047;
|
||||
}
|
||||
.card__media--autothumb.yellow {
|
||||
background-color: #ffeb3b
|
||||
background-color: #ffeb3b;
|
||||
}
|
||||
.card__media--autothumb.orange {
|
||||
background-color: #ffa726
|
||||
background-color: #ffa726;
|
||||
}
|
||||
|
||||
.card__media--autothumb .card__autothumb__text {
|
||||
font-size: 2.0em;
|
||||
font-size: 2em;
|
||||
width: 100%;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 36%
|
||||
top: 36%;
|
||||
}
|
||||
|
||||
.card__indicators {
|
||||
|
@ -194,17 +194,17 @@ $font-size-subtext-multiple: 0.82;
|
|||
white-space: normal;
|
||||
}
|
||||
.card--small .card__media {
|
||||
height: calc( var(--card-small-width) * 9 / 16);
|
||||
height: calc(var(--card-small-width) * 9 / 16);
|
||||
}
|
||||
|
||||
.card--form {
|
||||
width: calc( var(--input-width) + var(--card-padding) * 2);
|
||||
width: calc(var(--input-width) + var(--card-padding) * 2);
|
||||
}
|
||||
|
||||
.card__subtitle {
|
||||
color: var(--color-help);
|
||||
font-size: 0.85em;
|
||||
line-height: calc( var(--font-line-height) * 1 / 0.85);
|
||||
line-height: calc(var(--font-line-height) * 1 / 0.85);
|
||||
}
|
||||
|
||||
.card--file-subtitle {
|
||||
|
@ -219,8 +219,7 @@ $font-size-subtext-multiple: 0.82;
|
|||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.card-series-submit
|
||||
{
|
||||
.card-series-submit {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: var(--card-max-width);
|
||||
|
@ -279,7 +278,7 @@ $padding-right-card-hover-hack: 30px;
|
|||
position: absolute;
|
||||
padding: 0 var(--card-margin);
|
||||
height: 100%;
|
||||
top: calc( $padding-top-card-hover-hack - var(--card-margin) );
|
||||
top: calc($padding-top-card-hover-hack - var(--card-margin));
|
||||
}
|
||||
.card-row__nav .card-row__scroll-button {
|
||||
background: var(--card-bg);
|
||||
|
@ -295,8 +294,8 @@ $padding-right-card-hover-hack: 30px;
|
|||
transition: transform 0.2s var(--animation-style);
|
||||
|
||||
&:hover {
|
||||
opacity: 1.0;
|
||||
transform: scale(calc( var(--card-link-scaling) * 1.1));
|
||||
opacity: 1;
|
||||
transform: scale(calc(var(--card-link-scaling) * 1.1));
|
||||
}
|
||||
}
|
||||
.card-row__nav--left {
|
||||
|
@ -311,11 +310,11 @@ if we keep doing things like this, we should add a real grid system, but I'm goi
|
|||
*/
|
||||
.card-grid {
|
||||
$margin-card-grid: $spacing-vertical * 2/3;
|
||||
display:flex;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
> .card {
|
||||
width: $width-page-constrained / 2 - $margin-card-grid / 2;
|
||||
flex-grow:1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
> .card:nth-of-type(2n - 1):not(:last-child) {
|
||||
margin-right: $margin-card-grid;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
.channel-name {
|
||||
display: inline-flex;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
*, *:before, *:after {
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
@ -7,17 +9,18 @@ $md-checkbox-border-color: var(--input-border-color);
|
|||
$md-checkbox-size: 20px;
|
||||
$md-checkbox-padding: 4px;
|
||||
$md-checkmark-width: 2px;
|
||||
$md-checkmark-color: #FFF;
|
||||
$md-checkmark-color: #fff;
|
||||
|
||||
.form-field--checkbox {
|
||||
position: relative;
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
&:before, &:after {
|
||||
content: "";
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left:0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
@ -29,7 +32,7 @@ $md-checkmark-color: #FFF;
|
|||
border: 2px solid $md-checkbox-border-color;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
transition: background .3s;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
&:after {
|
||||
|
@ -37,19 +40,17 @@ $md-checkmark-color: #FFF;
|
|||
}
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
input[type='checkbox'] {
|
||||
outline: 0;
|
||||
visibility: hidden;
|
||||
margin-right: 16px;
|
||||
|
||||
&:checked {
|
||||
|
||||
+ label:before{
|
||||
+ label:before {
|
||||
background: $md-checkbox-checked-color;
|
||||
border:none;
|
||||
border: none;
|
||||
}
|
||||
+ label:after {
|
||||
|
||||
$md-checkmark-size: $md-checkbox-size - 2*$md-checkbox-padding;
|
||||
|
||||
transform: rotate(-45deg);
|
||||
|
@ -65,5 +66,4 @@ $md-checkmark-color: #FFF;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
.file-download, .file-download__overlay {
|
||||
.button__content {
|
||||
margin: 0 var(--text-link-padding);
|
||||
}
|
||||
.file-download,
|
||||
.file-download__overlay {
|
||||
.button__content {
|
||||
margin: 0 var(--text-link-padding);
|
||||
}
|
||||
}
|
||||
|
||||
.file-download
|
||||
{
|
||||
.file-download {
|
||||
position: relative;
|
||||
color: var(--color-download);
|
||||
}
|
||||
.file-download__overlay
|
||||
{
|
||||
.file-download__overlay {
|
||||
background: var(--color-download);
|
||||
color: var(--color-bg);
|
||||
position: absolute;
|
||||
|
|
|
@ -19,5 +19,4 @@ $height-file-tile: $spacing-vertical * 6;
|
|||
.card__title-primary {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
.form-row-submit
|
||||
{
|
||||
.form-row-submit {
|
||||
margin-top: $spacing-vertical;
|
||||
}
|
||||
.form-row-submit--with-footer
|
||||
{
|
||||
.form-row-submit--with-footer {
|
||||
margin-bottom: $spacing-vertical;
|
||||
}
|
||||
|
||||
|
@ -11,7 +9,7 @@
|
|||
margin-top: $spacing-vertical * 5/6;
|
||||
margin-bottom: 0px;
|
||||
line-height: 1;
|
||||
font-size:calc( 0.9 * var(--font-size));
|
||||
font-size: calc(0.9 * var(--font-size));
|
||||
}
|
||||
.form-row__label-row--prefix {
|
||||
float: left;
|
||||
|
@ -19,7 +17,8 @@
|
|||
}
|
||||
|
||||
.form-row--focus {
|
||||
.form-field__label, .form-field__prefix {
|
||||
.form-field__label,
|
||||
.form-field__prefix {
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
}
|
||||
|
@ -37,26 +36,27 @@
|
|||
background: var(--select-bg);
|
||||
color: var(--select-color);
|
||||
&:focus {
|
||||
outline: var(--input-border-size) solid var(--color-primary);
|
||||
outline: var(--input-border-size) solid var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="radio"], input[type="checkbox"], {
|
||||
&:checked + .form-field__label, {
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
&:checked + .form-field__label {
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"].input-copyable {
|
||||
input[type='text'].input-copyable {
|
||||
background: var(--input-bg);
|
||||
color: var(--input-disabled-color);
|
||||
color: var(--input-disabled-color);
|
||||
line-height: 1;
|
||||
padding-top: $spacing-vertical * 1/3;
|
||||
padding-bottom: $spacing-vertical * 1/3;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
width: 100%;
|
||||
font-family: "Consolas", "Lucida Console", "Adobe Source Code Pro", monospace;
|
||||
font-family: 'Consolas', 'Lucida Console', 'Adobe Source Code Pro', monospace;
|
||||
|
||||
&.input-copyable--with-copy-btn {
|
||||
width: 85%;
|
||||
|
@ -64,44 +64,44 @@
|
|||
}
|
||||
|
||||
input[readonly] {
|
||||
color: var(--input-disabled-color) !important;
|
||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||
color: var(--input-disabled-color) !important;
|
||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||
}
|
||||
|
||||
input[readonly]:focus {
|
||||
background: var(--input-bg) !important;
|
||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||
background: var(--input-bg) !important;
|
||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||
}
|
||||
|
||||
textarea,
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="date"]{
|
||||
input[type='text'],
|
||||
input[type='password'],
|
||||
input[type='email'],
|
||||
input[type='number'],
|
||||
input[type='search'],
|
||||
input[type='date'] {
|
||||
background: var(--input-bg);
|
||||
border-bottom: var(--input-border-size) solid var(--input-border-color);
|
||||
caret-color: var(--color-primary);
|
||||
caret-color: var(--color-primary);
|
||||
color: var(--input-color);
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding:0 1px 8px 1px;
|
||||
padding: 0 1px 8px 1px;
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: none;
|
||||
transition: all var(--transition-duration) var(--transition-type);
|
||||
transition: all var(--transition-duration) var(--transition-type);
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
color: var(--input-placeholder-color);
|
||||
opacity: var(--input-placeholder-opacity) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--color-primary);
|
||||
background: var(--input-active-bg);
|
||||
}
|
||||
|
||||
&:hover:not(:focus){
|
||||
&:hover:not(:focus) {
|
||||
border-color: var(--input-hover-border-color);
|
||||
}
|
||||
|
||||
|
@ -112,11 +112,10 @@
|
|||
&.form-field__input--inline {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
border-bottom-width: var(--input-border-size);
|
||||
border-bottom-width: var(--input-border-size);
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
textarea {
|
||||
|
@ -132,7 +131,8 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.form-field__label, .form-row__label {
|
||||
.form-field__label,
|
||||
.form-row__label {
|
||||
color: var(--form-label-color);
|
||||
&[for] {
|
||||
cursor: pointer;
|
||||
|
@ -167,17 +167,18 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field__error, .form-field__helper {
|
||||
.form-field__error,
|
||||
.form-field__helper {
|
||||
margin-top: $spacing-vertical * 1/3;
|
||||
font-size: 0.8em;
|
||||
transition: opacity var(--transition-duration) var(--transition-type);
|
||||
transition: opacity var(--transition-duration) var(--transition-type);
|
||||
}
|
||||
|
||||
.form-field__error {
|
||||
color: var(--color-error);
|
||||
}
|
||||
.form-field__helper {
|
||||
color:var(--color-help);
|
||||
color: var(--color-help);
|
||||
}
|
||||
|
||||
.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
#header
|
||||
{
|
||||
#header {
|
||||
color: var(--header-color);
|
||||
background: var(--header-bg);
|
||||
display: flex;
|
||||
|
@ -19,11 +17,11 @@
|
|||
padding-left: $spacing-vertical / 4;
|
||||
padding-right: $spacing-vertical / 4;
|
||||
.button-alt {
|
||||
background: var(--header-button-bg) !important;
|
||||
font-size: 1em;
|
||||
background: var(--header-button-bg) !important;
|
||||
font-size: 1em;
|
||||
}
|
||||
.button-alt:hover {
|
||||
background: var(--header-button-hover-bg) !important;
|
||||
background: var(--header-button-hover-bg) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,17 +29,18 @@
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.wunderbar
|
||||
{
|
||||
.wunderbar {
|
||||
position: relative;
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: $spacing-vertical / 2 - 4px; //hacked
|
||||
top: $spacing-vertical / 2 - 4px; //hacked
|
||||
}
|
||||
}
|
||||
|
||||
.wunderbar--active .icon-search { color: var(--color-primary); }
|
||||
.wunderbar--active .icon-search {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
// below styles should be inside the common input styling
|
||||
// will come back to this with the redesign - sean
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
.load-screen {
|
||||
color: white;
|
||||
background: var(--color-brand);
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
.CodeMirror {
|
||||
background: var(--color-canvas) !important;
|
||||
border: 0px !important;
|
||||
border-radius: 0px !important;
|
||||
color: var(--text-color) !important;
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
background: var(--color-canvas) !important;
|
||||
border: 0px !important;
|
||||
border-radius: 0px !important;
|
||||
color: var(--text-color) !important;
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
opacity: 1 !important;
|
||||
border: 0 !important;
|
||||
background: var(--color-bg-alt);
|
||||
border-radius: 0 !important;
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
opacity: 1 !important;
|
||||
border: 0 !important;
|
||||
background: var(--color-bg-alt);
|
||||
border-radius: 0 !important;
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
}
|
||||
|
||||
.editor-toolbar i.separator {
|
||||
|
@ -20,85 +20,85 @@
|
|||
}
|
||||
|
||||
.editor-toolbar.fullscreen {
|
||||
background: var(--color-bg) !important;
|
||||
background: var(--color-bg) !important;
|
||||
}
|
||||
|
||||
div.editor-toolbar a {
|
||||
opacity: 0.64;
|
||||
color: var(--text-color) !important;
|
||||
opacity: 0.64;
|
||||
color: var(--text-color) !important;
|
||||
}
|
||||
|
||||
.editor-toolbar a.active,
|
||||
.editor-toolbar a:hover {
|
||||
opacity: 1;
|
||||
background: var(--button-bg) !important;
|
||||
border-color: transparent !important;
|
||||
opacity: 1;
|
||||
background: var(--button-bg) !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
.editor-toolbar.disabled-for-preview a:not(.no-disable) {
|
||||
background: var(--color-bg-alt) !important;
|
||||
border-color: transparent !important;
|
||||
background: var(--color-bg-alt) !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
.editor-statusbar {
|
||||
color: var(--form-label-color) !important;
|
||||
color: var(--form-label-color) !important;
|
||||
}
|
||||
|
||||
.editor-preview {
|
||||
background: var(--card-bg) !important;
|
||||
border: 0 !important;
|
||||
background: var(--card-bg) !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.editor-preview-side {
|
||||
background: var(--color-bg-alt) !important;
|
||||
border: 1px solid var(--input-border-color) !important;
|
||||
background: var(--color-bg-alt) !important;
|
||||
border: 1px solid var(--input-border-color) !important;
|
||||
}
|
||||
|
||||
.editor-preview pre,
|
||||
.editor-preview-side pre {
|
||||
background: #eee;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.editor-preview table td,
|
||||
.editor-preview table th,
|
||||
.editor-preview-side table td,
|
||||
.editor-preview-side table th {
|
||||
border: 1px solid var(--input-border-color) !important;
|
||||
border: 1px solid var(--input-border-color) !important;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-code .cm-tag {
|
||||
color: #63a35c;
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-code .cm-attribute {
|
||||
color: #795da3;
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-code .cm-string {
|
||||
color: #183691;
|
||||
color: #183691;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-selected {
|
||||
background: var(--text-selection-bg) !important;
|
||||
color: var(--text-selection-color) !important;
|
||||
background: var(--text-selection-bg) !important;
|
||||
color: var(--text-selection-color) !important;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-cursor{
|
||||
border-color: var(--color-primary) !important;
|
||||
.CodeMirror .CodeMirror-cursor {
|
||||
border-color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-code .cm-comment {
|
||||
background: rgba(0, 0, 0, .05);
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-code .cm-link {
|
||||
color: #7f8c8d;
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-code .cm-url {
|
||||
color: #aab2b3;
|
||||
color: #aab2b3;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-placeholder {
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
$border-radius-menu: 2px;
|
||||
|
||||
.menu-container {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
.modal-overlay, .error-modal-overlay {
|
||||
.modal-overlay,
|
||||
.error-modal-overlay {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -72,11 +72,12 @@
|
|||
max-width: none;
|
||||
width: var(--modal-width);
|
||||
}
|
||||
.error-modal__error-list { /*shitty hack/temp fix for long errors making modal unusable*/
|
||||
.error-modal__error-list {
|
||||
/*shitty hack/temp fix for long errors making modal unusable*/
|
||||
border: 1px solid var(--input-border-color);
|
||||
padding: 8px;
|
||||
list-style: none;
|
||||
max-height: 400px;
|
||||
max-width: var(--modal-width);
|
||||
max-width: var(--modal-width);
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
|
||||
.notice {
|
||||
padding: 10px 20px;
|
||||
border: 1px solid #000;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
border-radius: 5px;
|
||||
padding: 10px 20px;
|
||||
border: 1px solid #000;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
border-radius: 5px;
|
||||
|
||||
color: #468847;
|
||||
background-color: #dff0d8;
|
||||
border-color: #d6e9c6;
|
||||
color: #468847;
|
||||
background-color: #dff0d8;
|
||||
border-color: #d6e9c6;
|
||||
}
|
||||
|
||||
.notice--error {
|
||||
color: #b94a48;
|
||||
background-color: #f2dede;
|
||||
border-color: #eed3d7;
|
||||
color: #b94a48;
|
||||
background-color: #f2dede;
|
||||
border-color: #eed3d7;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
.pagination {
|
||||
display: block;
|
||||
padding: 0;
|
||||
|
@ -13,7 +12,9 @@
|
|||
border-radius: 2px;
|
||||
&:not(.pagination__item--selected):hover {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
> a { cursor: hand }
|
||||
> a {
|
||||
cursor: hand;
|
||||
}
|
||||
}
|
||||
> a {
|
||||
display: inline-block;
|
||||
|
@ -21,12 +22,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.pagination__item--previous, .pagination__item--next {
|
||||
.pagination__item--previous,
|
||||
.pagination__item--next {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.pagination__item--break {
|
||||
padding: 0 $spacing-vertical * 2 / 3;
|
||||
padding: 0 $spacing-vertical * 2 / 3;
|
||||
}
|
||||
|
||||
.pagination__item--selected {
|
||||
|
|
|
@ -5,50 +5,50 @@ $md-radio-checked-size: 10px;
|
|||
$md-radio-ripple-size: 15px;
|
||||
|
||||
.form-field--radio {
|
||||
position: relative;
|
||||
position: relative;
|
||||
|
||||
label {
|
||||
label {
|
||||
cursor: pointer;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
transition-property: transform, border-color;
|
||||
}
|
||||
|
||||
&:before {
|
||||
width: $md-radio-size;
|
||||
height: $md-radio-size;
|
||||
background: transparent;
|
||||
border: 2px solid $md-radio-border-color;
|
||||
cursor: pointer;
|
||||
|
||||
&:before, &:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left:0;
|
||||
top: 0;
|
||||
border-radius: 50%;
|
||||
transition: all .3s ease;
|
||||
transition-property: transform, border-color;
|
||||
}
|
||||
|
||||
&:before {
|
||||
width: $md-radio-size;
|
||||
height: $md-radio-size;
|
||||
background: transparent;
|
||||
border: 2px solid $md-radio-border-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:after {
|
||||
top: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
||||
left: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
||||
width:$md-radio-checked-size;
|
||||
height:$md-radio-checked-size;
|
||||
transform: scale(0);
|
||||
background:$md-radio-checked-color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
visibility: hidden;
|
||||
margin-right: 16px;
|
||||
|
||||
&:checked + label:before {
|
||||
border-color: $md-radio-checked-color;
|
||||
}
|
||||
|
||||
&:checked + label:after {
|
||||
transform: scale(1);
|
||||
}
|
||||
&:after {
|
||||
top: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
||||
left: $md-radio-size / 2 - $md-radio-checked-size / 2;
|
||||
width: $md-radio-checked-size;
|
||||
height: $md-radio-checked-size;
|
||||
transform: scale(0);
|
||||
background: $md-radio-checked-color;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='radio'] {
|
||||
visibility: hidden;
|
||||
margin-right: 16px;
|
||||
|
||||
&:checked + label:before {
|
||||
border-color: $md-radio-checked-color;
|
||||
}
|
||||
|
||||
&:checked + label:after {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
overflow: auto;
|
||||
width: 8px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--scrollbar-track-bg);
|
||||
border-radius: var(--scrollbar-radius);
|
||||
margin: 4px;
|
||||
background: var(--scrollbar-track-bg);
|
||||
border-radius: var(--scrollbar-radius);
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: var(--scrollbar-radius);
|
||||
background-color: var(--scrollbar-thumb-bg);
|
||||
transition: background-color 0.3s ease;
|
||||
border-radius: var(--scrollbar-radius);
|
||||
background-color: var(--scrollbar-thumb-bg);
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: var(--scrollbar-thumb-hover-bg);
|
||||
background-color: var(--scrollbar-thumb-hover-bg);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:active {
|
||||
background-color: var(--scrollbar-thumb-active-bg);
|
||||
background-color: var(--scrollbar-thumb-active-bg);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
margin-left: 40px;
|
||||
}
|
||||
|
||||
|
||||
.shapeshift__link {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
$padding-snack-horizontal: $spacing-vertical;
|
||||
|
||||
.snack-bar {
|
||||
|
@ -24,7 +23,7 @@ $padding-snack-horizontal: $spacing-vertical;
|
|||
|
||||
border-radius: 2px;
|
||||
|
||||
transition: all var(--transition-duration) var(--transition-type);
|
||||
transition: all var(--transition-duration) var(--transition-type);
|
||||
|
||||
z-index: 10000; /*hack to get it over react modal */
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
table.table-standard {
|
||||
word-wrap: break-word;
|
||||
max-width: 100%;
|
||||
|
||||
th, td {
|
||||
th,
|
||||
td {
|
||||
padding: $spacing-vertical/2 8px;
|
||||
}
|
||||
th {
|
||||
|
@ -13,7 +13,8 @@ table.table-standard {
|
|||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
thead th, > tr:first-child th {
|
||||
thead th,
|
||||
> tr:first-child th {
|
||||
vertical-align: bottom;
|
||||
font-weight: 500;
|
||||
font-size: 0.9em;
|
||||
|
@ -32,7 +33,7 @@ table.table-standard {
|
|||
}
|
||||
tfoot td {
|
||||
padding: $spacing-vertical / 2 8px;
|
||||
font-size: .85em;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
tbody {
|
||||
tr {
|
||||
|
@ -62,9 +63,19 @@ table.table-stretch {
|
|||
}
|
||||
|
||||
table.table-transactions {
|
||||
td:nth-of-type(1) { width: 15%; }
|
||||
td:nth-of-type(2) { width: 15%; }
|
||||
td:nth-of-type(3) { width: 15%; }
|
||||
td:nth-of-type(4) { width: 40%; }
|
||||
td:nth-of-type(5) { width: 15%; }
|
||||
td:nth-of-type(1) {
|
||||
width: 15%;
|
||||
}
|
||||
td:nth-of-type(2) {
|
||||
width: 15%;
|
||||
}
|
||||
td:nth-of-type(3) {
|
||||
width: 15%;
|
||||
}
|
||||
td:nth-of-type(4) {
|
||||
width: 40%;
|
||||
}
|
||||
td:nth-of-type(5) {
|
||||
width: 15%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
/* Tabs */
|
||||
|
||||
nav.sub-header
|
||||
{
|
||||
nav.sub-header {
|
||||
text-transform: uppercase;
|
||||
max-width: $width-page-constrained;
|
||||
margin-bottom: 40px;
|
||||
border-bottom: var(--divider);
|
||||
user-select: none;
|
||||
> a
|
||||
{
|
||||
> a {
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
|
@ -21,16 +19,13 @@ nav.sub-header
|
|||
color: var(--tab-color);
|
||||
position: relative;
|
||||
|
||||
&:first-child
|
||||
{
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
&:last-child
|
||||
{
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
&.sub-header-selected
|
||||
{
|
||||
&.sub-header-selected {
|
||||
color: var(--tab-active-color);
|
||||
&:before {
|
||||
width: 100%;
|
||||
|
@ -45,8 +40,7 @@ nav.sub-header
|
|||
animation-timing-function: var(--animation-style);
|
||||
}
|
||||
}
|
||||
&:hover
|
||||
{
|
||||
&:hover {
|
||||
color: var(--tab-active-color);
|
||||
}
|
||||
}
|
||||
|
@ -60,8 +54,11 @@ nav.sub-header
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes activeTab {
|
||||
from {width: 0;}
|
||||
to {width: 100%;}
|
||||
from {
|
||||
width: 0;
|
||||
}
|
||||
to {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "../mixin/link.scss";
|
||||
@import '../mixin/link.scss';
|
||||
|
||||
.tooltip {
|
||||
position: relative;
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
.tooltip--header .tooltip__link {
|
||||
@include text-link(#aaa);
|
||||
font-size: calc( var(--font-size) * 3/4 );
|
||||
font-size: calc(var(--font-size) * 3/4);
|
||||
margin-left: var(--button-padding);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
$height-video-embedded: $width-page-constrained * 9 / 16;
|
||||
|
||||
video {
|
||||
|
@ -32,13 +31,11 @@ video {
|
|||
height: $height-video-embedded;
|
||||
}
|
||||
}
|
||||
.video--obscured .video__cover
|
||||
{
|
||||
.video--obscured .video__cover {
|
||||
position: relative;
|
||||
filter: blur(var(--nsfw-blur-intensity));
|
||||
}
|
||||
|
||||
|
||||
.video__loading-screen {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@mixin text-link($color: var(--color-primary), $hover-opacity: 0.70) {
|
||||
.icon
|
||||
{
|
||||
@mixin text-link($color: var(--color-primary), $hover-opacity: 0.7) {
|
||||
.icon {
|
||||
&:first-child {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
@ -15,10 +14,9 @@
|
|||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
&:hover
|
||||
{
|
||||
&:hover {
|
||||
opacity: $hover-opacity;
|
||||
transition: opacity var(--transition-duration) var(--transition-type);
|
||||
transition: opacity var(--transition-duration) var(--transition-type);
|
||||
text-decoration: underline;
|
||||
.icon {
|
||||
text-decoration: none;
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
import { createLogger } from "redux-logger";
|
||||
import appReducer from "redux/reducers/app";
|
||||
import availabilityReducer from "redux/reducers/availability";
|
||||
import claimsReducer from "redux/reducers/claims";
|
||||
import contentReducer from "redux/reducers/content";
|
||||
import costInfoReducer from "redux/reducers/cost_info";
|
||||
import fileInfoReducer from "redux/reducers/file_info";
|
||||
import navigationReducer from "redux/reducers/navigation";
|
||||
import rewardsReducer from "redux/reducers/rewards";
|
||||
import searchReducer from "redux/reducers/search";
|
||||
import settingsReducer from "redux/reducers/settings";
|
||||
import userReducer from "redux/reducers/user";
|
||||
import walletReducer from "redux/reducers/wallet";
|
||||
import shapeShiftReducer from "redux/reducers/shape_shift";
|
||||
import subscriptionsReducer from "redux/reducers/subscriptions";
|
||||
import { persistStore, autoRehydrate } from "redux-persist";
|
||||
import createCompressor from "redux-persist-transform-compress";
|
||||
import createFilter from "redux-persist-transform-filter";
|
||||
import localForage from "localforage";
|
||||
import { createStore, applyMiddleware, compose, combineReducers } from "redux";
|
||||
import thunk from "redux-thunk";
|
||||
|
||||
const env = process.env.NODE_ENV || "production"
|
||||
import { createLogger } from 'redux-logger';
|
||||
import appReducer from 'redux/reducers/app';
|
||||
import availabilityReducer from 'redux/reducers/availability';
|
||||
import claimsReducer from 'redux/reducers/claims';
|
||||
import contentReducer from 'redux/reducers/content';
|
||||
import costInfoReducer from 'redux/reducers/cost_info';
|
||||
import fileInfoReducer from 'redux/reducers/file_info';
|
||||
import navigationReducer from 'redux/reducers/navigation';
|
||||
import rewardsReducer from 'redux/reducers/rewards';
|
||||
import searchReducer from 'redux/reducers/search';
|
||||
import settingsReducer from 'redux/reducers/settings';
|
||||
import userReducer from 'redux/reducers/user';
|
||||
import walletReducer from 'redux/reducers/wallet';
|
||||
import shapeShiftReducer from 'redux/reducers/shape_shift';
|
||||
import subscriptionsReducer from 'redux/reducers/subscriptions';
|
||||
import { persistStore, autoRehydrate } from 'redux-persist';
|
||||
import createCompressor from 'redux-persist-transform-compress';
|
||||
import createFilter from 'redux-persist-transform-filter';
|
||||
import localForage from 'localforage';
|
||||
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
|
||||
function isFunction(object) {
|
||||
return typeof object === "function";
|
||||
return typeof object === 'function';
|
||||
}
|
||||
|
||||
function isNotFunction(object) {
|
||||
|
@ -32,10 +30,8 @@ function isNotFunction(object) {
|
|||
|
||||
function createBulkThunkMiddleware() {
|
||||
return ({ dispatch, getState }) => next => action => {
|
||||
if (action.type === "BATCH_ACTIONS") {
|
||||
action.actions
|
||||
.filter(isFunction)
|
||||
.map(actionFn => actionFn(dispatch, getState));
|
||||
if (action.type === 'BATCH_ACTIONS') {
|
||||
action.actions.filter(isFunction).map(actionFn => actionFn(dispatch, getState));
|
||||
}
|
||||
return next(action);
|
||||
};
|
||||
|
@ -44,10 +40,8 @@ function createBulkThunkMiddleware() {
|
|||
function enableBatching(reducer) {
|
||||
return function batchingReducer(state, action) {
|
||||
switch (action.type) {
|
||||
case "BATCH_ACTIONS":
|
||||
return action.actions
|
||||
.filter(isNotFunction)
|
||||
.reduce(batchingReducer, state);
|
||||
case 'BATCH_ACTIONS':
|
||||
return action.actions.filter(isNotFunction).reduce(batchingReducer, state);
|
||||
default:
|
||||
return reducer(state, action);
|
||||
}
|
||||
|
@ -74,13 +68,14 @@ const reducers = combineReducers({
|
|||
const bulkThunk = createBulkThunkMiddleware();
|
||||
const middleware = [thunk, bulkThunk];
|
||||
|
||||
if (env === "development") {
|
||||
if (app.env === 'development') {
|
||||
const logger = createLogger({
|
||||
collapsed: true,
|
||||
});
|
||||
middleware.push(logger);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||
|
||||
const store = createStore(
|
||||
|
@ -88,18 +83,18 @@ const store = createStore(
|
|||
{}, // initial state
|
||||
composeEnhancers(
|
||||
autoRehydrate({
|
||||
log: env === "development",
|
||||
log: app.env === 'development',
|
||||
}),
|
||||
applyMiddleware(...middleware)
|
||||
)
|
||||
);
|
||||
|
||||
const compressor = createCompressor();
|
||||
const saveClaimsFilter = createFilter("claims", ["byId", "claimsByUri"]);
|
||||
const subscriptionsFilter = createFilter("subscriptions", ["subscriptions"]);
|
||||
const saveClaimsFilter = createFilter('claims', ['byId', 'claimsByUri']);
|
||||
const subscriptionsFilter = createFilter('subscriptions', ['subscriptions']);
|
||||
|
||||
const persistOptions = {
|
||||
whitelist: ["claims", "subscriptions"],
|
||||
whitelist: ['claims', 'subscriptions'],
|
||||
// Order is important. Needs to be compressed last or other transforms can't
|
||||
// read the data
|
||||
transforms: [saveClaimsFilter, subscriptionsFilter, compressor],
|
||||
|
@ -109,7 +104,7 @@ const persistOptions = {
|
|||
|
||||
window.cacheStore = persistStore(store, persistOptions, err => {
|
||||
if (err) {
|
||||
console.error("Unable to load saved settings");
|
||||
console.error('Unable to load saved SETTINGS');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
export type FormikActions = {
|
||||
setSubmitting: boolean => mixed,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// https://github.com/reactjs/redux/issues/911
|
||||
function batchActions(...actions) {
|
||||
return {
|
||||
type: "BATCH_ACTIONS",
|
||||
type: 'BATCH_ACTIONS',
|
||||
actions,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
export function formatCredits(amount, precision) {
|
||||
return amount.toFixed(precision || 1).replace(/\.?0+$/, "");
|
||||
return amount.toFixed(precision || 1).replace(/\.?0+$/, '');
|
||||
}
|
||||
|
||||
export function formatFullPrice(amount, precision) {
|
||||
let formated = "";
|
||||
export function formatFullPrice(amount, precision = 1) {
|
||||
let formated = '';
|
||||
|
||||
const quantity = amount.toString().split(".");
|
||||
const quantity = amount.toString().split('.');
|
||||
const fraction = quantity[1];
|
||||
|
||||
if (fraction) {
|
||||
// Set precision
|
||||
precision = precision || 1;
|
||||
|
||||
const decimals = fraction.split("");
|
||||
const first = decimals.filter(number => number != "0")[0];
|
||||
const decimals = fraction.split('');
|
||||
const first = decimals.filter(number => number !== '0')[0];
|
||||
const index = decimals.indexOf(first);
|
||||
|
||||
// Set format fraction
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
export function parseQueryParams(queryString) {
|
||||
if (queryString === "") return {};
|
||||
if (queryString === '') return {};
|
||||
const parts = queryString
|
||||
.split("?")
|
||||
.split('?')
|
||||
.pop()
|
||||
.split("&")
|
||||
.map(p => p.split("="));
|
||||
.split('&')
|
||||
.map(p => p.split('='));
|
||||
|
||||
const params = {};
|
||||
parts.forEach(arr => {
|
||||
params[arr[0]] = arr[1];
|
||||
parts.forEach(array => {
|
||||
const [first, second] = array;
|
||||
params[first] = second;
|
||||
});
|
||||
return params;
|
||||
}
|
||||
|
||||
export function toQueryString(params) {
|
||||
if (!params) return "";
|
||||
if (!params) return '';
|
||||
|
||||
const parts = [];
|
||||
for (const key in params) {
|
||||
if (params.hasOwnProperty(key) && params[key]) {
|
||||
Object.keys(params).forEach(key => {
|
||||
if (Object.prototype.hasOwnProperty.call(params, key) && params[key]) {
|
||||
parts.push(`${key}=${params[key]}`);
|
||||
}
|
||||
}
|
||||
return parts.join("&");
|
||||
});
|
||||
|
||||
return parts.join('&');
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
// util for creating reducers
|
||||
// based off of redux-actions
|
||||
// https://redux-actions.js.org/docs/api/handleAction.html#handleactions
|
||||
export const handleActions = (actionMap, defaultState) => (
|
||||
state = defaultState,
|
||||
action
|
||||
) => {
|
||||
const handleActions = (actionMap, defaultState) => (state = defaultState, action) => {
|
||||
const handler = actionMap[action.type];
|
||||
|
||||
if (handler) {
|
||||
|
@ -16,3 +13,5 @@ export const handleActions = (actionMap, defaultState) => (
|
|||
// returning a copy here breaks redux-persist
|
||||
return state;
|
||||
};
|
||||
|
||||
export { handleActions as default };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { remote } = require("electron");
|
||||
const { remote } = require('electron');
|
||||
|
||||
const application = remote.app;
|
||||
const dock = application.dock;
|
||||
const { dock } = application;
|
||||
const win = remote.BrowserWindow.getFocusedWindow();
|
||||
const setBadge = text => {
|
||||
if (!dock) return;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const { remote } = require("electron");
|
||||
import { remote } from 'electron';
|
||||
|
||||
const application = remote.app;
|
||||
const win = remote.getCurrentWindow();
|
||||
|
||||
const setProgressBar = progress => {
|
||||
|
|
|
@ -19,7 +19,7 @@ const validateAddress = (coinType, address) => {
|
|||
return coinRegex.test(address);
|
||||
};
|
||||
|
||||
export const validateShapeShiftForm = (vals, props) => {
|
||||
export const validateShapeShiftForm = vals => {
|
||||
const errors = {};
|
||||
|
||||
if (!vals.returnAddress) {
|
||||
|
@ -36,13 +36,13 @@ export const validateShapeShiftForm = (vals, props) => {
|
|||
};
|
||||
|
||||
const exampleCoinAddresses = {
|
||||
BTC: "1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq",
|
||||
BCH: "1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq",
|
||||
ETH: "0x8507cA6a274123fC8f80d929AF9D83602bC4e8cC",
|
||||
DASH: "XedBP7vLPFXbS3URjrH2Z57Fg9SWftBmQ6",
|
||||
LTC: "LgZivMvFMTDoqcA5weCQ2QrmRp7pa56bBk",
|
||||
BTC: '1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq',
|
||||
BCH: '1745oPaHeW7Fmpb1fUKTtasYfxr4zu9bwq',
|
||||
ETH: '0x8507cA6a274123fC8f80d929AF9D83602bC4e8cC',
|
||||
DASH: 'XedBP7vLPFXbS3URjrH2Z57Fg9SWftBmQ6',
|
||||
LTC: 'LgZivMvFMTDoqcA5weCQ2QrmRp7pa56bBk',
|
||||
XMR:
|
||||
"466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm",
|
||||
'466XMeJEcowYGx7RzUJj3VDWBZgRWErVQQX6tHYbsacS5QF6v3tidE6LZZnTJgzeEh6bKEEJ6GC9jHirrUKvJwVKVj9e7jm',
|
||||
};
|
||||
|
||||
export const getExampleAddress = coin => exampleCoinAddresses[coin];
|
||||
|
|
|
@ -6,21 +6,25 @@
|
|||
// as much as it can, without ever going more than once per `wait` duration;
|
||||
// but if you'd like to disable the execution on the leading edge, pass
|
||||
// `{leading: false}`. To disable execution on the trailing edge, ditto.
|
||||
export default function throttle(func, wait, options) {
|
||||
let timeout, context, args, result;
|
||||
export default function throttle(func, wait, options = {}) {
|
||||
let timeout;
|
||||
let context;
|
||||
let args;
|
||||
let result;
|
||||
let previous = 0;
|
||||
const getNow = () => new Date().getTime();
|
||||
|
||||
if (!options) options = {};
|
||||
|
||||
const later = function() {
|
||||
previous = options.leading === false ? 0 : getNow();
|
||||
timeout = null;
|
||||
result = func.apply(context, args);
|
||||
if (!timeout) context = args = null;
|
||||
if (!timeout) {
|
||||
context = null;
|
||||
args = null;
|
||||
}
|
||||
};
|
||||
|
||||
const throttled = function() {
|
||||
const throttled = function(...funcArgs) {
|
||||
const now = getNow();
|
||||
|
||||
if (!previous && options.leading === false) previous = now;
|
||||
|
@ -28,7 +32,7 @@ export default function throttle(func, wait, options) {
|
|||
const remaining = wait - (now - previous);
|
||||
|
||||
context = this;
|
||||
args = arguments;
|
||||
args = funcArgs;
|
||||
|
||||
if (remaining <= 0 || remaining > wait) {
|
||||
if (timeout) {
|
||||
|
@ -39,7 +43,10 @@ export default function throttle(func, wait, options) {
|
|||
previous = now;
|
||||
result = func.apply(context, args);
|
||||
|
||||
if (!timeout) context = args = null;
|
||||
if (!timeout) {
|
||||
context = null;
|
||||
args = null;
|
||||
}
|
||||
} else if (!timeout && options.trailing !== false) {
|
||||
timeout = setTimeout(later, remaining);
|
||||
}
|
||||
|
@ -49,7 +56,9 @@ export default function throttle(func, wait, options) {
|
|||
throttled.cancel = function() {
|
||||
clearTimeout(timeout);
|
||||
previous = 0;
|
||||
timeout = context = args = null;
|
||||
timeout = null;
|
||||
context = null;
|
||||
args = null;
|
||||
};
|
||||
|
||||
return throttled;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue