Merge remote-tracking branch 'upstream/master' into tb2
This commit is contained in:
commit
21175ba608
136 changed files with 1293 additions and 23087 deletions
.bumpversion.cfg
.github
.gitignoreCHANGELOG.mdREADME.mdapp
build
package.jsonui
dist
index.html
js/mediaelement
DO NOT CHANGE THESE FILES. USE -src- FOLDER.txtbackground.pngbigplay.fw.pngbigplay.pngbigplay.svgcontrols-ted.pngcontrols-wmp-bg.pngcontrols-wmp.pngcontrols.fw.pngcontrols.pngcontrols.svgflashmediaelement-cdn.swfflashmediaelement-debug.swfflashmediaelement.swfjquery.jsjumpforward.pngloading.gifmediaelement-and-player.jsmediaelement-and-player.min.jsmediaelement.jsmediaelement.min.jsmediaelementplayer.cssmediaelementplayer.jsmediaelementplayer.min.cssmediaelementplayer.min.jsmejs-skins.csssilverlightmediaelement.xapskipback.png
quit.htmlupgrade.htmlwarning.htmljs
|
@ -17,6 +17,10 @@ values =
|
||||||
production
|
production
|
||||||
|
|
||||||
[bumpversion:file:app/package.json]
|
[bumpversion:file:app/package.json]
|
||||||
|
search = "version": "{current_version}"
|
||||||
|
replace = "version": "{new_version}"
|
||||||
|
|
||||||
[bumpversion:file:ui/package.json]
|
[bumpversion:file:ui/package.json]
|
||||||
|
search = "version": "{current_version}"
|
||||||
|
replace = "version": "{new_version}"
|
||||||
|
|
||||||
|
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
|
@ -31,7 +31,7 @@ Tell us what happens instead
|
||||||
You can include a screenshot instead of typing it out -->
|
You can include a screenshot instead of typing it out -->
|
||||||
|
|
||||||
<!-- For the daemon, run:
|
<!-- For the daemon, run:
|
||||||
curl 'http://localhost:5279/lbryapi' --data '{"method":"version"}'
|
curl 'http://localhost:5279' --data '{"method":"version"}'
|
||||||
and include the full output -->
|
and include the full output -->
|
||||||
|
|
||||||
- LBRY Daemon version:
|
- LBRY Daemon version:
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -10,8 +10,10 @@
|
||||||
|
|
||||||
|
|
||||||
/app/dist
|
/app/dist
|
||||||
|
/app/locales
|
||||||
/app/node_modules
|
/app/node_modules
|
||||||
/build/venv
|
/build/venv
|
||||||
|
/build/daemon.ver
|
||||||
/lbry-app-venv
|
/lbry-app-venv
|
||||||
/lbry-app
|
/lbry-app
|
||||||
/lbry-venv
|
/lbry-venv
|
||||||
|
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -8,20 +8,32 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
* Added a new component, `FormFieldPrice` which is now used in Publish and Settings
|
|
||||||
* Added a tipping button to send LBRY Credits to the publisher
|
* Added a tipping button to send LBRY Credits to the publisher
|
||||||
*
|
* Added a forward button and improved history behavior. Back/forward disable when unusable.
|
||||||
|
* Added a new component, `FormFieldPrice` which is now used in Publish and Settings.
|
||||||
|
* Added wallet backup guide reference.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Some form field refactoring as we progress towards form sanity.
|
* Updated to daemon [0.15](https://github.com/lbryio/lbry/releases). Most relevant changes for app are improved announcing of content and a fix for the daemon getting stuck running.
|
||||||
|
* Continued to refine first-run process, process for new users, and introducing people to LBRY and LBRY credits.
|
||||||
|
* Changed the default price settings.
|
||||||
* When an "Open" button is clicked on a show page, if the file fails to open, the app will try to open the file's folder.
|
* When an "Open" button is clicked on a show page, if the file fails to open, the app will try to open the file's folder.
|
||||||
*
|
* Some form field refactoring as we take baby steps towards form sanity.
|
||||||
|
* Replaced confusing placeholder text from email input.
|
||||||
|
* Refactored modal and settings logic.
|
||||||
|
* Updated several packages and fixed warnings in build process (all but the [fsevents warning](https://github.com/yarnpkg/yarn/issues/3738), which is a rather dramatic debate)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Tiles will no longer be blurry on hover (Windows only bug)
|
* Tiles will no longer be blurry on hover (Windows only bug)
|
||||||
* Removed placeholder values from price selection form fields, which was causing confusion that these were real values (#426)
|
* Removed placeholder values from price selection form fields, which was causing confusion that these were real values (#426)
|
||||||
* Fixed showing "other currency" help tip in publish form, which was caused due to not "setting" state for price
|
* Fixed showing "other currency" help tip in publish form, which was caused due to not "setting" state for price
|
||||||
*
|
* Public page now properly checks for all required fields are filled
|
||||||
|
* Fixed pagination styling for pages > 5 (#416)
|
||||||
|
* Fixed sizing on squat videos (#419)
|
||||||
|
* Support claims no longer show up on Published page (#384)
|
||||||
|
* Fixed rendering of small prices (#461)
|
||||||
|
* Fixed incorrect URI in Downloads/Published page (#460)
|
||||||
|
* Fixed menu bug (#503)
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
*
|
*
|
||||||
|
|
12
README.md
12
README.md
|
@ -22,10 +22,12 @@ To install from source or make changes to the application, continue reading belo
|
||||||
|
|
||||||
### One-time Setup
|
### One-time Setup
|
||||||
|
|
||||||
1. Install node and npm.
|
1. Install npm and node (v6 and above required, use [nvm](https://github.com/creationix/nvm/blob/master/README.md) if having trouble)
|
||||||
2. Check out this repo.
|
2. Install keytar and libsecret (see [keytar repository](https://github.com/atom/node-keytar) )
|
||||||
3. Set up a Python virtual environment, or live on the wild side.
|
3. Install yarn by running: npm install -g yarn (may require elevated permissions)
|
||||||
4. Run `./build.sh`. This builds the UI assets and puts them into `app/dist`. It also downloads [lbry daemon](https://github.com/lbryio/lbry/releases).
|
4. Check out this repo.
|
||||||
|
5. Set up a Python virtual environment, or live on the wild side.
|
||||||
|
6. Run `./build.sh`. This builds the UI assets and puts them into `app/dist`. It also downloads [lbry daemon](https://github.com/lbryio/lbry/releases).
|
||||||
|
|
||||||
### Running
|
### Running
|
||||||
|
|
||||||
|
@ -51,4 +53,4 @@ checkout out the build steps in [appveyor.yml](https://github.com/lbryio/lbry-ap
|
||||||
|
|
||||||
## Internationalization
|
## Internationalization
|
||||||
|
|
||||||
If you want to help translating the lbry-app, you can copy the en.json file in /app/locales and modify the values while leaving the keys as their original English strings. An example for this would be: `"Skip": "Überspringen",` Translations should automatically show up in options.
|
If you want to help translating the lbry-app, you can copy the en.json file in /app/locales and modify the values while leaving the keys as their original English strings. An example for this would be: `"Skip": "Überspringen",` Translations should automatically show up in options.
|
||||||
|
|
|
@ -32,7 +32,7 @@ const DAEMON_PATH = process.env.LBRY_DAEMON || path.join(__dirname, 'dist', 'lbr
|
||||||
let client = jayson.client.http({
|
let client = jayson.client.http({
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 5279,
|
port: 5279,
|
||||||
path: '/lbryapi',
|
path: '/',
|
||||||
timeout: 1000
|
timeout: 1000
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
"electron-rebuild": "^1.5.11"
|
"electron-rebuild": "^1.5.11"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.14.2"
|
"lbrynetDaemonVersion": "0.15.1",
|
||||||
}
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
}
|
}
|
|
@ -1 +0,0 @@
|
||||||
https://github.com/lbryio/lbry/releases/download/v0.14.2/lbrynet-daemon-v0.14.2-OSNAME.zip
|
|
|
@ -29,7 +29,10 @@ cd ..
|
||||||
|
|
||||||
|
|
||||||
# get daemon and cli executable
|
# get daemon and cli executable
|
||||||
$daemon_url = (Get-Content build\DAEMON_URL -Raw).replace("OSNAME", "windows")
|
$package_settings = (Get-Content app\package.json -Raw | ConvertFrom-Json).lbrySettings
|
||||||
|
$daemon_ver = $package_settings.lbrynetDaemonVersion
|
||||||
|
$daemon_url_template = $package_settings.lbrynetDaemonUrlTemplate
|
||||||
|
$daemon_url = $daemon_url_template.Replace('OSNAME', 'windows').Replace('DAEMONVER', $daemon_ver)
|
||||||
Invoke-WebRequest -Uri $daemon_url -OutFile daemon.zip
|
Invoke-WebRequest -Uri $daemon_url -OutFile daemon.zip
|
||||||
Expand-Archive daemon.zip -DestinationPath app\dist\
|
Expand-Archive daemon.zip -DestinationPath app\dist\
|
||||||
dir app\dist\ # verify that daemon binary is there
|
dir app\dist\ # verify that daemon binary is there
|
||||||
|
|
|
@ -80,10 +80,19 @@ else
|
||||||
OSNAME="linux"
|
OSNAME="linux"
|
||||||
fi
|
fi
|
||||||
DAEMON_VER=$(node -e "console.log(require(\"$ROOT/app/package.json\").lbrySettings.lbrynetDaemonVersion)")
|
DAEMON_VER=$(node -e "console.log(require(\"$ROOT/app/package.json\").lbrySettings.lbrynetDaemonVersion)")
|
||||||
DAEMON_URL="https://github.com/lbryio/lbry/releases/download/v${DAEMON_VER}/lbrynet-daemon-v${DAEMON_VER}-${OSNAME}.zip"
|
DAEMON_URL_TEMPLATE=$(node -e "console.log(require(\"$ROOT/app/package.json\").lbrySettings.lbrynetDaemonUrlTemplate)")
|
||||||
wget --quiet "$DAEMON_URL" -O "$BUILD_DIR/daemon.zip"
|
DAEMON_URL=$(echo ${DAEMON_URL_TEMPLATE//DAEMONVER/$DAEMON_VER} | sed "s/OSNAME/$OSNAME/g")
|
||||||
unzip "$BUILD_DIR/daemon.zip" -d "$ROOT/app/dist/"
|
DAEMON_VER_PATH="$BUILD_DIR/daemon.ver"
|
||||||
rm "$BUILD_DIR/daemon.zip"
|
echo "$DAEMON_VER_PATH"
|
||||||
|
if [[ ! -f $DAEMON_VER_PATH || ! -f $ROOT/app/dist/lbrynet-daemon || "$(< "$DAEMON_VER_PATH")" != "$DAEMON_VER" ]]; then
|
||||||
|
wget --quiet "$DAEMON_URL" -O "$BUILD_DIR/daemon.zip"
|
||||||
|
unzip "$BUILD_DIR/daemon.zip" -d "$ROOT/app/dist/"
|
||||||
|
rm "$BUILD_DIR/daemon.zip"
|
||||||
|
echo "$DAEMON_VER" > "$DAEMON_VER_PATH"
|
||||||
|
else
|
||||||
|
echo "Already have daemon version $DAEMON_VER, skipping download"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ This script should be run locally, not on a build server.
|
||||||
import argparse
|
import argparse
|
||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -16,7 +17,7 @@ import github
|
||||||
import changelog
|
import changelog
|
||||||
|
|
||||||
ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||||
DAEMON_URL_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'DAEMON_URL')
|
APP_PACKAGE_JSON_FILE = os.path.join(ROOT, 'app', 'package.json')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -38,11 +39,11 @@ def main():
|
||||||
|
|
||||||
print 'Current version: {}'.format(repo.current_version)
|
print 'Current version: {}'.format(repo.current_version)
|
||||||
print 'New version: {}'.format(repo.new_version)
|
print 'New version: {}'.format(repo.new_version)
|
||||||
with open(DAEMON_URL_FILE, 'r') as f:
|
with open(APP_PACKAGE_JSON_FILE, 'r') as f:
|
||||||
daemon_url_template = f.read().strip()
|
package_settings = json.load(f)['lbrySettings']
|
||||||
daemon_version = re.search('/(?P<version>v[^/]+)', daemon_url_template)
|
daemon_url_template = package_settings['lbrynetDaemonUrlTemplate']
|
||||||
print 'Daemon version: {} ({})'.format(
|
daemon_version = package_settings['lbrynetDaemonVersion']
|
||||||
daemon_version.group('version'), daemon_url_template)
|
print 'Daemon version: {} ({})'.format(daemon_version, daemon_url_template.replace('DAEMONVER', daemon_version))
|
||||||
|
|
||||||
if not args.confirm and not confirm():
|
if not args.confirm and not confirm():
|
||||||
print "Aborting"
|
print "Aborting"
|
||||||
|
@ -190,18 +191,25 @@ def run_sanity_checks(repo, branch):
|
||||||
|
|
||||||
|
|
||||||
def check_daemon_urls():
|
def check_daemon_urls():
|
||||||
success = True
|
with open(APP_PACKAGE_JSON_FILE, 'r') as f:
|
||||||
with open(DAEMON_URL_FILE, 'r') as f:
|
package_settings = json.load(f)['lbrySettings']
|
||||||
daemon_url_template = f.read().strip()
|
|
||||||
if "OSNAME" not in daemon_url_template:
|
|
||||||
print "Daemon URL must include the string 'OSNAME'"
|
|
||||||
return False
|
|
||||||
for osname in ('linux', 'macos', 'windows'):
|
|
||||||
if not check_url(daemon_url_template.replace('OSNAME', osname)):
|
|
||||||
success = False
|
|
||||||
print "Daemon URL for " + osname + " does not work"
|
|
||||||
return success
|
|
||||||
|
|
||||||
|
daemon_url_template = package_settings['lbrynetDaemonUrlTemplate']
|
||||||
|
daemon_version = package_settings['lbrynetDaemonVersion']
|
||||||
|
|
||||||
|
if "OSNAME" not in daemon_url_template:
|
||||||
|
print "Daemon URL must include the string \"OSNAME\""
|
||||||
|
return False
|
||||||
|
elif "DAEMONVER" not in daemon_url_template:
|
||||||
|
print "Daemon URL must include the string \"DAEMONVER\""
|
||||||
|
return False
|
||||||
|
|
||||||
|
for osname in ('linux', 'macos', 'windows'):
|
||||||
|
if not check_url(daemon_url_template.replace('DAEMONVER', daemon_version).replace('OSNAME', osname)):
|
||||||
|
print "Daemon URL for", osname, " does not work"
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def check_url(url):
|
def check_url(url):
|
||||||
url = url.strip()
|
url = url.strip()
|
||||||
|
|
|
@ -60,5 +60,6 @@
|
||||||
"electron": "^1.7.5",
|
"electron": "^1.7.5",
|
||||||
"electron-builder": "^11.7.0",
|
"electron-builder": "^11.7.0",
|
||||||
"electron-debug": "^1.4.0"
|
"electron-debug": "^1.4.0"
|
||||||
}
|
},
|
||||||
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
|
|
3
ui/dist/index.html
vendored
3
ui/dist/index.html
vendored
|
@ -4,7 +4,6 @@
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>LBRY</title>
|
<title>LBRY</title>
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
||||||
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
||||||
|
@ -19,8 +18,6 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="canvas"></div>
|
<div id="canvas"></div>
|
||||||
<script src="./js/mediaelement/jquery.js"></script>
|
|
||||||
<script src="./js/mediaelement/mediaelement-and-player.js"></script>
|
|
||||||
<script src="./js/bundle.js"></script>
|
<script src="./js/bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
BIN
ui/dist/js/mediaelement/background.png
vendored
BIN
ui/dist/js/mediaelement/background.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 166 B |
BIN
ui/dist/js/mediaelement/bigplay.fw.png
vendored
BIN
ui/dist/js/mediaelement/bigplay.fw.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 78 KiB |
BIN
ui/dist/js/mediaelement/bigplay.png
vendored
BIN
ui/dist/js/mediaelement/bigplay.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 2.9 KiB |
14
ui/dist/js/mediaelement/bigplay.svg
vendored
14
ui/dist/js/mediaelement/bigplay.svg
vendored
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<svg id="bigplay" viewBox="0 0 100 200" style="background-color:#ffffff00" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
|
|
||||||
x="0px" y="0px" width="100px" height="200px"
|
|
||||||
>
|
|
||||||
<g id="dark">
|
|
||||||
<path id="Polygon" d="M 72.5 49.5 L 38.75 68.9856 L 38.75 30.0144 L 72.5 49.5 Z" fill="#ffffff" opacity="0.75" />
|
|
||||||
<path id="Ellipse" d="M 13 50.5 C 13 29.7891 29.7891 13 50.5 13 C 71.2109 13 88 29.7891 88 50.5 C 88 71.2109 71.2109 88 50.5 88 C 29.7891 88 13 71.2109 13 50.5 Z" stroke="#ffffff" stroke-width="5" fill="none" opacity="0.75"/>
|
|
||||||
</g>
|
|
||||||
<g id="light">
|
|
||||||
<path id="Polygon2" d="M 72.5 149.5 L 38.75 168.9856 L 38.75 130.0144 L 72.5 149.5 Z" fill="#ffffff" opacity="1.0" />
|
|
||||||
<path id="Ellipse2" d="M 13 150.5 C 13 129.7891 29.7891 113 50.5 113 C 71.2109 113 88 129.7891 88 150.5 C 88 171.211 71.2109 188 50.5 188 C 29.7891 188 13 171.211 13 150.5 Z" stroke="#ffffff" stroke-width="5" fill="none" opacity="1.0"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before (image error) Size: 1 KiB |
BIN
ui/dist/js/mediaelement/controls-ted.png
vendored
BIN
ui/dist/js/mediaelement/controls-ted.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 1.5 KiB |
BIN
ui/dist/js/mediaelement/controls-wmp-bg.png
vendored
BIN
ui/dist/js/mediaelement/controls-wmp-bg.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 1.9 KiB |
BIN
ui/dist/js/mediaelement/controls-wmp.png
vendored
BIN
ui/dist/js/mediaelement/controls-wmp.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 5.4 KiB |
BIN
ui/dist/js/mediaelement/controls.fw.png
vendored
BIN
ui/dist/js/mediaelement/controls.fw.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 79 KiB |
BIN
ui/dist/js/mediaelement/controls.png
vendored
BIN
ui/dist/js/mediaelement/controls.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 1.8 KiB |
1
ui/dist/js/mediaelement/controls.svg
vendored
1
ui/dist/js/mediaelement/controls.svg
vendored
File diff suppressed because one or more lines are too long
Before (image error) Size: 10 KiB |
BIN
ui/dist/js/mediaelement/flashmediaelement-cdn.swf
vendored
BIN
ui/dist/js/mediaelement/flashmediaelement-cdn.swf
vendored
Binary file not shown.
BIN
ui/dist/js/mediaelement/flashmediaelement-debug.swf
vendored
BIN
ui/dist/js/mediaelement/flashmediaelement-debug.swf
vendored
Binary file not shown.
BIN
ui/dist/js/mediaelement/flashmediaelement.swf
vendored
BIN
ui/dist/js/mediaelement/flashmediaelement.swf
vendored
Binary file not shown.
9597
ui/dist/js/mediaelement/jquery.js
vendored
9597
ui/dist/js/mediaelement/jquery.js
vendored
File diff suppressed because it is too large
Load diff
BIN
ui/dist/js/mediaelement/jumpforward.png
vendored
BIN
ui/dist/js/mediaelement/jumpforward.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 1.5 KiB |
BIN
ui/dist/js/mediaelement/loading.gif
vendored
BIN
ui/dist/js/mediaelement/loading.gif
vendored
Binary file not shown.
Before ![]() (image error) Size: 6.1 KiB |
5816
ui/dist/js/mediaelement/mediaelement-and-player.js
vendored
5816
ui/dist/js/mediaelement/mediaelement-and-player.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
2063
ui/dist/js/mediaelement/mediaelement.js
vendored
2063
ui/dist/js/mediaelement/mediaelement.js
vendored
File diff suppressed because it is too large
Load diff
15
ui/dist/js/mediaelement/mediaelement.min.js
vendored
15
ui/dist/js/mediaelement/mediaelement.min.js
vendored
File diff suppressed because one or more lines are too long
1000
ui/dist/js/mediaelement/mediaelementplayer.css
vendored
1000
ui/dist/js/mediaelement/mediaelementplayer.css
vendored
File diff suppressed because it is too large
Load diff
3736
ui/dist/js/mediaelement/mediaelementplayer.js
vendored
3736
ui/dist/js/mediaelement/mediaelementplayer.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
289
ui/dist/js/mediaelement/mejs-skins.css
vendored
289
ui/dist/js/mediaelement/mejs-skins.css
vendored
|
@ -1,289 +0,0 @@
|
||||||
/* TED player */
|
|
||||||
.mejs-container.mejs-ted {
|
|
||||||
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls {
|
|
||||||
background: #eee;
|
|
||||||
height: 65px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-ted .mejs-button,
|
|
||||||
.mejs-ted .mejs-time {
|
|
||||||
position: absolute;
|
|
||||||
background: #ddd;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-total {
|
|
||||||
background-color: none;
|
|
||||||
background: url(controls-ted.png) repeat-x 0 -52px;
|
|
||||||
height: 6px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-buffering {
|
|
||||||
height: 6px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-loaded {
|
|
||||||
background-color: none;
|
|
||||||
background: url(controls-ted.png) repeat-x 0 -52px;
|
|
||||||
width: 0;
|
|
||||||
height: 6px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-current {
|
|
||||||
width: 0;
|
|
||||||
height: 6px;
|
|
||||||
background-color: none;
|
|
||||||
background: url(controls-ted.png) repeat-x 0 -59px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-handle {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
width: 14px;
|
|
||||||
height: 21px;
|
|
||||||
top: -7px;
|
|
||||||
border: 0;
|
|
||||||
background: url(controls-ted.png) no-repeat 0 0;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-float {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-playpause-button {
|
|
||||||
top: 29px;
|
|
||||||
left: 9px;
|
|
||||||
width: 49px;
|
|
||||||
height: 28px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-playpause-button button {
|
|
||||||
width: 49px;
|
|
||||||
height: 28px;
|
|
||||||
background: url(controls-ted.png) no-repeat -50px -23px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-pause button {
|
|
||||||
background-position: 0 -23px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-ted .mejs-controls .mejs-fullscreen-button {
|
|
||||||
top: 34px;
|
|
||||||
right: 9px;
|
|
||||||
width: 17px;
|
|
||||||
height: 15px;
|
|
||||||
background : none;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-fullscreen-button button {
|
|
||||||
width: 19px;
|
|
||||||
height: 17px;
|
|
||||||
background: transparent url(controls-ted.png) no-repeat 0 -66px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-unfullscreen button {
|
|
||||||
background: transparent url(controls-ted.png) no-repeat -21px -66px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-volume-button {
|
|
||||||
top: 30px;
|
|
||||||
right: 35px;
|
|
||||||
width: 24px;
|
|
||||||
height: 22px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-mute button {
|
|
||||||
background: url(controls-ted.png) no-repeat -15px 0;
|
|
||||||
width: 24px;
|
|
||||||
height: 22px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-unmute button {
|
|
||||||
background: url(controls-ted.png) no-repeat -40px 0;
|
|
||||||
width: 24px;
|
|
||||||
height: 22px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-slider {
|
|
||||||
background: #fff;
|
|
||||||
border: solid 1px #aaa;
|
|
||||||
border-width: 1px 1px 0 1px;
|
|
||||||
width: 22px;
|
|
||||||
height: 65px;
|
|
||||||
top: -65px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-total {
|
|
||||||
background: url(controls-ted.png) repeat-y -41px -66px;
|
|
||||||
left: 8px;
|
|
||||||
width: 6px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-current {
|
|
||||||
left: 8px;
|
|
||||||
width: 6px;
|
|
||||||
background: url(controls-ted.png) repeat-y -48px -66px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-handle {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-ted .mejs-controls .mejs-time span {
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-currenttime-container {
|
|
||||||
position: absolute;
|
|
||||||
top: 32px;
|
|
||||||
right: 100px;
|
|
||||||
border: solid 1px #999;
|
|
||||||
background: #fff;
|
|
||||||
color: #333;
|
|
||||||
padding-top: 2px;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-duration-container {
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 32px;
|
|
||||||
right: 65px;
|
|
||||||
border: solid 1px #999;
|
|
||||||
background: #fff;
|
|
||||||
color: #333;
|
|
||||||
padding-top: 2px;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-ted .mejs-controls .mejs-time button{
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
.mejs-ted .mejs-controls .mejs-captions-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* END: TED player */
|
|
||||||
|
|
||||||
|
|
||||||
/* WMP player */
|
|
||||||
.mejs-container.mejs-wmp {
|
|
||||||
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls {
|
|
||||||
background: transparent url(controls-wmp-bg.png) center 16px no-repeat;
|
|
||||||
height: 65px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-wmp .mejs-button,
|
|
||||||
.mejs-wmp .mejs-time {
|
|
||||||
position: absolute;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-total {
|
|
||||||
background-color: transparent;
|
|
||||||
border: solid 1px #ccc;
|
|
||||||
height: 3px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-buffering {
|
|
||||||
height: 3px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-loaded {
|
|
||||||
background-color: rgba(255,255,255,0.3);
|
|
||||||
width: 0;
|
|
||||||
height: 3px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-current {
|
|
||||||
width: 0;
|
|
||||||
height: 1px;
|
|
||||||
background-color: #014CB6;
|
|
||||||
border: solid 1px #7FC9FA;
|
|
||||||
border-width: 1px 0;
|
|
||||||
border-color: #7FC9FA #fff #619FF2 #fff;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-handle {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
width: 16px;
|
|
||||||
height: 9px;
|
|
||||||
top: -3px;
|
|
||||||
border: 0;
|
|
||||||
background: url(controls-wmp.png) no-repeat 0 -80px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-float {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-playpause-button {
|
|
||||||
top: 10px;
|
|
||||||
left: 50%;
|
|
||||||
margin: 10px 0 0 -20px;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-playpause-button button {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: url(controls-wmp.png) no-repeat 0 0;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-pause button {
|
|
||||||
background-position: 0 -40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-wmp .mejs-controls .mejs-currenttime-container {
|
|
||||||
position: absolute;
|
|
||||||
top: 25px;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -93px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-duration-container {
|
|
||||||
position: absolute;
|
|
||||||
top: 25px;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -58px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.mejs-wmp .mejs-controls .mejs-volume-button {
|
|
||||||
top: 32px;
|
|
||||||
right: 50%;
|
|
||||||
margin-right: -55px;
|
|
||||||
width: 20px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-volume-button button {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
background: url(controls-wmp.png) no-repeat -42px -17px;
|
|
||||||
width: 20px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-unmute button {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
background: url(controls-wmp.png) no-repeat -42px 0;
|
|
||||||
width: 20px;
|
|
||||||
height: 15px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-volume-button .mejs-volume-slider {
|
|
||||||
background: rgba(102,102,102,0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mejs-wmp .mejs-controls .mejs-fullscreen-button {
|
|
||||||
top: 32px;
|
|
||||||
right: 50%;
|
|
||||||
margin-right: -82px;
|
|
||||||
width: 15px;
|
|
||||||
height: 14px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-fullscreen-button button {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
background: url(controls-wmp.png) no-repeat -63px 0;
|
|
||||||
width: 15px;
|
|
||||||
height: 14px;
|
|
||||||
}
|
|
||||||
.mejs-wmp .mejs-controls .mejs-captions-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* END: WMP player */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
ui/dist/js/mediaelement/silverlightmediaelement.xap
vendored
BIN
ui/dist/js/mediaelement/silverlightmediaelement.xap
vendored
Binary file not shown.
BIN
ui/dist/js/mediaelement/skipback.png
vendored
BIN
ui/dist/js/mediaelement/skipback.png
vendored
Binary file not shown.
Before ![]() (image error) Size: 4.1 KiB |
3
ui/dist/quit.html
vendored
3
ui/dist/quit.html
vendored
|
@ -3,8 +3,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>LBRY</title>
|
<title>LBRY</title>
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
||||||
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
||||||
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
|
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
4
ui/dist/upgrade.html
vendored
4
ui/dist/upgrade.html
vendored
|
@ -3,11 +3,9 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>LBRY</title>
|
<title>LBRY</title>
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
||||||
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
||||||
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
|
||||||
|
|
4
ui/dist/warning.html
vendored
4
ui/dist/warning.html
vendored
|
@ -3,11 +3,9 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>LBRY</title>
|
<title>LBRY</title>
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
||||||
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
||||||
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
|
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
|
||||||
|
|
|
@ -8,6 +8,8 @@ import {
|
||||||
selectPageTitle,
|
selectPageTitle,
|
||||||
selectCurrentPage,
|
selectCurrentPage,
|
||||||
selectCurrentParams,
|
selectCurrentParams,
|
||||||
|
selectHistoryBack,
|
||||||
|
selectHistoryForward,
|
||||||
} from "selectors/app";
|
} from "selectors/app";
|
||||||
import { doSearch } from "actions/search";
|
import { doSearch } from "actions/search";
|
||||||
import { doFetchDaemonSettings } from "actions/settings";
|
import { doFetchDaemonSettings } from "actions/settings";
|
||||||
|
@ -31,7 +33,11 @@ export function doNavigate(path, params = {}, options = {}) {
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const pageTitle = selectPageTitle(state);
|
const pageTitle = selectPageTitle(state);
|
||||||
dispatch(doHistoryPush({ params }, pageTitle, url));
|
const historyState = history.state;
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
doHistoryPush({ params, page: historyState.page + 1 }, pageTitle, url)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,10 +83,35 @@ export function doChangePath(path, options = {}) {
|
||||||
|
|
||||||
export function doHistoryBack() {
|
export function doHistoryBack() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
if (!history.state) return;
|
// Get back history from stack
|
||||||
if (history.state.index === 0) return;
|
const back = selectHistoryBack(getState());
|
||||||
|
|
||||||
history.back();
|
if (back) {
|
||||||
|
// Set location
|
||||||
|
dispatch(doChangePath(back.location));
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: types.HISTORY_NAVIGATE,
|
||||||
|
data: { page: back },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doHistoryForward() {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
// Get forward history from stack
|
||||||
|
const forward = selectHistoryForward(getState());
|
||||||
|
|
||||||
|
if (forward) {
|
||||||
|
// Set location
|
||||||
|
dispatch(doChangePath(forward.location));
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: types.HISTORY_NAVIGATE,
|
||||||
|
data: { page: forward },
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +119,12 @@ export function doHistoryPush(currentState, title, relativeUrl) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
title += " - LBRY";
|
title += " - LBRY";
|
||||||
history.pushState(currentState, title, `#${relativeUrl}`);
|
history.pushState(currentState, title, `#${relativeUrl}`);
|
||||||
|
dispatch({
|
||||||
|
type: types.HISTORY_NAVIGATE,
|
||||||
|
data: {
|
||||||
|
location: relativeUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,10 +303,22 @@ export function doDaemonReady() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const path = window.location.hash || "#/discover";
|
const path = window.location.hash || "#/discover";
|
||||||
const params = parseQueryParams(path.split("?")[1] || "");
|
const params = parseQueryParams(path.split("?")[1] || "");
|
||||||
history.replaceState({ params, index: 0 }, document.title, `${path}`);
|
|
||||||
|
// Get first page
|
||||||
|
const page = {
|
||||||
|
index: 0,
|
||||||
|
location: path.replace(/^#/, ""),
|
||||||
|
};
|
||||||
|
|
||||||
|
history.replaceState(
|
||||||
|
{ params, is_first_page: true, page: 1 },
|
||||||
|
document.title,
|
||||||
|
`${path}`
|
||||||
|
);
|
||||||
dispatch(doAuthenticate());
|
dispatch(doAuthenticate());
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DAEMON_READY,
|
type: types.DAEMON_READY,
|
||||||
|
data: { page },
|
||||||
});
|
});
|
||||||
dispatch(doFetchDaemonSettings());
|
dispatch(doFetchDaemonSettings());
|
||||||
dispatch(doFileList());
|
dispatch(doFileList());
|
||||||
|
@ -302,3 +351,14 @@ export function doQuit() {
|
||||||
remote.app.quit();
|
remote.app.quit();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doChangeVolume(volume) {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
dispatch({
|
||||||
|
type: types.VOLUME_CHANGED,
|
||||||
|
data: {
|
||||||
|
volume,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -231,14 +231,15 @@ export function doStartDownload(uri, outpoint) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
if (!outpoint) { throw new Error("outpoint is required to begin a download"); }
|
if (!outpoint) {
|
||||||
|
throw new Error("outpoint is required to begin a download");
|
||||||
|
}
|
||||||
|
|
||||||
const { downloadingByOutpoint = {} } = state.fileInfo;
|
const { downloadingByOutpoint = {} } = state.fileInfo;
|
||||||
|
|
||||||
if (downloadingByOutpoint[outpoint]) return;
|
if (downloadingByOutpoint[outpoint]) return;
|
||||||
|
|
||||||
lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => {
|
lbry.file_list({ outpoint, full_status: true }).then(([fileInfo]) => {
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DOWNLOADING_STARTED,
|
type: types.DOWNLOADING_STARTED,
|
||||||
data: {
|
data: {
|
||||||
|
@ -282,29 +283,32 @@ export function doLoadVideo(uri) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.get({ uri }).then(streamInfo => {
|
lbry
|
||||||
const timeout =
|
.get({ uri })
|
||||||
streamInfo === null ||
|
.then(streamInfo => {
|
||||||
typeof streamInfo !== "object" ||
|
const timeout =
|
||||||
streamInfo.error == "Timeout";
|
streamInfo === null ||
|
||||||
|
typeof streamInfo !== "object" ||
|
||||||
|
streamInfo.error == "Timeout";
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
|
dispatch({
|
||||||
|
type: types.LOADING_VIDEO_FAILED,
|
||||||
|
data: { uri },
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(doOpenModal("timedOut"));
|
||||||
|
} else {
|
||||||
|
dispatch(doDownloadFile(uri, streamInfo));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.LOADING_VIDEO_FAILED,
|
type: types.LOADING_VIDEO_FAILED,
|
||||||
data: { uri },
|
data: { uri },
|
||||||
});
|
});
|
||||||
|
dispatch(doAlertError(error));
|
||||||
dispatch(doOpenModal("timedOut"));
|
|
||||||
} else {
|
|
||||||
dispatch(doDownloadFile(uri, streamInfo));
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
dispatch({
|
|
||||||
type: types.LOADING_VIDEO_FAILED,
|
|
||||||
data: { uri },
|
|
||||||
});
|
});
|
||||||
dispatch(doAlertError(error));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +340,7 @@ export function doPurchaseUri(uri, purchaseModalName) {
|
||||||
const { cost } = costInfo;
|
const { cost } = costInfo;
|
||||||
|
|
||||||
// the file is free or we have partially downloaded it
|
// the file is free or we have partially downloaded it
|
||||||
if (cost <= 0.01 || (fileInfo && fileInfo.download_directory)) {
|
if (cost === 0 || (fileInfo && fileInfo.download_directory)) {
|
||||||
dispatch(doLoadVideo(uri));
|
dispatch(doLoadVideo(uri));
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -361,9 +365,6 @@ export function doFetchClaimsByChannel(uri, page) {
|
||||||
lbry.claim_list_by_channel({ uri, page }).then(result => {
|
lbry.claim_list_by_channel({ uri, page }).then(result => {
|
||||||
const claimResult = result[uri],
|
const claimResult = result[uri],
|
||||||
claims = claimResult ? claimResult.claims_in_channel : [],
|
claims = claimResult ? claimResult.claims_in_channel : [],
|
||||||
totalPages = claimResult
|
|
||||||
? claimResult.claims_in_channel_pages
|
|
||||||
: undefined,
|
|
||||||
currentPage = claimResult ? claimResult.returned_page : undefined;
|
currentPage = claimResult ? claimResult.returned_page : undefined;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -371,7 +372,6 @@ export function doFetchClaimsByChannel(uri, page) {
|
||||||
data: {
|
data: {
|
||||||
uri,
|
uri,
|
||||||
claims,
|
claims,
|
||||||
totalPages,
|
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -379,6 +379,28 @@ export function doFetchClaimsByChannel(uri, page) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doFetchClaimCountByChannel(uri) {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
dispatch({
|
||||||
|
type: types.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;
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uri,
|
||||||
|
totalClaims,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function doFetchClaimListMine() {
|
export function doFetchClaimListMine() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import * as types from "constants/action_types";
|
import * as types from "constants/action_types";
|
||||||
|
import * as settings from "constants/settings";
|
||||||
|
import batchActions from "util/batchActions";
|
||||||
import lbry from "lbry";
|
import lbry from "lbry";
|
||||||
|
import fs from "fs";
|
||||||
|
import http from "http";
|
||||||
|
|
||||||
export function doFetchDaemonSettings() {
|
export function doFetchDaemonSettings() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
|
@ -41,3 +45,96 @@ export function doSetClientSetting(key, value) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doDownloadLanguage(langFile) {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
const destinationPath = `app/locales/${langFile}`;
|
||||||
|
const language = langFile.replace(".json", "");
|
||||||
|
const req = http.get(
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "text/html",
|
||||||
|
},
|
||||||
|
host: "i18n.lbry.io",
|
||||||
|
path: `/langs/${langFile}`,
|
||||||
|
},
|
||||||
|
response => {
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
const file = fs.createWriteStream(destinationPath);
|
||||||
|
|
||||||
|
file.on("error", errorHandler);
|
||||||
|
file.on("finish", () => {
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// push to our local list
|
||||||
|
dispatch({
|
||||||
|
type: types.DOWNLOAD_LANGUAGE_SUCCEEDED,
|
||||||
|
data: { language: language },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
response.pipe(file);
|
||||||
|
} else {
|
||||||
|
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, function() {
|
||||||
|
req.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on("error", errorHandler);
|
||||||
|
|
||||||
|
req.end();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doDownloadLanguages() {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
if (!fs.existsSync(app.i18n.directory)) {
|
||||||
|
fs.mkdirSync(app.i18n.directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.onreadystatechange = () => {
|
||||||
|
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
try {
|
||||||
|
const files = JSON.parse(xhr.responseText);
|
||||||
|
const actions = [];
|
||||||
|
files.forEach(file => {
|
||||||
|
actions.push(doDownloadLanguage(file));
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(batchActions(...actions));
|
||||||
|
} catch (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
__("The list of available languages could not be retrieved.")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.open("get", "http://i18n.lbry.io");
|
||||||
|
xhr.send();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doChangeLanguage(language) {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
lbry.setClientSetting(settings.LANGUAGE, language);
|
||||||
|
app.i18n.setLocale(language);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as types from "constants/action_types";
|
import * as types from "constants/action_types";
|
||||||
import * as modals from "constants/modal_types";
|
import * as modals from "constants/modal_types";
|
||||||
import lbryio from "lbryio";
|
import lbryio from "lbryio";
|
||||||
import { setLocal } from "utils";
|
|
||||||
import { doOpenModal } from "actions/app";
|
import { doOpenModal } from "actions/app";
|
||||||
import { doRewardList, doClaimRewardType } from "actions/rewards";
|
import { doRewardList, doClaimRewardType } from "actions/rewards";
|
||||||
import { selectEmailToVerify, selectUser } from "selectors/user";
|
import { selectEmailToVerify, selectUser } from "selectors/user";
|
||||||
|
@ -95,15 +94,6 @@ export function doUserEmailNew(email) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doUserEmailDecline() {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
setLocal("user_email_declined", true);
|
|
||||||
dispatch({
|
|
||||||
type: types.USER_EMAIL_DECLINE,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doUserEmailVerify(verificationToken) {
|
export function doUserEmailVerify(verificationToken) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const email = selectEmailToVerify(getState());
|
const email = selectEmailToVerify(getState());
|
||||||
|
|
|
@ -111,7 +111,7 @@ export function doSendDraftTransaction() {
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry
|
lbry
|
||||||
.send_amount_to_address({
|
.wallet_send({
|
||||||
amount: draftTx.amount,
|
amount: draftTx.amount,
|
||||||
address: draftTx.address,
|
address: draftTx.address,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import store from "store.js";
|
import store from "store.js";
|
||||||
import lbry from "./lbry.js";
|
import lbry from "./lbry.js";
|
||||||
|
import * as settings from "constants/settings";
|
||||||
|
|
||||||
const env = ENV;
|
const env = ENV;
|
||||||
const config = {
|
const config = {
|
||||||
...require(`./config/${env}`),
|
...require(`./config/${env}`),
|
||||||
};
|
};
|
||||||
const language = lbry.getClientSetting("language")
|
const language = lbry.getClientSetting(settings.LANGUAGE)
|
||||||
? lbry.getClientSetting("language")
|
? lbry.getClientSetting(settings.LANGUAGE)
|
||||||
: "en";
|
: "en";
|
||||||
const i18n = require("y18n")({
|
const i18n = require("y18n")({
|
||||||
directory: "app/locales",
|
directory: "app/locales",
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Router from "component/router";
|
import Router from "component/router/index";
|
||||||
import Header from "component/header";
|
import Header from "component/header";
|
||||||
import ModalError from "component/modalError";
|
import ModalRouter from "modal/modalRouter";
|
||||||
import ModalAuthFailure from "component/modalAuthFailure";
|
|
||||||
import ModalDownloading from "component/modalDownloading";
|
|
||||||
import ModalInsufficientCredits from "component/modalInsufficientCredits";
|
|
||||||
import ModalUpgrade from "component/modalUpgrade";
|
|
||||||
import ModalWelcome from "component/modalWelcome";
|
|
||||||
import ModalFirstReward from "component/modalFirstReward";
|
|
||||||
import ModalTransactionFailed from "component/modalTransactionFailed";
|
|
||||||
import ModalInsufficientBalance from "component/modalInsufficientBalance";
|
|
||||||
import lbry from "lbry";
|
import lbry from "lbry";
|
||||||
import * as modals from "constants/modal_types";
|
|
||||||
|
|
||||||
class App extends React.PureComponent {
|
class App extends React.PureComponent {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
@ -36,52 +27,23 @@ class App extends React.PureComponent {
|
||||||
|
|
||||||
fetchRewardedContent();
|
fetchRewardedContent();
|
||||||
|
|
||||||
this.showWelcome(this.props);
|
|
||||||
|
|
||||||
this.scrollListener = () => this.props.recordScroll(window.scrollY);
|
this.scrollListener = () => this.props.recordScroll(window.scrollY);
|
||||||
|
|
||||||
window.addEventListener("scroll", this.scrollListener);
|
window.addEventListener("scroll", this.scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
this.showWelcome(nextProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
showWelcome(props) {
|
|
||||||
const { isWelcomeAcknowledged, openWelcomeModal, user } = props;
|
|
||||||
|
|
||||||
if (
|
|
||||||
!isWelcomeAcknowledged &&
|
|
||||||
user &&
|
|
||||||
!user.is_reward_approved &&
|
|
||||||
!user.is_identity_verified
|
|
||||||
) {
|
|
||||||
openWelcomeModal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
window.removeEventListener("scroll", this.scrollListener);
|
window.removeEventListener("scroll", this.scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { modal } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="window">
|
<div id="window">
|
||||||
<Header />
|
<Header />
|
||||||
<div id="main-content">
|
<div id="main-content">
|
||||||
<Router />
|
<Router />
|
||||||
</div>
|
</div>
|
||||||
{modal == modals.UPGRADE && <ModalUpgrade />}
|
<ModalRouter />
|
||||||
{modal == modals.DOWNLOADING && <ModalDownloading />}
|
|
||||||
{modal == modals.ERROR && <ModalError />}
|
|
||||||
{modal == modals.INSUFFICIENT_CREDITS && <ModalInsufficientCredits />}
|
|
||||||
{modal == modals.WELCOME && <ModalWelcome />}
|
|
||||||
{modal == modals.FIRST_REWARD && <ModalFirstReward />}
|
|
||||||
{modal == modals.AUTHENTICATION_FAILURE && <ModalAuthFailure />}
|
|
||||||
{modal == modals.TRANSACTION_FAILED && <ModalTransactionFailed />}
|
|
||||||
{modal == modals.INSUFFICIENT_BALANCE && <ModalInsufficientBalance />}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { formatCredits } from "utils";
|
import { formatCredits, formatFullPrice } from "util/formatCredits";
|
||||||
import lbry from "../lbry.js";
|
import lbry from "../lbry.js";
|
||||||
|
|
||||||
//component/icon.js
|
//component/icon.js
|
||||||
|
@ -68,35 +68,50 @@ export class CreditAmount extends React.PureComponent {
|
||||||
isEstimate: React.PropTypes.bool,
|
isEstimate: React.PropTypes.bool,
|
||||||
label: React.PropTypes.bool,
|
label: React.PropTypes.bool,
|
||||||
showFree: React.PropTypes.bool,
|
showFree: React.PropTypes.bool,
|
||||||
|
showFullPrice: React.PropTypes.bool,
|
||||||
look: React.PropTypes.oneOf(["indicator", "plain"]),
|
look: React.PropTypes.oneOf(["indicator", "plain"]),
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
precision: 1,
|
precision: 2,
|
||||||
label: true,
|
label: true,
|
||||||
showFree: false,
|
|
||||||
look: "indicator",
|
look: "indicator",
|
||||||
|
showFree: false,
|
||||||
|
showFullPrice: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const formattedAmount = formatCredits(
|
const minimumRenderableAmount = Math.pow(10, -1 * this.props.precision);
|
||||||
this.props.amount,
|
const { amount, precision, showFullPrice } = this.props;
|
||||||
this.props.precision
|
|
||||||
);
|
let formattedAmount;
|
||||||
|
let fullPrice = formatFullPrice(amount, 2);
|
||||||
|
|
||||||
|
if (showFullPrice) {
|
||||||
|
formattedAmount = fullPrice;
|
||||||
|
} else {
|
||||||
|
formattedAmount = amount > 0 && amount < minimumRenderableAmount
|
||||||
|
? "<" + minimumRenderableAmount
|
||||||
|
: formatCredits(amount, precision);
|
||||||
|
}
|
||||||
|
|
||||||
let amountText;
|
let amountText;
|
||||||
if (this.props.showFree && parseFloat(formattedAmount) == 0) {
|
if (this.props.showFree && parseFloat(this.props.amount) === 0) {
|
||||||
amountText = __("free");
|
amountText = __("free");
|
||||||
} else if (this.props.label) {
|
} else if (this.props.label) {
|
||||||
amountText =
|
amountText =
|
||||||
formattedAmount +
|
formattedAmount +
|
||||||
" " +
|
" " +
|
||||||
(parseFloat(formattedAmount) == 1 ? __("credit") : __("credits"));
|
(parseFloat(amount) == 1 ? __("credit") : __("credits"));
|
||||||
} else {
|
} else {
|
||||||
amountText = formattedAmount;
|
amountText = formattedAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={`credit-amount credit-amount--${this.props.look}`}>
|
<span
|
||||||
|
className={`credit-amount credit-amount--${this.props.look}`}
|
||||||
|
title={fullPrice}
|
||||||
|
>
|
||||||
<span>
|
<span>
|
||||||
{amountText}
|
{amountText}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Icon, BusyMessage } from "component/common";
|
import { Icon, BusyMessage } from "component/common";
|
||||||
import FilePrice from "component/filePrice";
|
import FilePrice from "component/filePrice";
|
||||||
import { Modal } from "component/modal";
|
import { Modal } from "modal/modal";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import { ToolTip } from "component/tooltip";
|
import { ToolTip } from "component/tooltip";
|
||||||
import { DropDownMenu, DropDownMenuItem } from "component/menu";
|
import { DropDownMenu, DropDownMenuItem } from "component/menu";
|
||||||
import ModalRemoveFile from "component/modalRemoveFile";
|
import ModalRemoveFile from "modal/modalRemoveFile";
|
||||||
import * as modals from "constants/modal_types";
|
import * as modals from "constants/modal_types";
|
||||||
|
|
||||||
class FileActions extends React.PureComponent {
|
class FileActions extends React.PureComponent {
|
||||||
|
@ -200,7 +200,7 @@ class FileActions extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{__("This will purchase")} <strong>{title}</strong> {__("for")}{" "}
|
{__("This will purchase")} <strong>{title}</strong> {__("for")}{" "}
|
||||||
<strong>
|
<strong>
|
||||||
<FilePrice uri={uri} look="plain" />
|
<FilePrice uri={uri} showFullPrice={true} look="plain" />
|
||||||
</strong>{" "}
|
</strong>{" "}
|
||||||
{__("credits")}.
|
{__("credits")}.
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -209,7 +209,8 @@ class FileActions extends React.PureComponent {
|
||||||
contentLabel={__("Download failed")}
|
contentLabel={__("Download failed")}
|
||||||
onConfirmed={closeModal}
|
onConfirmed={closeModal}
|
||||||
>
|
>
|
||||||
{__("LBRY was unable to download the stream")} <strong>{uri}</strong>.
|
{__("LBRY was unable to download the stream")}{" "}{" "}
|
||||||
|
<strong>{title}</strong>.
|
||||||
</Modal>
|
</Modal>
|
||||||
{modal == modals.CONFIRM_FILE_REMOVE &&
|
{modal == modals.CONFIRM_FILE_REMOVE &&
|
||||||
<ModalRemoveFile
|
<ModalRemoveFile
|
||||||
|
|
|
@ -62,7 +62,8 @@ class FileCard extends React.PureComponent {
|
||||||
? metadata.thumbnail
|
? metadata.thumbnail
|
||||||
: null;
|
: null;
|
||||||
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw;
|
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw;
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent =
|
||||||
|
claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
|
|
||||||
let description = "";
|
let description = "";
|
||||||
if (isResolvingUri && !claim) {
|
if (isResolvingUri && !claim) {
|
||||||
|
@ -95,8 +96,9 @@ class FileCard extends React.PureComponent {
|
||||||
<div className="card__subtitle">
|
<div className="card__subtitle">
|
||||||
<span style={{ float: "right" }}>
|
<span style={{ float: "right" }}>
|
||||||
<FilePrice uri={uri} />
|
<FilePrice uri={uri} />
|
||||||
{isRewardContent && <span>{" "}<IconFeatured /></span> }
|
{isRewardContent && <span>{" "}<IconFeatured /></span>}
|
||||||
{fileInfo && <span>{" "}<Icon fixed icon="icon-folder" /></span> }
|
{fileInfo &&
|
||||||
|
<span>{" "}<Icon fixed icon="icon-folder" /></span>}
|
||||||
</span>
|
</span>
|
||||||
<UriIndicator uri={uri} />
|
<UriIndicator uri={uri} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import lbry from "lbry.js";
|
|
||||||
import lbryuri from "lbryuri.js";
|
import lbryuri from "lbryuri.js";
|
||||||
import Link from "component/link";
|
|
||||||
import FormField from "component/formField";
|
import FormField from "component/formField";
|
||||||
import FileTile from "component/fileTile";
|
import FileTile from "component/fileTile";
|
||||||
import rewards from "rewards.js";
|
import { BusyMessage } from "component/common.js";
|
||||||
import lbryio from "lbryio.js";
|
|
||||||
import { BusyMessage, Thumbnail } from "component/common.js";
|
|
||||||
|
|
||||||
class FileList extends React.PureComponent {
|
class FileList extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -55,6 +51,14 @@ class FileList extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getChannelSignature(fileInfo) {
|
||||||
|
if (fileInfo.value) {
|
||||||
|
return fileInfo.value.publisherSignature.certificateId;
|
||||||
|
} else {
|
||||||
|
return fileInfo.metadata.publisherSignature.certificateId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleSortChanged(event) {
|
handleSortChanged(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
sortBy: event.target.value,
|
sortBy: event.target.value,
|
||||||
|
@ -67,12 +71,12 @@ class FileList extends React.PureComponent {
|
||||||
const content = [];
|
const content = [];
|
||||||
|
|
||||||
this._sortFunctions[sortBy](fileInfos).forEach(fileInfo => {
|
this._sortFunctions[sortBy](fileInfos).forEach(fileInfo => {
|
||||||
let uriParams = {
|
let uriParams = {};
|
||||||
claimId: fileInfo.claim_id,
|
|
||||||
};
|
|
||||||
if (fileInfo.channel_name) {
|
if (fileInfo.channel_name) {
|
||||||
uriParams.channelName = fileInfo.channel_name;
|
uriParams.channelName = fileInfo.channel_name;
|
||||||
uriParams.contentName = fileInfo.name;
|
uriParams.contentName = fileInfo.name;
|
||||||
|
uriParams.claimId = this.getChannelSignature(fileInfo);
|
||||||
} else {
|
} else {
|
||||||
uriParams.claimId = fileInfo.claim_id;
|
uriParams.claimId = fileInfo.claim_id;
|
||||||
uriParams.name = fileInfo.name;
|
uriParams.name = fileInfo.name;
|
||||||
|
|
|
@ -19,7 +19,7 @@ class FilePrice extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { costInfo, look = "indicator" } = this.props;
|
const { costInfo, look = "indicator", showFullPrice = false } = this.props;
|
||||||
|
|
||||||
const isEstimate = costInfo ? !costInfo.includesData : null;
|
const isEstimate = costInfo ? !costInfo.includesData : null;
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ class FilePrice extends React.PureComponent {
|
||||||
amount={costInfo.cost}
|
amount={costInfo.cost}
|
||||||
isEstimate={isEstimate}
|
isEstimate={isEstimate}
|
||||||
showFree={true}
|
showFree={true}
|
||||||
|
showFullPrice={showFullPrice}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ class FileTile extends React.PureComponent {
|
||||||
? metadata.thumbnail
|
? metadata.thumbnail
|
||||||
: null;
|
: null;
|
||||||
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw;
|
const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw;
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent =
|
||||||
|
claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
|
|
||||||
let onClick = () => navigate("/show", { uri });
|
let onClick = () => navigate("/show", { uri });
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ class FileTile extends React.PureComponent {
|
||||||
<div className="file-tile__content">
|
<div className="file-tile__content">
|
||||||
<div className="card__title-primary">
|
<div className="card__title-primary">
|
||||||
{!hidePrice ? <FilePrice uri={this.props.uri} /> : null}
|
{!hidePrice ? <FilePrice uri={this.props.uri} /> : null}
|
||||||
{isRewardContent && <IconFeatured /> }
|
{isRewardContent && <IconFeatured />}
|
||||||
<div className="meta">{uri}</div>
|
<div className="meta">{uri}</div>
|
||||||
<h3>
|
<h3>
|
||||||
<TruncatedText lines={1}>{title}</TruncatedText>
|
<TruncatedText lines={1}>{title}</TruncatedText>
|
||||||
|
|
|
@ -14,21 +14,23 @@ class FormFieldPrice extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchChange() {
|
handleChange(newValues) {
|
||||||
|
const newState = Object.assign({}, this.state, newValues);
|
||||||
|
this.setState(newState);
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
amount: this.state.amount,
|
amount: newState.amount,
|
||||||
currency: this.state.currency,
|
currency: newState.currency,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFeeAmountChange(event) {
|
handleFeeAmountChange(event) {
|
||||||
this.state.amount = event.target.value ? Number(event.target.value) : null;
|
this.handleChange({
|
||||||
this.dispatchChange();
|
amount: event.target.value ? Number(event.target.value) : null,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFeeCurrencyChange(event) {
|
handleFeeCurrencyChange(event) {
|
||||||
this.state.currency = event.target.value;
|
this.handleChange({ currency: event.target.value });
|
||||||
this.dispatchChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { formatCredits } from "utils";
|
import { formatCredits } from "util/formatCredits";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
import { selectIsBackDisabled, selectIsForwardDisabled } from "selectors/app";
|
||||||
import { selectBalance } from "selectors/wallet";
|
import { selectBalance } from "selectors/wallet";
|
||||||
import { doNavigate, doHistoryBack } from "actions/app";
|
import { doNavigate, doHistoryBack, doHistoryForward } from "actions/app";
|
||||||
import Header from "./view";
|
import Header from "./view";
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
isBackDisabled: selectIsBackDisabled(state),
|
||||||
|
isForwardDisabled: selectIsForwardDisabled(state),
|
||||||
balance: formatCredits(selectBalance(state), 1),
|
balance: formatCredits(selectBalance(state), 1),
|
||||||
publish: __("Publish"),
|
publish: __("Publish"),
|
||||||
});
|
});
|
||||||
|
@ -13,6 +16,7 @@ const select = state => ({
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
navigate: path => dispatch(doNavigate(path)),
|
||||||
back: () => dispatch(doHistoryBack()),
|
back: () => dispatch(doHistoryBack()),
|
||||||
|
forward: () => dispatch(doHistoryForward()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(Header);
|
export default connect(select, perform)(Header);
|
||||||
|
|
|
@ -3,12 +3,34 @@ import Link from "component/link";
|
||||||
import WunderBar from "component/wunderbar";
|
import WunderBar from "component/wunderbar";
|
||||||
|
|
||||||
export const Header = props => {
|
export const Header = props => {
|
||||||
const { balance, back, navigate, publish } = props;
|
const {
|
||||||
|
balance,
|
||||||
|
back,
|
||||||
|
forward,
|
||||||
|
isBackDisabled,
|
||||||
|
isForwardDisabled,
|
||||||
|
navigate,
|
||||||
|
publish,
|
||||||
|
} = props;
|
||||||
return (
|
return (
|
||||||
<header id="header">
|
<header id="header">
|
||||||
<div className="header__item">
|
<div className="header__item">
|
||||||
<Link onClick={back} button="alt button--flat" icon="icon-arrow-left" title={__("Back")} />
|
<Link
|
||||||
|
onClick={back}
|
||||||
|
disabled={isBackDisabled}
|
||||||
|
button="alt button--flat"
|
||||||
|
icon="icon-arrow-left"
|
||||||
|
title={__("Back")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="header__item">
|
||||||
|
<Link
|
||||||
|
onClick={forward}
|
||||||
|
disabled={isForwardDisabled}
|
||||||
|
button="alt button--flat"
|
||||||
|
icon="icon-arrow-right"
|
||||||
|
title={__("Forward")}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="header__item">
|
<div className="header__item">
|
||||||
<Link
|
<Link
|
||||||
|
|
|
@ -3,10 +3,11 @@ import { Icon } from "component/common.js";
|
||||||
|
|
||||||
const IconFeatured = props => {
|
const IconFeatured = props => {
|
||||||
return (
|
return (
|
||||||
<span className="icon-featured" title={ __("Watch content with this icon to earn weekly rewards.")}>
|
<span
|
||||||
<Icon icon="icon-rocket"
|
className="icon-featured"
|
||||||
fixed
|
title={__("Watch content with this icon to earn weekly rewards.")}
|
||||||
className="card__icon-featured-content" />
|
>
|
||||||
|
<Icon icon="icon-rocket" fixed className="card__icon-featured-content" />
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,11 +17,9 @@ const Link = props => {
|
||||||
|
|
||||||
const className =
|
const className =
|
||||||
(props.className || "") +
|
(props.className || "") +
|
||||||
(!props.className && !props.button ? "button-text" : "") + // Non-button links get the same look as text buttons
|
(!props.className && !button ? "button-text" : "") + // Non-button links get the same look as text buttons
|
||||||
(props.button
|
(button ? " button-block button-" + button + " button-set-item" : "") +
|
||||||
? " button-block button-" + props.button + " button-set-item"
|
(disabled ? " disabled" : "");
|
||||||
: "") +
|
|
||||||
(props.disabled ? " disabled" : "");
|
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
if (children) {
|
if (children) {
|
||||||
|
|
|
@ -69,7 +69,8 @@ export class DropDownMenu extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleWindowClick(e) {
|
/*this will force "this" to always be the class, even when passed to an event listener*/
|
||||||
|
handleWindowClick = e => {
|
||||||
if (
|
if (
|
||||||
this.state.menuOpen &&
|
this.state.menuOpen &&
|
||||||
(!this._menuDiv || !this._menuDiv.contains(e.target))
|
(!this._menuDiv || !this._menuDiv.contains(e.target))
|
||||||
|
@ -78,7 +79,7 @@ export class DropDownMenu extends React.PureComponent {
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.state.menuOpen && this._isWindowClickBound) {
|
if (!this.state.menuOpen && this._isWindowClickBound) {
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { Modal } from "component/modal";
|
|
||||||
import { CreditAmount } from "component/common";
|
|
||||||
import Link from "component/link";
|
|
||||||
import RewardLink from "component/rewardLink";
|
|
||||||
|
|
||||||
class ModalWelcome extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
isFirstScreen: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { closeModal, totalRewardValue, verifyAccount } = this.props;
|
|
||||||
|
|
||||||
const totalRewardRounded = Math.round(totalRewardValue / 10) * 10;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
|
|
||||||
{this.state.isFirstScreen &&
|
|
||||||
<section>
|
|
||||||
<h3 className="modal__header">{__("Welcome to LBRY")}</h3>
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
"Using LBRY is like dating a centaur. Totally normal up top, and"
|
|
||||||
)}
|
|
||||||
{" "}<em>{__("way different")}</em> {__("underneath.")}
|
|
||||||
</p>
|
|
||||||
<p>{__("Up top, LBRY is similar to popular media sites.")}</p>
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
"Below, LBRY is controlled by users -- you -- via blockchain and decentralization."
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<div className="modal__buttons">
|
|
||||||
<Link
|
|
||||||
button="primary"
|
|
||||||
onClick={() => {
|
|
||||||
this.setState({ isFirstScreen: false });
|
|
||||||
}}
|
|
||||||
label={__("Continue")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>}
|
|
||||||
{!this.state.isFirstScreen &&
|
|
||||||
<section>
|
|
||||||
<h3 className="modal__header">{__("Claim Your Credits")}</h3>
|
|
||||||
<p>
|
|
||||||
The LBRY network is controlled and powered by credits called{" "}
|
|
||||||
<em>LBC</em>, a blockchain asset.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{__("New patrons receive ")} {" "}
|
|
||||||
{totalRewardValue
|
|
||||||
? <CreditAmount amount={totalRewardRounded} />
|
|
||||||
: <span className="credit-amount">{__("credits")}</span>}
|
|
||||||
{" "} {__("in rewards for usage and influence of the network.")}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{__(
|
|
||||||
"You'll also earn weekly bonuses for checking out the greatest new stuff."
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<div className="modal__buttons">
|
|
||||||
<Link
|
|
||||||
button="primary"
|
|
||||||
onClick={verifyAccount}
|
|
||||||
label={__("You Had Me At Free LBC")}
|
|
||||||
/>
|
|
||||||
<Link
|
|
||||||
button="alt"
|
|
||||||
onClick={closeModal}
|
|
||||||
label={__("I Burn Money")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>}
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalWelcome;
|
|
|
@ -55,7 +55,7 @@ class ChannelSection extends React.PureComponent {
|
||||||
handleCreateChannelClick(event) {
|
handleCreateChannelClick(event) {
|
||||||
if (this.state.newChannelName.length < 5) {
|
if (this.state.newChannelName.length < 5) {
|
||||||
this.refs.newChannelName.showError(
|
this.refs.newChannelName.showError(
|
||||||
__("LBRY channel names must be at least 4 characters in length.")
|
__("LBRY channel names must be at least 5 characters in length.")
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import FormField from "component/formField";
|
||||||
import { FormRow } from "component/form.js";
|
import { FormRow } from "component/form.js";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import FormFieldPrice from "component/formFieldPrice";
|
import FormFieldPrice from "component/formFieldPrice";
|
||||||
import Modal from "component/modal";
|
import Modal from "modal/modal";
|
||||||
import { BusyMessage } from "component/common";
|
import { BusyMessage } from "component/common";
|
||||||
import ChannelSection from "./internal/channelSection";
|
import ChannelSection from "./internal/channelSection";
|
||||||
|
|
||||||
|
@ -377,46 +377,6 @@ class PublishForm extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCreateChannelClick(event) {
|
|
||||||
if (this.state.newChannelName.length < 5) {
|
|
||||||
this.refs.newChannelName.showError(
|
|
||||||
__("LBRY channel names must be at least 4 characters in length.")
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
creatingChannel: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const newChannelName = this.state.newChannelName;
|
|
||||||
lbry
|
|
||||||
.channel_new({
|
|
||||||
channel_name: newChannelName,
|
|
||||||
amount: parseFloat(this.state.newChannelBid),
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
creatingChannel: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
this._updateChannelList(newChannelName);
|
|
||||||
}, 10000);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
// TODO: better error handling
|
|
||||||
this.refs.newChannelName.showError(
|
|
||||||
__("Unable to create channel due to an internal error.")
|
|
||||||
);
|
|
||||||
this.setState({
|
|
||||||
creatingChannel: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getLicense() {
|
getLicense() {
|
||||||
switch (this.state.licenseType) {
|
switch (this.state.licenseType) {
|
||||||
case "copyright":
|
case "copyright":
|
||||||
|
@ -564,6 +524,7 @@ class PublishForm extends React.PureComponent {
|
||||||
: <div>
|
: <div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow
|
<FormRow
|
||||||
|
ref="meta_title"
|
||||||
label={__("Title")}
|
label={__("Title")}
|
||||||
type="text"
|
type="text"
|
||||||
name="title"
|
name="title"
|
||||||
|
@ -825,6 +786,7 @@ class PublishForm extends React.PureComponent {
|
||||||
ref="bid"
|
ref="bid"
|
||||||
type="number"
|
type="number"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
|
min="0"
|
||||||
label={__("Deposit")}
|
label={__("Deposit")}
|
||||||
postfix="LBC"
|
postfix="LBC"
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
|
@ -833,6 +795,7 @@ class PublishForm extends React.PureComponent {
|
||||||
value={this.state.bid}
|
value={this.state.bid}
|
||||||
placeholder={this.claim() ? this.topClaimValue() + 10 : 100}
|
placeholder={this.claim() ? this.topClaimValue() + 10 : 100}
|
||||||
helper={lbcInputHelp}
|
helper={lbcInputHelp}
|
||||||
|
min="0"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: ""}
|
: ""}
|
||||||
|
@ -844,6 +807,7 @@ class PublishForm extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow
|
<FormRow
|
||||||
|
ref="tosAgree"
|
||||||
label={
|
label={
|
||||||
<span>
|
<span>
|
||||||
{__("I agree to the")}
|
{__("I agree to the")}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Modal from "component/modal";
|
import Modal from "modal/modal";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
|
|
||||||
const RewardLink = props => {
|
const RewardLink = props => {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import FileListPublished from "page/fileListPublished";
|
||||||
import ChannelPage from "page/channel";
|
import ChannelPage from "page/channel";
|
||||||
import SearchPage from "page/search";
|
import SearchPage from "page/search";
|
||||||
import AuthPage from "page/auth";
|
import AuthPage from "page/auth";
|
||||||
|
import BackupPage from "page/backup";
|
||||||
|
|
||||||
const route = (page, routesMap) => {
|
const route = (page, routesMap) => {
|
||||||
const component = routesMap[page];
|
const component = routesMap[page];
|
||||||
|
@ -26,6 +27,7 @@ const Router = props => {
|
||||||
|
|
||||||
return route(currentPage, {
|
return route(currentPage, {
|
||||||
auth: <AuthPage params={params} />,
|
auth: <AuthPage params={params} />,
|
||||||
|
backup: <BackupPage params={params} />,
|
||||||
channel: <ChannelPage params={params} />,
|
channel: <ChannelPage params={params} />,
|
||||||
developer: <DeveloperPage params={params} />,
|
developer: <DeveloperPage params={params} />,
|
||||||
discover: <DiscoverPage params={params} />,
|
discover: <DiscoverPage params={params} />,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import lbry from "../../lbry.js";
|
import lbry from "lbry.js";
|
||||||
import LoadScreen from "../load_screen.js";
|
import LoadScreen from "../load_screen.js";
|
||||||
import ModalIncompatibleDaemon from "../modalIncompatibleDaemon";
|
import ModalIncompatibleDaemon from "modal/modalIncompatibleDaemon";
|
||||||
import ModalUpgrade from "component/modalUpgrade";
|
import ModalUpgrade from "modal/modalUpgrade";
|
||||||
import ModalDownloading from "component/modalDownloading";
|
import ModalDownloading from "modal/modalDownloading";
|
||||||
|
|
||||||
export class SplashScreen extends React.PureComponent {
|
export class SplashScreen extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -34,7 +34,7 @@ class UserEmailNew extends React.PureComponent {
|
||||||
<FormRow
|
<FormRow
|
||||||
type="text"
|
type="text"
|
||||||
label="Email"
|
label="Email"
|
||||||
placeholder="scrwvwls@lbry.io"
|
placeholder="youremail@example.org"
|
||||||
name="email"
|
name="email"
|
||||||
value={this.state.email}
|
value={this.state.email}
|
||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}
|
||||||
|
|
|
@ -21,7 +21,7 @@ const select = (state, props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (uri) => dispatch(doNavigate(uri)),
|
navigate: uri => dispatch(doNavigate(uri)),
|
||||||
verifyUserIdentity: token => dispatch(doUserIdentityVerify(token)),
|
verifyUserIdentity: token => dispatch(doUserIdentityVerify(token)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { CreditAmount } from "component/common";
|
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import CardVerify from "component/cardVerify";
|
import CardVerify from "component/cardVerify";
|
||||||
|
import lbryio from "lbryio.js";
|
||||||
|
|
||||||
class UserVerify extends React.PureComponent {
|
class UserVerify extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -29,20 +29,34 @@ class UserVerify extends React.PureComponent {
|
||||||
<p>
|
<p>
|
||||||
{__(
|
{__(
|
||||||
"To ensure you are a real person, we require a valid credit or debit card."
|
"To ensure you are a real person, we require a valid credit or debit card."
|
||||||
) + " " + __("There is no charge at all, now or in the future.") + " " }
|
) +
|
||||||
<Link href="https://lbry.io/faq/identity-requirements" label={__("Read More")} />
|
" " +
|
||||||
|
__("There is no charge at all, now or in the future.") +
|
||||||
|
" "}
|
||||||
|
<Link
|
||||||
|
href="https://lbry.io/faq/identity-requirements"
|
||||||
|
label={__("Read More")}
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
{errorMessage && <p className="form-field__error">{errorMessage}</p>}
|
{errorMessage && <p className="form-field__error">{errorMessage}</p>}
|
||||||
<p><CardVerify
|
|
||||||
label={__("Link Card and Finish")}
|
|
||||||
disabled={isPending}
|
|
||||||
token={this.onToken.bind(this)}
|
|
||||||
stripeKey="pk_live_e8M4dRNnCCbmpZzduEUZBgJO"
|
|
||||||
/></p>
|
|
||||||
<p>
|
<p>
|
||||||
{__("You can continue without this step, but you will not be eligible to earn rewards.")}
|
<CardVerify
|
||||||
|
label={__("Link Card and Finish")}
|
||||||
|
disabled={isPending}
|
||||||
|
token={this.onToken.bind(this)}
|
||||||
|
stripeKey={lbryio.getStripeToken()}
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
<Link onClick={() => navigate("/discover")} button="alt" label={__("Skip Rewards")} />
|
<p>
|
||||||
|
{__(
|
||||||
|
"You can continue without this step, but you will not be eligible to earn rewards."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<Link
|
||||||
|
onClick={() => navigate("/discover")}
|
||||||
|
button="alt"
|
||||||
|
label={__("Skip Rewards")}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { doCloseModal } from "actions/app";
|
import { doCloseModal } from "actions/app";
|
||||||
import { doNavigate } from "actions/app";
|
import { doNavigate, doChangeVolume } from "actions/app";
|
||||||
import { selectCurrentModal } from "selectors/app";
|
import { selectCurrentModal, selectVolume } from "selectors/app";
|
||||||
import { doPurchaseUri, doLoadVideo } from "actions/content";
|
import { doPurchaseUri, doLoadVideo } from "actions/content";
|
||||||
import {
|
import {
|
||||||
makeSelectMetadataForUri,
|
makeSelectMetadataForUri,
|
||||||
|
@ -34,6 +34,7 @@ const makeSelect = () => {
|
||||||
isLoading: selectIsLoading(state, props),
|
isLoading: selectIsLoading(state, props),
|
||||||
isDownloading: selectIsDownloading(state, props),
|
isDownloading: selectIsDownloading(state, props),
|
||||||
contentType: selectContentType(state, props),
|
contentType: selectContentType(state, props),
|
||||||
|
volume: selectVolume(state, props),
|
||||||
});
|
});
|
||||||
|
|
||||||
return select;
|
return select;
|
||||||
|
@ -43,6 +44,7 @@ const perform = dispatch => ({
|
||||||
loadVideo: uri => dispatch(doLoadVideo(uri)),
|
loadVideo: uri => dispatch(doLoadVideo(uri)),
|
||||||
purchaseUri: uri => dispatch(doPurchaseUri(uri, "affirmPurchaseAndPlay")),
|
purchaseUri: uri => dispatch(doPurchaseUri(uri, "affirmPurchaseAndPlay")),
|
||||||
closeModal: () => dispatch(doCloseModal()),
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
|
changeVolume: volume => dispatch(doChangeVolume(volume)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(makeSelect, perform)(Video);
|
export default connect(makeSelect, perform)(Video);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import FilePrice from "component/filePrice";
|
import FilePrice from "component/filePrice";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import Modal from "component/modal";
|
import Modal from "modal/modal";
|
||||||
|
|
||||||
class VideoPlayButton extends React.PureComponent {
|
class VideoPlayButton extends React.PureComponent {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -83,7 +83,7 @@ class VideoPlayButton extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{__("This will purchase")} <strong>{title}</strong> {__("for")}{" "}
|
{__("This will purchase")} <strong>{title}</strong> {__("for")}{" "}
|
||||||
<strong>
|
<strong>
|
||||||
<FilePrice uri={uri} look="plain" />
|
<FilePrice uri={uri} showFullPrice={true} look="plain" />
|
||||||
</strong>{" "}
|
</strong>{" "}
|
||||||
{__("credits")}.
|
{__("credits")}.
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -3,7 +3,6 @@ import React from "react";
|
||||||
import { Thumbnail } from "component/common";
|
import { Thumbnail } from "component/common";
|
||||||
import player from "render-media";
|
import player from "render-media";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { setSession, getSession } from "utils";
|
|
||||||
import LoadingScreen from "./loading-screen";
|
import LoadingScreen from "./loading-screen";
|
||||||
|
|
||||||
class VideoPlayer extends React.PureComponent {
|
class VideoPlayer extends React.PureComponent {
|
||||||
|
@ -23,7 +22,13 @@ class VideoPlayer extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const container = this.refs.media;
|
const container = this.refs.media;
|
||||||
const { contentType, downloadPath, mediaType } = this.props;
|
const {
|
||||||
|
contentType,
|
||||||
|
downloadPath,
|
||||||
|
mediaType,
|
||||||
|
changeVolume,
|
||||||
|
volume,
|
||||||
|
} = this.props;
|
||||||
const loadedMetadata = e => {
|
const loadedMetadata = e => {
|
||||||
this.setState({ hasMetadata: true, startedPlaying: true });
|
this.setState({ hasMetadata: true, startedPlaying: true });
|
||||||
this.refs.media.children[0].play();
|
this.refs.media.children[0].play();
|
||||||
|
@ -69,9 +74,9 @@ class VideoPlayer extends React.PureComponent {
|
||||||
win32FullScreenChange.bind(this)
|
win32FullScreenChange.bind(this)
|
||||||
);
|
);
|
||||||
mediaElement.addEventListener("volumechange", () => {
|
mediaElement.addEventListener("volumechange", () => {
|
||||||
setSession("prefs_volume", mediaElement.volume);
|
changeVolume(mediaElement.volume);
|
||||||
});
|
});
|
||||||
mediaElement.volume = this.getPreferredVolume();
|
mediaElement.volume = volume;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +121,6 @@ class VideoPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreferredVolume() {
|
|
||||||
const volumePreference = parseFloat(getSession("prefs_volume"));
|
|
||||||
return isNaN(volumePreference) ? 1 : volumePreference;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const { contentType, downloadCompleted } = this.props;
|
const { contentType, downloadCompleted } = this.props;
|
||||||
const { startedPlaying } = this.state;
|
const { startedPlaying } = this.state;
|
||||||
|
|
|
@ -16,7 +16,11 @@ class Video extends React.PureComponent {
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
// reset playing state upon change path action
|
// reset playing state upon change path action
|
||||||
if (!this.isMediaSame(nextProps) && this.props.fileInfo && this.state.isPlaying) {
|
if (
|
||||||
|
!this.isMediaSame(nextProps) &&
|
||||||
|
this.props.fileInfo &&
|
||||||
|
this.state.isPlaying
|
||||||
|
) {
|
||||||
this.state.isPlaying = false;
|
this.state.isPlaying = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +66,8 @@ class Video extends React.PureComponent {
|
||||||
isDownloading,
|
isDownloading,
|
||||||
fileInfo,
|
fileInfo,
|
||||||
contentType,
|
contentType,
|
||||||
|
changeVolume,
|
||||||
|
volume,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { isPlaying = false } = this.state;
|
const { isPlaying = false } = this.state;
|
||||||
|
|
||||||
|
@ -115,6 +121,8 @@ class Video extends React.PureComponent {
|
||||||
mediaType={mediaType}
|
mediaType={mediaType}
|
||||||
contentType={contentType}
|
contentType={contentType}
|
||||||
downloadCompleted={fileInfo.completed}
|
downloadCompleted={fileInfo.completed}
|
||||||
|
changeVolume={changeVolume}
|
||||||
|
volume={volume}
|
||||||
/>)}
|
/>)}
|
||||||
{!isPlaying &&
|
{!isPlaying &&
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
|
import Modal from "modal/modal";
|
||||||
import { FormRow } from "component/form";
|
import { FormRow } from "component/form";
|
||||||
|
|
||||||
const WalletSend = props => {
|
const WalletSend = props => {
|
||||||
|
@ -16,6 +17,7 @@ const WalletSend = props => {
|
||||||
label={__("Amount")}
|
label={__("Amount")}
|
||||||
postfix={__("LBC")}
|
postfix={__("LBC")}
|
||||||
step="0.01"
|
step="0.01"
|
||||||
|
min="0"
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="1.23"
|
placeholder="1.23"
|
||||||
size="10"
|
size="10"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export const CHANGE_PATH = "CHANGE_PATH";
|
export const CHANGE_PATH = "CHANGE_PATH";
|
||||||
export const OPEN_MODAL = "OPEN_MODAL";
|
export const OPEN_MODAL = "OPEN_MODAL";
|
||||||
export const CLOSE_MODAL = "CLOSE_MODAL";
|
export const CLOSE_MODAL = "CLOSE_MODAL";
|
||||||
export const HISTORY_BACK = "HISTORY_BACK";
|
export const HISTORY_NAVIGATE = "HISTORY_NAVIGATE";
|
||||||
export const SHOW_SNACKBAR = "SHOW_SNACKBAR";
|
export const SHOW_SNACKBAR = "SHOW_SNACKBAR";
|
||||||
export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
|
export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
|
||||||
export const WINDOW_FOCUSED = "WINDOW_FOCUSED";
|
export const WINDOW_FOCUSED = "WINDOW_FOCUSED";
|
||||||
|
@ -9,6 +9,7 @@ export const CHANGE_AFTER_AUTH_PATH = "CHANGE_AFTER_AUTH_PATH";
|
||||||
export const DAEMON_READY = "DAEMON_READY";
|
export const DAEMON_READY = "DAEMON_READY";
|
||||||
export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH";
|
export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH";
|
||||||
export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH";
|
export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH";
|
||||||
|
export const VOLUME_CHANGED = "VOLUME_CHANGED";
|
||||||
|
|
||||||
// Upgrades
|
// Upgrades
|
||||||
export const UPGRADE_CANCELLED = "UPGRADE_CANCELLED";
|
export const UPGRADE_CANCELLED = "UPGRADE_CANCELLED";
|
||||||
|
@ -45,6 +46,10 @@ export const RESOLVE_URI_COMPLETED = "RESOLVE_URI_COMPLETED";
|
||||||
export const RESOLVE_URI_CANCELED = "RESOLVE_URI_CANCELED";
|
export const RESOLVE_URI_CANCELED = "RESOLVE_URI_CANCELED";
|
||||||
export const FETCH_CHANNEL_CLAIMS_STARTED = "FETCH_CHANNEL_CLAIMS_STARTED";
|
export const FETCH_CHANNEL_CLAIMS_STARTED = "FETCH_CHANNEL_CLAIMS_STARTED";
|
||||||
export const FETCH_CHANNEL_CLAIMS_COMPLETED = "FETCH_CHANNEL_CLAIMS_COMPLETED";
|
export const FETCH_CHANNEL_CLAIMS_COMPLETED = "FETCH_CHANNEL_CLAIMS_COMPLETED";
|
||||||
|
export const FETCH_CHANNEL_CLAIM_COUNT_STARTED =
|
||||||
|
"FETCH_CHANNEL_CLAIM_COUNT_STARTED";
|
||||||
|
export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED =
|
||||||
|
"FETCH_CHANNEL_CLAIM_COUNT_COMPLETED";
|
||||||
export const FETCH_CLAIM_LIST_MINE_STARTED = "FETCH_CLAIM_LIST_MINE_STARTED";
|
export const FETCH_CLAIM_LIST_MINE_STARTED = "FETCH_CLAIM_LIST_MINE_STARTED";
|
||||||
export const FETCH_CLAIM_LIST_MINE_COMPLETED =
|
export const FETCH_CLAIM_LIST_MINE_COMPLETED =
|
||||||
"FETCH_CLAIM_LIST_MINE_COMPLETED";
|
"FETCH_CLAIM_LIST_MINE_COMPLETED";
|
||||||
|
@ -118,3 +123,7 @@ export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED";
|
||||||
export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED";
|
export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED";
|
||||||
export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED";
|
export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED";
|
||||||
export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED";
|
export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED";
|
||||||
|
|
||||||
|
//Language
|
||||||
|
export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED";
|
||||||
|
export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED";
|
||||||
|
|
187
ui/js/constants/languages.js
Normal file
187
ui/js/constants/languages.js
Normal file
|
@ -0,0 +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"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LANGUAGES;
|
|
@ -9,3 +9,4 @@ export const FIRST_REWARD = "first_reward";
|
||||||
export const AUTHENTICATION_FAILURE = "auth_failure";
|
export const AUTHENTICATION_FAILURE = "auth_failure";
|
||||||
export const TRANSACTION_FAILED = "transaction_failed";
|
export const TRANSACTION_FAILED = "transaction_failed";
|
||||||
export const INSUFFICIENT_BALANCE = "insufficient_balance";
|
export const INSUFFICIENT_BALANCE = "insufficient_balance";
|
||||||
|
export const CREDIT_INTRO = "credit_intro";
|
||||||
|
|
5
ui/js/constants/settings.js
Normal file
5
ui/js/constants/settings.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export const CREDIT_INTRO_ACKNOWLEDGED = "credit_intro_acknowledged";
|
||||||
|
export const FIRST_RUN_ACKNOWLEDGED = "welcome_acknowledged";
|
||||||
|
export const LANGUAGE = "language";
|
||||||
|
export const SHOW_NSFW = "showNsfw";
|
||||||
|
export const SHOW_UNAVAILABLE = "showUnavailable";
|
|
@ -27,7 +27,7 @@ jsonrpc.call = function(
|
||||||
xhr.addEventListener("load", function() {
|
xhr.addEventListener("load", function() {
|
||||||
var response = JSON.parse(xhr.responseText);
|
var response = JSON.parse(xhr.responseText);
|
||||||
|
|
||||||
let error = response.error || response.result && response.result.error;
|
let error = response.error || (response.result && response.result.error);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (errorCallback) {
|
if (errorCallback) {
|
||||||
errorCallback(error);
|
errorCallback(error);
|
||||||
|
|
|
@ -1,15 +1,35 @@
|
||||||
import lbryio from "./lbryio.js";
|
|
||||||
import lighthouse from "./lighthouse.js";
|
import lighthouse from "./lighthouse.js";
|
||||||
import jsonrpc from "./jsonrpc.js";
|
import jsonrpc from "./jsonrpc.js";
|
||||||
import lbryuri from "./lbryuri.js";
|
import lbryuri from "./lbryuri.js";
|
||||||
import { getLocal, getSession, setSession, setLocal } from "./utils.js";
|
|
||||||
|
/**
|
||||||
|
* The 4 get/set functions below used to be in a utils.js library when used more widely.
|
||||||
|
* They've been reduced to just this file and probably ought to be eliminated entirely.
|
||||||
|
*/
|
||||||
|
function getLocal(key, fallback = undefined) {
|
||||||
|
const itemRaw = localStorage.getItem(key);
|
||||||
|
return itemRaw === null ? fallback : JSON.parse(itemRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLocal(key, value) {
|
||||||
|
localStorage.setItem(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSession(key, fallback = undefined) {
|
||||||
|
const itemRaw = sessionStorage.getItem(key);
|
||||||
|
return itemRaw === null ? fallback : JSON.parse(itemRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSession(key, value) {
|
||||||
|
sessionStorage.setItem(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
const { remote, ipcRenderer } = require("electron");
|
const { remote, ipcRenderer } = require("electron");
|
||||||
const menu = remote.require("./menu/main-menu");
|
const menu = remote.require("./menu/main-menu");
|
||||||
|
|
||||||
let lbry = {
|
let lbry = {
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
daemonConnectionString: "http://localhost:5279/lbryapi",
|
daemonConnectionString: "http://localhost:5279",
|
||||||
pendingPublishTimeout: 20 * 60 * 1000,
|
pendingPublishTimeout: 20 * 60 * 1000,
|
||||||
defaultClientSettings: {
|
defaultClientSettings: {
|
||||||
showNsfw: false,
|
showNsfw: false,
|
||||||
|
|
|
@ -148,7 +148,6 @@ lbryio.authenticate = function() {
|
||||||
has_verified_email: true,
|
has_verified_email: true,
|
||||||
is_identity_verified: true,
|
is_identity_verified: true,
|
||||||
is_reward_approved: false,
|
is_reward_approved: false,
|
||||||
is_reward_eligible: false,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -177,32 +176,20 @@ lbryio.authenticate = function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_id;
|
|
||||||
|
|
||||||
return lbry
|
return lbry
|
||||||
.status()
|
.status()
|
||||||
.then(status => {
|
.then(status => {
|
||||||
// first try swapping
|
|
||||||
app_id = status.installation_id;
|
|
||||||
return lbryio.call(
|
return lbryio.call(
|
||||||
"user",
|
"user",
|
||||||
"token_swap",
|
"new",
|
||||||
{ auth_token: "", app_id: app_id },
|
{
|
||||||
|
auth_token: "",
|
||||||
|
language: "en",
|
||||||
|
app_id: status.installation_id,
|
||||||
|
},
|
||||||
"post"
|
"post"
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
|
||||||
if (err.xhr.status == 403) {
|
|
||||||
// cannot swap. either app_id doesn't exist, or app_id already swapped. pretend its the former and create a new user. if we get another error, then its the latter
|
|
||||||
return lbryio.call(
|
|
||||||
"user",
|
|
||||||
"new",
|
|
||||||
{ auth_token: "", language: "en", app_id: app_id },
|
|
||||||
"post"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.auth_token) {
|
if (!response.auth_token) {
|
||||||
throw new Error(__("auth_token is missing from response"));
|
throw new Error(__("auth_token is missing from response"));
|
||||||
|
@ -218,4 +205,10 @@ lbryio.authenticate = function() {
|
||||||
return lbryio._authenticationPromise;
|
return lbryio._authenticationPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
lbryio.getStripeToken = () => {
|
||||||
|
return CONNECTION_STRING.startsWith("http://localhost:")
|
||||||
|
? "pk_test_NoL1JWL7i1ipfhVId5KfDZgo"
|
||||||
|
: "pk_live_e8M4dRNnCCbmpZzduEUZBgJO";
|
||||||
|
};
|
||||||
|
|
||||||
export default lbryio;
|
export default lbryio;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Provider } from "react-redux";
|
||||||
import store from "store.js";
|
import store from "store.js";
|
||||||
import SplashScreen from "component/splash";
|
import SplashScreen from "component/splash";
|
||||||
import { doChangePath, doNavigate, doDaemonReady } from "actions/app";
|
import { doChangePath, doNavigate, doDaemonReady } from "actions/app";
|
||||||
|
import { doDownloadLanguages } from "actions/settings";
|
||||||
import { toQueryString } from "util/query_params";
|
import { toQueryString } from "util/query_params";
|
||||||
import * as types from "constants/action_types";
|
import * as types from "constants/action_types";
|
||||||
|
|
||||||
|
@ -96,6 +97,8 @@ const updateProgress = () => {
|
||||||
const initialState = app.store.getState();
|
const initialState = app.store.getState();
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
|
app.store.dispatch(doDownloadLanguages());
|
||||||
|
|
||||||
function onDaemonReady() {
|
function onDaemonReady() {
|
||||||
window.sessionStorage.setItem("loaded", "y"); //once we've made it here once per session, we don't need to show splash again
|
window.sessionStorage.setItem("loaded", "y"); //once we've made it here once per session, we don't need to show splash again
|
||||||
app.store.dispatch(doDaemonReady());
|
app.store.dispatch(doDaemonReady());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactModal from "react-modal";
|
import ReactModal from "react-modal";
|
||||||
import Link from "component/link";
|
import Link from "component/link/index";
|
||||||
import app from "../app.js";
|
import app from "app.js";
|
||||||
|
|
||||||
export class Modal extends React.PureComponent {
|
export class Modal extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Modal } from "component/modal";
|
import { Modal } from "modal/modal";
|
||||||
|
|
||||||
class ModalAuthFailure extends React.PureComponent {
|
class ModalAuthFailure extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
|
@ -12,11 +12,17 @@ class ModalAuthFailure extends React.PureComponent {
|
||||||
type="confirm"
|
type="confirm"
|
||||||
confirmButtonLabel={__("Reload")}
|
confirmButtonLabel={__("Reload")}
|
||||||
abortButtonLabel={__("Continue")}
|
abortButtonLabel={__("Continue")}
|
||||||
onConfirmed={() => { window.location.reload() }}
|
onConfirmed={() => {
|
||||||
|
window.location.reload();
|
||||||
|
}}
|
||||||
onAborted={close}
|
onAborted={close}
|
||||||
>
|
>
|
||||||
<h3>{__("Authentication Failure")}</h3>
|
<h3>{__("Authentication Failure")}</h3>
|
||||||
<p>{__("If reloading does not fix this, or you see this at every start up, please email help@lbry.io.")}</p>
|
<p>
|
||||||
|
{__(
|
||||||
|
"If reloading does not fix this, or you see this at every start up, please email help@lbry.io."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -9,7 +9,8 @@ import {
|
||||||
makeSelectRewardByType,
|
makeSelectRewardByType,
|
||||||
selectTotalRewardValue,
|
selectTotalRewardValue,
|
||||||
} from "selectors/rewards";
|
} from "selectors/rewards";
|
||||||
import ModalWelcome from "./view";
|
import * as settings from "constants/settings";
|
||||||
|
import ModalCreditIntro from "./view";
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const selectHasClaimed = makeSelectHasClaimedReward(),
|
const selectHasClaimed = makeSelectHasClaimedReward(),
|
||||||
|
@ -24,7 +25,7 @@ const select = (state, props) => {
|
||||||
|
|
||||||
const perform = dispatch => () => {
|
const perform = dispatch => () => {
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
dispatch(doSetClientSetting("welcome_acknowledged", true));
|
dispatch(doSetClientSetting(settings.CREDIT_INTRO_ACKNOWLEDGED, true));
|
||||||
dispatch(doCloseModal());
|
dispatch(doCloseModal());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,4 +38,4 @@ const perform = dispatch => () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(select, perform)(ModalWelcome);
|
export default connect(select, perform)(ModalCreditIntro);
|
44
ui/js/modal/modalCreditIntro/view.jsx
Normal file
44
ui/js/modal/modalCreditIntro/view.jsx
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Modal } from "modal/modal";
|
||||||
|
import { CreditAmount } from "component/common";
|
||||||
|
import Link from "component/link/index";
|
||||||
|
|
||||||
|
const ModalCreditIntro = props => {
|
||||||
|
const { closeModal, totalRewardValue, verifyAccount } = props;
|
||||||
|
|
||||||
|
const totalRewardRounded = Math.round(totalRewardValue / 10) * 10;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
|
||||||
|
<section>
|
||||||
|
<h3 className="modal__header">{__("Claim Your Credits")}</h3>
|
||||||
|
<p>
|
||||||
|
The LBRY network is controlled and powered by credits called{" "}
|
||||||
|
<em>LBC</em>, a blockchain asset.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__("New patrons receive ")} {" "}
|
||||||
|
{totalRewardValue
|
||||||
|
? <CreditAmount amount={totalRewardRounded} />
|
||||||
|
: <span className="credit-amount">{__("credits")}</span>}
|
||||||
|
{" "} {__("in rewards for usage and influence of the network.")}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"You'll also earn weekly bonuses for checking out the greatest new stuff."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<div className="modal__buttons">
|
||||||
|
<Link
|
||||||
|
button="primary"
|
||||||
|
onClick={verifyAccount}
|
||||||
|
label={__("You Had Me At Free LBC")}
|
||||||
|
/>
|
||||||
|
<Link button="alt" onClick={closeModal} label={__("I Burn Money")} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModalCreditIntro;
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Modal } from "component/modal";
|
import { Modal } from "modal/modal";
|
||||||
import { Line } from "rc-progress";
|
import { Line } from "rc-progress";
|
||||||
import Link from "component/link";
|
import Link from "component/link/index";
|
||||||
|
|
||||||
class ModalDownloading extends React.PureComponent {
|
class ModalDownloading extends React.PureComponent {
|
||||||
render() {
|
render() {
|
|
@ -1,6 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import lbry from "lbry";
|
import lbry from "lbry";
|
||||||
import { ExpandableModal } from "component/modal";
|
import { ExpandableModal } from "modal/modal";
|
||||||
|
|
||||||
class ModalError extends React.PureComponent {
|
class ModalError extends React.PureComponent {
|
||||||
render() {
|
render() {
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Modal } from "component/modal";
|
import { Modal } from "modal/modal";
|
||||||
import { CreditAmount } from "component/common";
|
import { CreditAmount } from "component/common";
|
||||||
|
|
||||||
class ModalFirstReward extends React.PureComponent {
|
class ModalFirstReward extends React.PureComponent {
|
|
@ -1,6 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Modal } from "component/modal";
|
import { Modal } from "modal/modal";
|
||||||
import Link from "component/link";
|
import Link from "component/link/index";
|
||||||
|
|
||||||
class ModalIncompatibleDaemon extends React.PureComponent {
|
class ModalIncompatibleDaemon extends React.PureComponent {
|
||||||
render() {
|
render() {
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue