From 5bf9ac9fe61bd2aff8114fe34ea645b6185bb246 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 4 Aug 2017 19:36:36 -0600 Subject: [PATCH 001/132] implement theme-system --- ui/dist/index.html | 2 +- ui/js/lbry.js | 1 + ui/js/page/settings/view.jsx | 32 +++++++++++++++++++++++++++++++- ui/js/util/getThemes.js | 20 ++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 ui/js/util/getThemes.js diff --git a/ui/dist/index.html b/ui/dist/index.html index d951dddd1..c5b675312 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -6,7 +6,7 @@ - + diff --git a/ui/js/lbry.js b/ui/js/lbry.js index e43a20b55..e66362088 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -19,6 +19,7 @@ let lbry = { customLighthouseServers: [], showDeveloperMenu: false, language: "en", + theme: "light", }, }; diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index d7646c476..9767a5efe 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -3,9 +3,12 @@ import { FormField, FormRow } from "component/form.js"; import SubHeader from "component/subHeader"; import lbry from "lbry.js"; import Link from "component/link"; - +import getThemes from "util/getThemes"; const { remote } = require("electron"); +const themes = getThemes(); +console.log(themes); + class SettingsPage extends React.PureComponent { constructor(props) { super(props); @@ -18,6 +21,7 @@ class SettingsPage extends React.PureComponent { showUnavailable: lbry.getClientSetting("showUnavailable"), language: lbry.getClientSetting("language"), clearingCache: false, + theme: lbry.getClientSetting("theme"), }; } @@ -81,6 +85,13 @@ class SettingsPage extends React.PureComponent { this.setDaemonSetting("disable_max_key_fee", isDisabled); } + onThemeChange(event) { + const value = event.target.value; + const link = document.getElementById("theme"); + link.href = `./themes/${value}.css`; + this.props.setClientSetting("theme", value); + } + // onMaxUploadPrefChange(isLimited) { // if (!isLimited) { // this.setDaemonSetting("max_upload", 0.0); @@ -251,6 +262,25 @@ class SettingsPage extends React.PureComponent { +
+
+

{__("Theme")}

+
+
+ + {themes.map((i, k) => + + )} + + +
+
+

{__("Application Cache")}

diff --git a/ui/js/util/getThemes.js b/ui/js/util/getThemes.js new file mode 100644 index 000000000..d82bc4d0c --- /dev/null +++ b/ui/js/util/getThemes.js @@ -0,0 +1,20 @@ +const { readdirSync } = require("fs"); +const { extname } = require("path"); +const { remote } = require("electron"); + +function getThemes() { + // Themes path + const themesPath = `${remote.app.getAppPath()}/dist/themes`; + + // Get all themes / only .css + const themes = readdirSync(themesPath).filter(function(file) { + return extname(file) === ".css"; + }); + + // Remove file extension (css) + return themes.map(function(theme) { + return theme.replace(".css", ""); + }); +} + +export default getThemes; From 977d116f40e686446a64b6bbac6bfa207654a5bb Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 4 Aug 2017 19:42:38 -0600 Subject: [PATCH 002/132] remove debug --- ui/js/page/settings/view.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 9767a5efe..7d548909b 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -4,10 +4,9 @@ import SubHeader from "component/subHeader"; import lbry from "lbry.js"; import Link from "component/link"; import getThemes from "util/getThemes"; -const { remote } = require("electron"); +const { remote } = require("electron"); const themes = getThemes(); -console.log(themes); class SettingsPage extends React.PureComponent { constructor(props) { From 4bbab4befcdc6f8fc938c2560857440acbe500ef Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 4 Aug 2017 20:11:07 -0600 Subject: [PATCH 003/132] set default theme --- ui/js/page/settings/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 7d548909b..8fa7c93a8 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -269,7 +269,7 @@ class SettingsPage extends React.PureComponent { {themes.map((i, k) => From 9eec9fae1ad110739a6e4f158c71f945bc8b53d0 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 4 Aug 2017 20:18:18 -0600 Subject: [PATCH 004/132] tidy up From 8b7bb673549ae93b4550e90b7f790f81a32ac0d3 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 4 Aug 2017 21:07:07 -0600 Subject: [PATCH 005/132] add themes folder --- ui/dist/themes/light.css | 2859 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 2859 insertions(+) create mode 100644 ui/dist/themes/light.css diff --git a/ui/dist/themes/light.css b/ui/dist/themes/light.css new file mode 100644 index 000000000..bdddae868 --- /dev/null +++ b/ui/dist/themes/light.css @@ -0,0 +1,2859 @@ +body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, select, textarea, p, blockquote, th, td, iframe { + margin: 0; + padding: 0; } + +:focus { + outline: 0; } + +input::-webkit-search-cancel-button { + /* Remove default */ + -webkit-appearance: none; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +fieldset, img, iframe { + border: 0; } + +h1, h2, h3, h4, h5, h6 { + font-weight: normal; } + +ol, ul { + list-style-position: inside; } + ol > li, ul > li { + list-style-position: inside; } + +input, textarea, select { + font-family: inherit; + font-size: inherit; + font-weight: inherit; + border: 0 none; } + +img { + width: auto\9; + height: auto; + vertical-align: middle; + -ms-interpolation-mode: bicubic; } + +a { + color: inherit; + text-decoration: none; } + +@font-face { + font-family: 'FontAwesome'; + src: url("../font/fontawesome-webfont.eot?v=4.3.0"); + src: url("../font/fontawesome-webfont.eot?#iefix&v=4.3.0") format("embedded-opentype"), url("../font/fontawesome-webfont.woff2?v=4.3.0") format("woff2"), url("../font/fontawesome-webfont.woff?v=4.3.0") format("woff"), url("../font/fontawesome-webfont.ttf?v=4.3.0") format("truetype"), url("../font/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular") format("svg"); + font-weight: normal; + font-style: normal; } + +[class*="icon-"] { + display: inline-block; + text-align: center; + font-family: "FontAwesome"; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + speak: none; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: inherit; + text-rendering: auto; + transform: translate(0, 0); } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.icon-glass:before { + content: "\f000"; } + +.icon-music:before { + content: "\f001"; } + +.icon-search:before { + content: "\f002"; } + +.icon-envelope-o:before { + content: "\f003"; } + +.icon-heart:before { + content: "\f004"; } + +.icon-star:before { + content: "\f005"; } + +.icon-star-o:before { + content: "\f006"; } + +.icon-user:before { + content: "\f007"; } + +.icon-film:before { + content: "\f008"; } + +.icon-th-large:before { + content: "\f009"; } + +.icon-th:before { + content: "\f00a"; } + +.icon-th-list:before { + content: "\f00b"; } + +.icon-check:before { + content: "\f00c"; } + +.icon-remove:before, +.icon-close:before, +.icon-times:before { + content: "\f00d"; } + +.icon-search-plus:before { + content: "\f00e"; } + +.icon-search-minus:before { + content: "\f010"; } + +.icon-power-off:before { + content: "\f011"; } + +.icon-signal:before { + content: "\f012"; } + +.icon-gear:before, +.icon-cog:before { + content: "\f013"; } + +.icon-trash-o:before { + content: "\f014"; } + +.icon-home:before { + content: "\f015"; } + +.icon-file-o:before { + content: "\f016"; } + +.icon-clock-o:before { + content: "\f017"; } + +.icon-road:before { + content: "\f018"; } + +.icon-download:before { + content: "\f019"; } + +.icon-arrow-circle-o-down:before { + content: "\f01a"; } + +.icon-arrow-circle-o-up:before { + content: "\f01b"; } + +.icon-inbox:before { + content: "\f01c"; } + +.icon-play-circle-o:before { + content: "\f01d"; } + +.icon-rotate-right:before, +.icon-repeat:before { + content: "\f01e"; } + +.icon-refresh:before { + content: "\f021"; } + +.icon-list-alt:before { + content: "\f022"; } + +.icon-lock:before { + content: "\f023"; } + +.icon-flag:before { + content: "\f024"; } + +.icon-headphones:before { + content: "\f025"; } + +.icon-volume-off:before { + content: "\f026"; } + +.icon-volume-down:before { + content: "\f027"; } + +.icon-volume-up:before { + content: "\f028"; } + +.icon-qrcode:before { + content: "\f029"; } + +.icon-barcode:before { + content: "\f02a"; } + +.icon-tag:before { + content: "\f02b"; } + +.icon-tags:before { + content: "\f02c"; } + +.icon-book:before { + content: "\f02d"; } + +.icon-bookmark:before { + content: "\f02e"; } + +.icon-print:before { + content: "\f02f"; } + +.icon-camera:before { + content: "\f030"; } + +.icon-font:before { + content: "\f031"; } + +.icon-bold:before { + content: "\f032"; } + +.icon-italic:before { + content: "\f033"; } + +.icon-text-height:before { + content: "\f034"; } + +.icon-text-width:before { + content: "\f035"; } + +.icon-align-left:before { + content: "\f036"; } + +.icon-align-center:before { + content: "\f037"; } + +.icon-align-right:before { + content: "\f038"; } + +.icon-align-justify:before { + content: "\f039"; } + +.icon-list:before { + content: "\f03a"; } + +.icon-dedent:before, +.icon-outdent:before { + content: "\f03b"; } + +.icon-indent:before { + content: "\f03c"; } + +.icon-video-camera:before { + content: "\f03d"; } + +.icon-photo:before, +.icon-image:before, +.icon-picture-o:before { + content: "\f03e"; } + +.icon-pencil:before { + content: "\f040"; } + +.icon-map-marker:before { + content: "\f041"; } + +.icon-adjust:before { + content: "\f042"; } + +.icon-tint:before { + content: "\f043"; } + +.icon-edit:before, +.icon-pencil-square-o:before { + content: "\f044"; } + +.icon-share-square-o:before { + content: "\f045"; } + +.icon-check-square-o:before { + content: "\f046"; } + +.icon-arrows:before { + content: "\f047"; } + +.icon-step-backward:before { + content: "\f048"; } + +.icon-fast-backward:before { + content: "\f049"; } + +.icon-backward:before { + content: "\f04a"; } + +.icon-play:before { + content: "\f04b"; } + +.icon-pause:before { + content: "\f04c"; } + +.icon-stop:before { + content: "\f04d"; } + +.icon-forward:before { + content: "\f04e"; } + +.icon-fast-forward:before { + content: "\f050"; } + +.icon-step-forward:before { + content: "\f051"; } + +.icon-eject:before { + content: "\f052"; } + +.icon-chevron-left:before { + content: "\f053"; } + +.icon-chevron-right:before { + content: "\f054"; } + +.icon-plus-circle:before { + content: "\f055"; } + +.icon-minus-circle:before { + content: "\f056"; } + +.icon-times-circle:before { + content: "\f057"; } + +.icon-check-circle:before { + content: "\f058"; } + +.icon-question-circle:before { + content: "\f059"; } + +.icon-info-circle:before { + content: "\f05a"; } + +.icon-crosshairs:before { + content: "\f05b"; } + +.icon-times-circle-o:before { + content: "\f05c"; } + +.icon-check-circle-o:before { + content: "\f05d"; } + +.icon-ban:before { + content: "\f05e"; } + +.icon-arrow-left:before { + content: "\f060"; } + +.icon-arrow-right:before { + content: "\f061"; } + +.icon-arrow-up:before { + content: "\f062"; } + +.icon-arrow-down:before { + content: "\f063"; } + +.icon-mail-forward:before, +.icon-share:before { + content: "\f064"; } + +.icon-expand:before { + content: "\f065"; } + +.icon-compress:before { + content: "\f066"; } + +.icon-plus:before { + content: "\f067"; } + +.icon-minus:before { + content: "\f068"; } + +.icon-asterisk:before { + content: "\f069"; } + +.icon-exclamation-circle:before { + content: "\f06a"; } + +.icon-gift:before { + content: "\f06b"; } + +.icon-leaf:before { + content: "\f06c"; } + +.icon-fire:before { + content: "\f06d"; } + +.icon-eye:before { + content: "\f06e"; } + +.icon-eye-slash:before { + content: "\f070"; } + +.icon-warning:before, +.icon-exclamation-triangle:before { + content: "\f071"; } + +.icon-plane:before { + content: "\f072"; } + +.icon-calendar:before { + content: "\f073"; } + +.icon-random:before { + content: "\f074"; } + +.icon-comment:before { + content: "\f075"; } + +.icon-magnet:before { + content: "\f076"; } + +.icon-chevron-up:before { + content: "\f077"; } + +.icon-chevron-down:before { + content: "\f078"; } + +.icon-retweet:before { + content: "\f079"; } + +.icon-shopping-cart:before { + content: "\f07a"; } + +.icon-folder:before { + content: "\f07b"; } + +.icon-folder-open:before { + content: "\f07c"; } + +.icon-arrows-v:before { + content: "\f07d"; } + +.icon-arrows-h:before { + content: "\f07e"; } + +.icon-bar-chart-o:before, +.icon-bar-chart:before { + content: "\f080"; } + +.icon-twitter-square:before { + content: "\f081"; } + +.icon-facebook-square:before { + content: "\f082"; } + +.icon-camera-retro:before { + content: "\f083"; } + +.icon-key:before { + content: "\f084"; } + +.icon-gears:before, +.icon-cogs:before { + content: "\f085"; } + +.icon-comments:before { + content: "\f086"; } + +.icon-thumbs-o-up:before { + content: "\f087"; } + +.icon-thumbs-o-down:before { + content: "\f088"; } + +.icon-star-half:before { + content: "\f089"; } + +.icon-heart-o:before { + content: "\f08a"; } + +.icon-sign-out:before { + content: "\f08b"; } + +.icon-linkedin-square:before { + content: "\f08c"; } + +.icon-thumb-tack:before { + content: "\f08d"; } + +.icon-external-link:before { + content: "\f08e"; } + +.icon-sign-in:before { + content: "\f090"; } + +.icon-trophy:before { + content: "\f091"; } + +.icon-github-square:before { + content: "\f092"; } + +.icon-upload:before { + content: "\f093"; } + +.icon-lemon-o:before { + content: "\f094"; } + +.icon-phone:before { + content: "\f095"; } + +.icon-square-o:before { + content: "\f096"; } + +.icon-bookmark-o:before { + content: "\f097"; } + +.icon-phone-square:before { + content: "\f098"; } + +.icon-twitter:before { + content: "\f099"; } + +.icon-facebook-f:before, +.icon-facebook:before { + content: "\f09a"; } + +.icon-github:before { + content: "\f09b"; } + +.icon-unlock:before { + content: "\f09c"; } + +.icon-credit-card:before { + content: "\f09d"; } + +.icon-rss:before { + content: "\f09e"; } + +.icon-hdd-o:before { + content: "\f0a0"; } + +.icon-bullhorn:before { + content: "\f0a1"; } + +.icon-bell:before { + content: "\f0f3"; } + +.icon-certificate:before { + content: "\f0a3"; } + +.icon-hand-o-right:before { + content: "\f0a4"; } + +.icon-hand-o-left:before { + content: "\f0a5"; } + +.icon-hand-o-up:before { + content: "\f0a6"; } + +.icon-hand-o-down:before { + content: "\f0a7"; } + +.icon-arrow-circle-left:before { + content: "\f0a8"; } + +.icon-arrow-circle-right:before { + content: "\f0a9"; } + +.icon-arrow-circle-up:before { + content: "\f0aa"; } + +.icon-arrow-circle-down:before { + content: "\f0ab"; } + +.icon-globe:before { + content: "\f0ac"; } + +.icon-wrench:before { + content: "\f0ad"; } + +.icon-tasks:before { + content: "\f0ae"; } + +.icon-filter:before { + content: "\f0b0"; } + +.icon-briefcase:before { + content: "\f0b1"; } + +.icon-arrows-alt:before { + content: "\f0b2"; } + +.icon-group:before, +.icon-users:before { + content: "\f0c0"; } + +.icon-chain:before, +.icon-link:before { + content: "\f0c1"; } + +.icon-cloud:before { + content: "\f0c2"; } + +.icon-flask:before { + content: "\f0c3"; } + +.icon-cut:before, +.icon-scissors:before { + content: "\f0c4"; } + +.icon-copy:before, +.icon-files-o:before { + content: "\f0c5"; } + +.icon-paperclip:before { + content: "\f0c6"; } + +.icon-save:before, +.icon-floppy-o:before { + content: "\f0c7"; } + +.icon-square:before { + content: "\f0c8"; } + +.icon-navicon:before, +.icon-reorder:before, +.icon-bars:before { + content: "\f0c9"; } + +.icon-list-ul:before { + content: "\f0ca"; } + +.icon-list-ol:before { + content: "\f0cb"; } + +.icon-strikethrough:before { + content: "\f0cc"; } + +.icon-underline:before { + content: "\f0cd"; } + +.icon-table:before { + content: "\f0ce"; } + +.icon-magic:before { + content: "\f0d0"; } + +.icon-truck:before { + content: "\f0d1"; } + +.icon-pinterest:before { + content: "\f0d2"; } + +.icon-pinterest-square:before { + content: "\f0d3"; } + +.icon-google-plus-square:before { + content: "\f0d4"; } + +.icon-google-plus:before { + content: "\f0d5"; } + +.icon-money:before { + content: "\f0d6"; } + +.icon-caret-down:before { + content: "\f0d7"; } + +.icon-caret-up:before { + content: "\f0d8"; } + +.icon-caret-left:before { + content: "\f0d9"; } + +.icon-caret-right:before { + content: "\f0da"; } + +.icon-columns:before { + content: "\f0db"; } + +.icon-unsorted:before, +.icon-sort:before { + content: "\f0dc"; } + +.icon-sort-down:before, +.icon-sort-desc:before { + content: "\f0dd"; } + +.icon-sort-up:before, +.icon-sort-asc:before { + content: "\f0de"; } + +.icon-envelope:before { + content: "\f0e0"; } + +.icon-linkedin:before { + content: "\f0e1"; } + +.icon-rotate-left:before, +.icon-undo:before { + content: "\f0e2"; } + +.icon-legal:before, +.icon-gavel:before { + content: "\f0e3"; } + +.icon-dashboard:before, +.icon-tachometer:before { + content: "\f0e4"; } + +.icon-comment-o:before { + content: "\f0e5"; } + +.icon-comments-o:before { + content: "\f0e6"; } + +.icon-flash:before, +.icon-bolt:before { + content: "\f0e7"; } + +.icon-sitemap:before { + content: "\f0e8"; } + +.icon-umbrella:before { + content: "\f0e9"; } + +.icon-paste:before, +.icon-clipboard:before { + content: "\f0ea"; } + +.icon-lightbulb-o:before { + content: "\f0eb"; } + +.icon-exchange:before { + content: "\f0ec"; } + +.icon-cloud-download:before { + content: "\f0ed"; } + +.icon-cloud-upload:before { + content: "\f0ee"; } + +.icon-user-md:before { + content: "\f0f0"; } + +.icon-stethoscope:before { + content: "\f0f1"; } + +.icon-suitcase:before { + content: "\f0f2"; } + +.icon-bell-o:before { + content: "\f0a2"; } + +.icon-coffee:before { + content: "\f0f4"; } + +.icon-cutlery:before { + content: "\f0f5"; } + +.icon-file-text-o:before { + content: "\f0f6"; } + +.icon-building-o:before { + content: "\f0f7"; } + +.icon-hospital-o:before { + content: "\f0f8"; } + +.icon-ambulance:before { + content: "\f0f9"; } + +.icon-medkit:before { + content: "\f0fa"; } + +.icon-fighter-jet:before { + content: "\f0fb"; } + +.icon-beer:before { + content: "\f0fc"; } + +.icon-h-square:before { + content: "\f0fd"; } + +.icon-plus-square:before { + content: "\f0fe"; } + +.icon-angle-double-left:before { + content: "\f100"; } + +.icon-angle-double-right:before { + content: "\f101"; } + +.icon-angle-double-up:before { + content: "\f102"; } + +.icon-angle-double-down:before { + content: "\f103"; } + +.icon-angle-left:before { + content: "\f104"; } + +.icon-angle-right:before { + content: "\f105"; } + +.icon-angle-up:before { + content: "\f106"; } + +.icon-angle-down:before { + content: "\f107"; } + +.icon-desktop:before { + content: "\f108"; } + +.icon-laptop:before { + content: "\f109"; } + +.icon-tablet:before { + content: "\f10a"; } + +.icon-mobile-phone:before, +.icon-mobile:before { + content: "\f10b"; } + +.icon-circle-o:before { + content: "\f10c"; } + +.icon-quote-left:before { + content: "\f10d"; } + +.icon-quote-right:before { + content: "\f10e"; } + +.icon-spinner:before { + content: "\f110"; } + +.icon-circle:before { + content: "\f111"; } + +.icon-mail-reply:before, +.icon-reply:before { + content: "\f112"; } + +.icon-github-alt:before { + content: "\f113"; } + +.icon-folder-o:before { + content: "\f114"; } + +.icon-folder-open-o:before { + content: "\f115"; } + +.icon-smile-o:before { + content: "\f118"; } + +.icon-frown-o:before { + content: "\f119"; } + +.icon-meh-o:before { + content: "\f11a"; } + +.icon-gamepad:before { + content: "\f11b"; } + +.icon-keyboard-o:before { + content: "\f11c"; } + +.icon-flag-o:before { + content: "\f11d"; } + +.icon-flag-checkered:before { + content: "\f11e"; } + +.icon-terminal:before { + content: "\f120"; } + +.icon-code:before { + content: "\f121"; } + +.icon-mail-reply-all:before, +.icon-reply-all:before { + content: "\f122"; } + +.icon-star-half-empty:before, +.icon-star-half-full:before, +.icon-star-half-o:before { + content: "\f123"; } + +.icon-location-arrow:before { + content: "\f124"; } + +.icon-crop:before { + content: "\f125"; } + +.icon-code-fork:before { + content: "\f126"; } + +.icon-unlink:before, +.icon-chain-broken:before { + content: "\f127"; } + +.icon-question:before { + content: "\f128"; } + +.icon-info:before { + content: "\f129"; } + +.icon-exclamation:before { + content: "\f12a"; } + +.icon-superscript:before { + content: "\f12b"; } + +.icon-subscript:before { + content: "\f12c"; } + +.icon-eraser:before { + content: "\f12d"; } + +.icon-puzzle-piece:before { + content: "\f12e"; } + +.icon-microphone:before { + content: "\f130"; } + +.icon-microphone-slash:before { + content: "\f131"; } + +.icon-shield:before { + content: "\f132"; } + +.icon-calendar-o:before { + content: "\f133"; } + +.icon-fire-extinguisher:before { + content: "\f134"; } + +.icon-rocket:before { + content: "\f135"; } + +.icon-maxcdn:before { + content: "\f136"; } + +.icon-chevron-circle-left:before { + content: "\f137"; } + +.icon-chevron-circle-right:before { + content: "\f138"; } + +.icon-chevron-circle-up:before { + content: "\f139"; } + +.icon-chevron-circle-down:before { + content: "\f13a"; } + +.icon-html5:before { + content: "\f13b"; } + +.icon-css3:before { + content: "\f13c"; } + +.icon-anchor:before { + content: "\f13d"; } + +.icon-unlock-alt:before { + content: "\f13e"; } + +.icon-bullseye:before { + content: "\f140"; } + +.icon-ellipsis-h:before { + content: "\f141"; } + +.icon-ellipsis-v:before { + content: "\f142"; } + +.icon-rss-square:before { + content: "\f143"; } + +.icon-play-circle:before { + content: "\f144"; } + +.icon-ticket:before { + content: "\f145"; } + +.icon-minus-square:before { + content: "\f146"; } + +.icon-minus-square-o:before { + content: "\f147"; } + +.icon-level-up:before { + content: "\f148"; } + +.icon-level-down:before { + content: "\f149"; } + +.icon-check-square:before { + content: "\f14a"; } + +.icon-pencil-square:before { + content: "\f14b"; } + +.icon-external-link-square:before { + content: "\f14c"; } + +.icon-share-square:before { + content: "\f14d"; } + +.icon-compass:before { + content: "\f14e"; } + +.icon-toggle-down:before, +.icon-caret-square-o-down:before { + content: "\f150"; } + +.icon-toggle-up:before, +.icon-caret-square-o-up:before { + content: "\f151"; } + +.icon-toggle-right:before, +.icon-caret-square-o-right:before { + content: "\f152"; } + +.icon-euro:before, +.icon-eur:before { + content: "\f153"; } + +.icon-gbp:before { + content: "\f154"; } + +.icon-dollar:before, +.icon-usd:before { + content: "\f155"; } + +.icon-rupee:before, +.icon-inr:before { + content: "\f156"; } + +.icon-cny:before, +.icon-rmb:before, +.icon-yen:before, +.icon-jpy:before { + content: "\f157"; } + +.icon-ruble:before, +.icon-rouble:before, +.icon-rub:before { + content: "\f158"; } + +.icon-won:before, +.icon-krw:before { + content: "\f159"; } + +.icon-bitcoin:before, +.icon-btc:before { + content: "\f15a"; } + +.icon-file:before { + content: "\f15b"; } + +.icon-file-text:before { + content: "\f15c"; } + +.icon-sort-alpha-asc:before { + content: "\f15d"; } + +.icon-sort-alpha-desc:before { + content: "\f15e"; } + +.icon-sort-amount-asc:before { + content: "\f160"; } + +.icon-sort-amount-desc:before { + content: "\f161"; } + +.icon-sort-numeric-asc:before { + content: "\f162"; } + +.icon-sort-numeric-desc:before { + content: "\f163"; } + +.icon-thumbs-up:before { + content: "\f164"; } + +.icon-thumbs-down:before { + content: "\f165"; } + +.icon-youtube-square:before { + content: "\f166"; } + +.icon-youtube:before { + content: "\f167"; } + +.icon-xing:before { + content: "\f168"; } + +.icon-xing-square:before { + content: "\f169"; } + +.icon-youtube-play:before { + content: "\f16a"; } + +.icon-dropbox:before { + content: "\f16b"; } + +.icon-stack-overflow:before { + content: "\f16c"; } + +.icon-instagram:before { + content: "\f16d"; } + +.icon-flickr:before { + content: "\f16e"; } + +.icon-adn:before { + content: "\f170"; } + +.icon-bitbucket:before { + content: "\f171"; } + +.icon-bitbucket-square:before { + content: "\f172"; } + +.icon-tumblr:before { + content: "\f173"; } + +.icon-tumblr-square:before { + content: "\f174"; } + +.icon-long-arrow-down:before { + content: "\f175"; } + +.icon-long-arrow-up:before { + content: "\f176"; } + +.icon-long-arrow-left:before { + content: "\f177"; } + +.icon-long-arrow-right:before { + content: "\f178"; } + +.icon-apple:before { + content: "\f179"; } + +.icon-windows:before { + content: "\f17a"; } + +.icon-android:before { + content: "\f17b"; } + +.icon-linux:before { + content: "\f17c"; } + +.icon-dribbble:before { + content: "\f17d"; } + +.icon-skype:before { + content: "\f17e"; } + +.icon-foursquare:before { + content: "\f180"; } + +.icon-trello:before { + content: "\f181"; } + +.icon-female:before { + content: "\f182"; } + +.icon-male:before { + content: "\f183"; } + +.icon-gittip:before, +.icon-gratipay:before { + content: "\f184"; } + +.icon-sun-o:before { + content: "\f185"; } + +.icon-moon-o:before { + content: "\f186"; } + +.icon-archive:before { + content: "\f187"; } + +.icon-bug:before { + content: "\f188"; } + +.icon-vk:before { + content: "\f189"; } + +.icon-weibo:before { + content: "\f18a"; } + +.icon-renren:before { + content: "\f18b"; } + +.icon-pagelines:before { + content: "\f18c"; } + +.icon-stack-exchange:before { + content: "\f18d"; } + +.icon-arrow-circle-o-right:before { + content: "\f18e"; } + +.icon-arrow-circle-o-left:before { + content: "\f190"; } + +.icon-toggle-left:before, +.icon-caret-square-o-left:before { + content: "\f191"; } + +.icon-dot-circle-o:before { + content: "\f192"; } + +.icon-wheelchair:before { + content: "\f193"; } + +.icon-vimeo-square:before { + content: "\f194"; } + +.icon-turkish-lira:before, +.icon-try:before { + content: "\f195"; } + +.icon-plus-square-o:before { + content: "\f196"; } + +.icon-space-shuttle:before { + content: "\f197"; } + +.icon-slack:before { + content: "\f198"; } + +.icon-envelope-square:before { + content: "\f199"; } + +.icon-wordpress:before { + content: "\f19a"; } + +.icon-openid:before { + content: "\f19b"; } + +.icon-institution:before, +.icon-bank:before, +.icon-university:before { + content: "\f19c"; } + +.icon-mortar-board:before, +.icon-graduation-cap:before { + content: "\f19d"; } + +.icon-yahoo:before { + content: "\f19e"; } + +.icon-google:before { + content: "\f1a0"; } + +.icon-reddit:before { + content: "\f1a1"; } + +.icon-reddit-square:before { + content: "\f1a2"; } + +.icon-stumbleupon-circle:before { + content: "\f1a3"; } + +.icon-stumbleupon:before { + content: "\f1a4"; } + +.icon-delicious:before { + content: "\f1a5"; } + +.icon-digg:before { + content: "\f1a6"; } + +.icon-pied-piper:before { + content: "\f1a7"; } + +.icon-pied-piper-alt:before { + content: "\f1a8"; } + +.icon-drupal:before { + content: "\f1a9"; } + +.icon-joomla:before { + content: "\f1aa"; } + +.icon-language:before { + content: "\f1ab"; } + +.icon-fax:before { + content: "\f1ac"; } + +.icon-building:before { + content: "\f1ad"; } + +.icon-child:before { + content: "\f1ae"; } + +.icon-paw:before { + content: "\f1b0"; } + +.icon-spoon:before { + content: "\f1b1"; } + +.icon-cube:before { + content: "\f1b2"; } + +.icon-cubes:before { + content: "\f1b3"; } + +.icon-behance:before { + content: "\f1b4"; } + +.icon-behance-square:before { + content: "\f1b5"; } + +.icon-steam:before { + content: "\f1b6"; } + +.icon-steam-square:before { + content: "\f1b7"; } + +.icon-recycle:before { + content: "\f1b8"; } + +.icon-automobile:before, +.icon-car:before { + content: "\f1b9"; } + +.icon-cab:before, +.icon-taxi:before { + content: "\f1ba"; } + +.icon-tree:before { + content: "\f1bb"; } + +.icon-spotify:before { + content: "\f1bc"; } + +.icon-deviantart:before { + content: "\f1bd"; } + +.icon-soundcloud:before { + content: "\f1be"; } + +.icon-database:before { + content: "\f1c0"; } + +.icon-file-pdf-o:before { + content: "\f1c1"; } + +.icon-file-word-o:before { + content: "\f1c2"; } + +.icon-file-excel-o:before { + content: "\f1c3"; } + +.icon-file-powerpoint-o:before { + content: "\f1c4"; } + +.icon-file-photo-o:before, +.icon-file-picture-o:before, +.icon-file-image-o:before { + content: "\f1c5"; } + +.icon-file-zip-o:before, +.icon-file-archive-o:before { + content: "\f1c6"; } + +.icon-file-sound-o:before, +.icon-file-audio-o:before { + content: "\f1c7"; } + +.icon-file-movie-o:before, +.icon-file-video-o:before { + content: "\f1c8"; } + +.icon-file-code-o:before { + content: "\f1c9"; } + +.icon-vine:before { + content: "\f1ca"; } + +.icon-codepen:before { + content: "\f1cb"; } + +.icon-jsfiddle:before { + content: "\f1cc"; } + +.icon-life-bouy:before, +.icon-life-buoy:before, +.icon-life-saver:before, +.icon-support:before, +.icon-life-ring:before { + content: "\f1cd"; } + +.icon-circle-o-notch:before { + content: "\f1ce"; } + +.icon-ra:before, +.icon-rebel:before { + content: "\f1d0"; } + +.icon-ge:before, +.icon-empire:before { + content: "\f1d1"; } + +.icon-git-square:before { + content: "\f1d2"; } + +.icon-git:before { + content: "\f1d3"; } + +.icon-hacker-news:before { + content: "\f1d4"; } + +.icon-tencent-weibo:before { + content: "\f1d5"; } + +.icon-qq:before { + content: "\f1d6"; } + +.icon-wechat:before, +.icon-weixin:before { + content: "\f1d7"; } + +.icon-send:before, +.icon-paper-plane:before { + content: "\f1d8"; } + +.icon-send-o:before, +.icon-paper-plane-o:before { + content: "\f1d9"; } + +.icon-history:before { + content: "\f1da"; } + +.icon-genderless:before, +.icon-circle-thin:before { + content: "\f1db"; } + +.icon-header:before { + content: "\f1dc"; } + +.icon-paragraph:before { + content: "\f1dd"; } + +.icon-sliders:before { + content: "\f1de"; } + +.icon-share-alt:before { + content: "\f1e0"; } + +.icon-share-alt-square:before { + content: "\f1e1"; } + +.icon-bomb:before { + content: "\f1e2"; } + +.icon-soccer-ball-o:before, +.icon-futbol-o:before { + content: "\f1e3"; } + +.icon-tty:before { + content: "\f1e4"; } + +.icon-binoculars:before { + content: "\f1e5"; } + +.icon-plug:before { + content: "\f1e6"; } + +.icon-slideshare:before { + content: "\f1e7"; } + +.icon-twitch:before { + content: "\f1e8"; } + +.icon-yelp:before { + content: "\f1e9"; } + +.icon-newspaper-o:before { + content: "\f1ea"; } + +.icon-wifi:before { + content: "\f1eb"; } + +.icon-calculator:before { + content: "\f1ec"; } + +.icon-paypal:before { + content: "\f1ed"; } + +.icon-google-wallet:before { + content: "\f1ee"; } + +.icon-cc-visa:before { + content: "\f1f0"; } + +.icon-cc-mastercard:before { + content: "\f1f1"; } + +.icon-cc-discover:before { + content: "\f1f2"; } + +.icon-cc-amex:before { + content: "\f1f3"; } + +.icon-cc-paypal:before { + content: "\f1f4"; } + +.icon-cc-stripe:before { + content: "\f1f5"; } + +.icon-bell-slash:before { + content: "\f1f6"; } + +.icon-bell-slash-o:before { + content: "\f1f7"; } + +.icon-trash:before { + content: "\f1f8"; } + +.icon-copyright:before { + content: "\f1f9"; } + +.icon-at:before { + content: "\f1fa"; } + +.icon-eyedropper:before { + content: "\f1fb"; } + +.icon-paint-brush:before { + content: "\f1fc"; } + +.icon-birthday-cake:before { + content: "\f1fd"; } + +.icon-area-chart:before { + content: "\f1fe"; } + +.icon-pie-chart:before { + content: "\f200"; } + +.icon-line-chart:before { + content: "\f201"; } + +.icon-lastfm:before { + content: "\f202"; } + +.icon-lastfm-square:before { + content: "\f203"; } + +.icon-toggle-off:before { + content: "\f204"; } + +.icon-toggle-on:before { + content: "\f205"; } + +.icon-bicycle:before { + content: "\f206"; } + +.icon-bus:before { + content: "\f207"; } + +.icon-ioxhost:before { + content: "\f208"; } + +.icon-angellist:before { + content: "\f209"; } + +.icon-cc:before { + content: "\f20a"; } + +.icon-shekel:before, +.icon-sheqel:before, +.icon-ils:before { + content: "\f20b"; } + +.icon-meanpath:before { + content: "\f20c"; } + +.icon-buysellads:before { + content: "\f20d"; } + +.icon-connectdevelop:before { + content: "\f20e"; } + +.icon-dashcube:before { + content: "\f210"; } + +.icon-forumbee:before { + content: "\f211"; } + +.icon-leanpub:before { + content: "\f212"; } + +.icon-sellsy:before { + content: "\f213"; } + +.icon-shirtsinbulk:before { + content: "\f214"; } + +.icon-simplybuilt:before { + content: "\f215"; } + +.icon-skyatlas:before { + content: "\f216"; } + +.icon-cart-plus:before { + content: "\f217"; } + +.icon-cart-arrow-down:before { + content: "\f218"; } + +.icon-diamond:before { + content: "\f219"; } + +.icon-ship:before { + content: "\f21a"; } + +.icon-user-secret:before { + content: "\f21b"; } + +.icon-motorcycle:before { + content: "\f21c"; } + +.icon-street-view:before { + content: "\f21d"; } + +.icon-heartbeat:before { + content: "\f21e"; } + +.icon-venus:before { + content: "\f221"; } + +.icon-mars:before { + content: "\f222"; } + +.icon-mercury:before { + content: "\f223"; } + +.icon-transgender:before { + content: "\f224"; } + +.icon-transgender-alt:before { + content: "\f225"; } + +.icon-venus-double:before { + content: "\f226"; } + +.icon-mars-double:before { + content: "\f227"; } + +.icon-venus-mars:before { + content: "\f228"; } + +.icon-mars-stroke:before { + content: "\f229"; } + +.icon-mars-stroke-v:before { + content: "\f22a"; } + +.icon-mars-stroke-h:before { + content: "\f22b"; } + +.icon-neuter:before { + content: "\f22c"; } + +.icon-facebook-official:before { + content: "\f230"; } + +.icon-pinterest-p:before { + content: "\f231"; } + +.icon-whatsapp:before { + content: "\f232"; } + +.icon-server:before { + content: "\f233"; } + +.icon-user-plus:before { + content: "\f234"; } + +.icon-user-times:before { + content: "\f235"; } + +.icon-hotel:before, +.icon-bed:before { + content: "\f236"; } + +.icon-viacoin:before { + content: "\f237"; } + +.icon-train:before { + content: "\f238"; } + +.icon-subway:before { + content: "\f239"; } + +.icon-medium:before { + content: "\f23a"; } + +html { + height: 100%; + font-size: 16px; } + +body { + font-family: 'Source Sans Pro', sans-serif; + line-height: 1.3333; } + +#window { + min-height: 100vh; + background: #f5f5f5; } + +.badge { + background: #216C2A; + display: inline-block; + padding: 2px; + color: white; + border-radius: 2px; } + +.credit-amount--indicator { + font-weight: bold; + color: #216C2A; } + +#main-content { + padding: 24px; + margin-top: 60px; + display: flex; + flex-direction: column; } + #main-content main { + margin-left: auto; + margin-right: auto; + max-width: 100%; } + #main-content main.main--single-column { + width: 800px; } + +main.main--refreshing:before { + position: absolute; + background: url("../img/busy.gif") no-repeat center center; + width: 30px; + height: 24px; + content: ""; + left: 50%; + margin-left: -15px; + display: inline-block; } + +.icon-fixed-width { + /* This borrowed is from a component of Font Awesome we're not using, maybe add it? */ + width: 1.28571em; + text-align: center; } + +h2 { + font-size: 1.75em; } + +h3 { + font-size: 1.4em; } + +h4 { + font-size: 1.2em; } + +h5 { + font-size: 1.1em; } + +sup, sub { + vertical-align: baseline; + position: relative; } + +sup { + top: -0.4em; } + +sub { + top: 0.4em; } + +code { + font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace; + background-color: #eee; } + +p { + margin-bottom: 0.8em; } + p:last-child { + margin-bottom: 0; } + +.hidden { + display: none; } + +.disabled { + pointer-events: none; + opacity: 0.7; } + +.truncated-text { + display: -webkit-box; + overflow: hidden; + -webkit-box-orient: vertical; } + +.busy-indicator { + background: url("../img/busy.gif") no-repeat center center; + display: inline-block; + margin: -1em 0; + min-width: 16px; + min-height: 8px; + vertical-align: middle; + padding: 0 30px; } + .busy-indicator:last-child { + padding-right: 2px; } + .busy-indicator:first-child { + padding-left: 2px; } + +/*should this be here or work this way? had to hack additional rule below*/ +.icon:only-child { + position: relative; + top: 0.16em; } + +.icon-featured > .icon { + top: 0; } + +.help { + font-size: .85em; + color: rgba(0, 0, 0, 0.6); } + +.meta { + font-size: 0.9em; + color: #505050; } + +.empty { + color: #505050; + font-style: italic; } + +/*should be redone/moved*/ +.file-list__header .busy-indicator { + float: left; + margin-top: 12px; } + +.sort-section { + display: block; + margin-bottom: 16px; + text-align: right; + line-height: 1; + font-size: 0.85em; + color: rgba(0, 0, 0, 0.6); } + +section.section-spaced { + margin-bottom: 24px; } + +.text-center { + text-align: center; } + +table.table-standard { + word-wrap: break-word; + max-width: 100%; } + table.table-standard th, table.table-standard td { + padding: 12px 8px; } + table.table-standard th { + font-weight: bold; + font-size: 0.9em; } + table.table-standard td { + vertical-align: top; } + table.table-standard thead th, table.table-standard > tr:first-child th { + vertical-align: bottom; + font-weight: bold; + font-size: 0.9em; + padding: 7px 8px 4px; + text-align: left; + border-bottom: 1px solid #e2e2e2; } + table.table-standard thead th img, table.table-standard > tr:first-child th img { + vertical-align: text-bottom; } + table.table-standard tr.thead:not(:first-child) th { + border-top: 1px solid #e2e2e2; } + table.table-standard tfoot td { + padding: 12px 8px; + font-size: .85em; } + table.table-standard tbody tr:nth-child(even):not(.odd) { + background-color: #f4f4f4; } + table.table-standard tbody tr:nth-child(odd):not(.even) { + background-color: white; } + table.table-standard tbody tr.thead { + background: none; } + table.table-standard tbody tr td { + border: 0 none; } + +table.table-stretch { + width: 100%; } + +.button-set-item { + position: relative; + display: inline-block; } + .button-set-item + .button-set-item { + margin-left: 12px; } + +.button-block, .faux-button-block { + display: inline-block; + height: 36px; + line-height: 36px; + text-decoration: none; + border: 0 none; + text-align: center; + border-radius: 2px; + text-transform: uppercase; } + .button-block .icon, .faux-button-block .icon { + top: 0em; } + .button-block .icon:first-child, .faux-button-block .icon:first-child { + padding-right: 5px; } + .button-block .icon:last-child, .faux-button-block .icon:last-child { + padding-left: 5px; } + .button-block .icon:only-child, .faux-button-block .icon:only-child { + padding-left: 0; + padding-right: 0; } + +.button-block { + cursor: pointer; } + +.button__content { + margin: 0 12px; } + +.button-primary { + color: #f0f0f0; + background-color: #155B4A; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + .button-primary:focus { + color: white; + background-color: #125041; } + +.button-alt { + background-color: #D9D9D9; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + +.button-text { + color: #155B4A; + cursor: pointer; + display: inline-block; } + .button-text .icon:first-child { + padding-right: 5px; } + .button-text .icon:last-child:not(:only-child) { + padding-left: 5px; } + .button-text:not(.no-underline) { + text-decoration: underline; } + .button-text:not(.no-underline) .icon { + text-decoration: none; } + .button-text:hover { + opacity: 0.7; + transition: opacity 0.225s ease; + text-decoration: underline; } + .button-text:hover .icon { + text-decoration: none; } + .button-text .button__content { + margin: 0 4px; } + +.button-text-help { + color: #aaa; + cursor: pointer; + font-size: 0.8em; } + .button-text-help .icon:first-child { + padding-right: 5px; } + .button-text-help .icon:last-child:not(:only-child) { + padding-left: 5px; } + .button-text-help:not(.no-underline) { + text-decoration: underline; } + .button-text-help:not(.no-underline) .icon { + text-decoration: none; } + .button-text-help:hover { + opacity: 0.7; + transition: opacity 0.225s ease; + text-decoration: underline; } + .button-text-help:hover .icon { + text-decoration: none; } + +.button--flat { + box-shadow: none !important; } + +.card { + margin-left: auto; + margin-right: auto; + max-width: 800px; + background: #ffffff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + border-radius: 2px; + margin-bottom: 16px; + overflow: auto; } + +.card--obscured { + position: relative; } + +.card--obscured .card__inner { + filter: blur(20px); } + +.card__title-primary, +.card__title-identity, +.card__actions, +.card__content, +.card__subtext { + padding: 0 16px; } + +.card--small .card__title-primary, +.card--small .card__title-identity, +.card--small .card__actions, +.card--small .card__content, +.card--small .card__subtext { + padding: 0 8px; } + +.card__title-primary { + margin-top: 16px; } + +.card__title-identity { + margin-top: 8px; + margin-bottom: 8px; } + +.card__actions { + margin-top: 16px; } + +.card__actions--bottom { + margin-top: 8px; + margin-bottom: 8px; } + +.card__actions--form-submit { + margin-top: 24px; + margin-bottom: 16px; } + +.card__content { + margin-top: 16px; + margin-bottom: 16px; } + +.card__subtext { + color: #505050; + font-size: 0.82em; + margin-top: 8px; + margin-bottom: 8px; } + +.card__subtext--allow-newlines { + white-space: pre-wrap; } + +.card__subtext--two-lines { + height: 34.98579px; + /*this is so one line text still has the proper height*/ } + +.card-overlay { + position: absolute; + left: 0px; + right: 0px; + top: 0px; + bottom: 0px; + padding: 20px; + background-color: rgba(128, 128, 128, 0.8); + color: #fff; + display: flex; + align-items: center; + font-weight: 600; } + +.card__link { + display: block; } + +.card--link { + transition: transform 120ms ease-in-out; } + +.card--link:hover { + position: relative; + z-index: 1; + box-shadow: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2), 2px 3px 7px 0 rgba(0, 0, 0, 0.12); + transform: scale(1.1) translate3d(10px, 0, 0); + transform-origin: 50% 50%; + overflow-x: visible; + overflow-y: visible; } + +.card--link:hover ~ .card--link { + transform: translate3d(20px, 0, 0); } + +.card__media { + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + +.card__media--autothumb { + position: relative; } + +.card__media--autothumb.purple { + background-color: #9c27b0; } + +.card__media--autothumb.red { + background-color: #e53935; } + +.card__media--autothumb.pink { + background-color: #e91e63; } + +.card__media--autothumb.indigo { + background-color: #3f51b5; } + +.card__media--autothumb.blue { + background-color: #2196f3; } + +.card__media--autothumb.light-blue { + background-color: #039be5; } + +.card__media--autothumb.cyan { + background-color: #00acc1; } + +.card__media--autothumb.teal { + background-color: #009688; } + +.card__media--autothumb.green { + background-color: #43a047; } + +.card__media--autothumb.yellow { + background-color: #ffeb3b; } + +.card__media--autothumb.orange { + background-color: #ffa726; } + +.card__media--autothumb .card__autothumb__text { + font-size: 2.0em; + width: 100%; + color: #ffffff; + text-align: center; + position: absolute; + top: 36%; } + +.card--small { + width: 240px; + overflow-x: hidden; + white-space: normal; } + +.card--small .card__media { + height: 135px; } + +.card--form { + width: 362px; } + +.card__subtitle { + color: rgba(0, 0, 0, 0.6); + font-size: 0.85em; + line-height: 1.56859; } + +.card-series-submit { + margin-left: auto; + margin-right: auto; + max-width: 800px; + padding: 12px; } + +.card-row + .card-row { + margin-top: 8px; } + +.card-row__items { + width: 100%; + overflow: hidden; + /*hacky way to give space for hover */ + padding-top: 20px; + margin-top: -20px; + padding-right: 30px; + margin-right: -30px; } + .card-row__items > .card { + vertical-align: top; + display: inline-block; } + .card-row__items > .card + .card { + margin-left: 8px; } + +.card-row--small { + overflow: hidden; + white-space: nowrap; + /*hacky way to give space for hover */ + padding-right: 30px; } + +.card-row__header { + margin-bottom: 8px; } + +.card-row__scrollhouse { + position: relative; } + +.card-row__nav { + position: absolute; + padding: 0 16px; + height: 100%; + top: 4px; } + +.card-row__nav .card-row__scroll-button { + background: #ffffff; + color: rgba(0, 0, 0, 0.6); + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + padding: 24px 12px; + position: absolute; + cursor: pointer; + left: 0; + top: 36%; + z-index: 2; + opacity: 0.8; + transition: transform 60ms ease-in-out; } + .card-row__nav .card-row__scroll-button:hover { + opacity: 1.0; + transform: scale(1.21); } + +.card-row__nav--left { + left: 0; } + +.card-row__nav--right { + right: -30px; } + +.card__icon-featured-content { + color: orangered; } + +.file-actions { + line-height: 36px; + min-height: 36px; } + +.file-actions__download-status-bar .button__content, .file-actions__download-status-bar-overlay .button__content { + margin: 0 4px; } + +.file-actions__download-status-bar { + position: relative; + color: #444; } + +.file-actions__download-status-bar-overlay { + background: #444; + color: white; + position: absolute; + white-space: nowrap; + overflow: hidden; + z-index: 1; + top: 0px; + left: 0px; } + +.file-selector__choose-button { + font-size: 13px; } + +.file-selector__path { + font-size: 14px; } + +.file-tile__row { + overflow: hidden; + height: 144px; } + .file-tile__row .credit-amount { + float: right; } + .file-tile__row .icon-featured { + float: right; } + .file-tile__row .card__media { + height: 144px; + max-width: 144px; + width: 144px; + margin-right: 12px; + float: left; } + .file-tile__row .file-tile__content { + padding-top: 8px; + margin-left: 156px; } + .file-tile__row .card__title-primary { + margin-top: 0; } + +.form-row-submit { + margin-top: 24px; } + +.form-row-submit--with-footer { + margin-bottom: 24px; } + +.form-row__label-row { + margin-top: 20px; + margin-bottom: 4px; + line-height: 1; + font-size: 14.4px; } + +.form-row__label-row--prefix { + float: left; + margin-right: 5px; } + +input[type="text"].input-copyable { + border: 1px solid rgba(160, 160, 160, 0.5); + line-height: 1; + padding-top: 8px; + padding-bottom: 8px; + width: 330px; + padding-left: 5px; + padding-right: 5px; + width: 100%; } + input[type="text"].input-copyable:focus { + border-color: black; } + +.form-field { + display: inline-block; } + .form-field input[type="checkbox"], + .form-field input[type="radio"] { + cursor: pointer; } + .form-field select { + transition: outline 0.225s ease; + cursor: pointer; + box-sizing: border-box; + padding-left: 5px; + padding-right: 5px; + height: 24px; } + .form-field select:focus { + outline: 2px solid #155B4A; } + .form-field textarea, + .form-field input[type="text"], + .form-field input[type="password"], + .form-field input[type="email"], + .form-field input[type="number"], + .form-field input[type="search"], + .form-field input[type="date"] { + transition: all 0.225s ease; + cursor: pointer; + padding-left: 1px; + padding-right: 1px; + box-sizing: border-box; + -webkit-appearance: none; } + .form-field textarea::-webkit-input-placeholder, + .form-field input[type="text"]::-webkit-input-placeholder, + .form-field input[type="password"]::-webkit-input-placeholder, + .form-field input[type="email"]::-webkit-input-placeholder, + .form-field input[type="number"]::-webkit-input-placeholder, + .form-field input[type="search"]::-webkit-input-placeholder, + .form-field input[type="date"]::-webkit-input-placeholder { + color: #999999; } + .form-field textarea:-moz-placeholder, + .form-field input[type="text"]:-moz-placeholder, + .form-field input[type="password"]:-moz-placeholder, + .form-field input[type="email"]:-moz-placeholder, + .form-field input[type="number"]:-moz-placeholder, + .form-field input[type="search"]:-moz-placeholder, + .form-field input[type="date"]:-moz-placeholder { + color: #999999; } + .form-field textarea:-ms-input-placeholder, + .form-field input[type="text"]:-ms-input-placeholder, + .form-field input[type="password"]:-ms-input-placeholder, + .form-field input[type="email"]:-ms-input-placeholder, + .form-field input[type="number"]:-ms-input-placeholder, + .form-field input[type="search"]:-ms-input-placeholder, + .form-field input[type="date"]:-ms-input-placeholder { + color: #999999; } + .form-field textarea[readonly], + .form-field input[type="text"][readonly], + .form-field input[type="password"][readonly], + .form-field input[type="email"][readonly], + .form-field input[type="number"][readonly], + .form-field input[type="search"][readonly], + .form-field input[type="date"][readonly] { + background-color: #bbb; } + .form-field input[type="text"], + .form-field input[type="password"], + .form-field input[type="email"], + .form-field input[type="number"], + .form-field input[type="search"], + .form-field input[type="date"] { + border-bottom: 2px solid rgba(160, 160, 160, 0.5); + line-height: 1; + padding-top: 8px; + padding-bottom: 8px; } + .form-field input[type="text"].form-field__input--error, + .form-field input[type="password"].form-field__input--error, + .form-field input[type="email"].form-field__input--error, + .form-field input[type="number"].form-field__input--error, + .form-field input[type="search"].form-field__input--error, + .form-field input[type="date"].form-field__input--error { + border-color: #a94442; } + .form-field input[type="text"].form-field__input--inline, + .form-field input[type="password"].form-field__input--inline, + .form-field input[type="email"].form-field__input--inline, + .form-field input[type="number"].form-field__input--inline, + .form-field input[type="search"].form-field__input--inline, + .form-field input[type="date"].form-field__input--inline { + padding-top: 0; + padding-bottom: 0; + border-bottom-width: 1px; + margin-left: 8px; + margin-right: 8px; } + .form-field textarea:focus, + .form-field input[type="text"]:focus, + .form-field input[type="password"]:focus, + .form-field input[type="email"]:focus, + .form-field input[type="number"]:focus, + .form-field input[type="search"]:focus, + .form-field input[type="date"]:focus { + border-color: #155B4A; } + .form-field textarea { + padding: 2px; + border: 2px solid rgba(160, 160, 160, 0.5); } + +.form-field--SimpleMDE { + display: block; } + +.form-field__label[for] { + cursor: pointer; } + +.form-field__label > input[type="checkbox"], .form-field__label input[type="radio"] { + margin-right: 6px; } + +.form-field__label--error { + color: #a94442; } + +.form-field__input-text { + width: 330px; } + +.form-field__prefix { + margin-right: 4px; } + +.form-field__postfix { + margin-left: 4px; } + +.form-field__input-number { + width: 70px; + text-align: right; } + +.form-field--textarea { + width: 100%; } + +.form-field__input-textarea { + width: 100%; } + +.form-field__error, .form-field__helper { + margin-top: 8px; + font-size: 0.8em; + transition: opacity 0.225s ease; } + +.form-field__error { + color: #a94442; } + +.form-field__helper { + color: rgba(0, 0, 0, 0.6); } + +.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll { + height: auto; } + +#header { + color: #666; + background: #fff; + display: flex; + position: fixed; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + top: 0; + left: 0; + width: 100%; + z-index: 3; + padding: 12px; + box-sizing: border-box; } + +.header__item { + flex: 0 0 content; + padding-left: 6px; + padding-right: 6px; } + +.header__item--wunderbar { + flex-grow: 1; } + +.wunderbar { + position: relative; } + .wunderbar .icon { + position: absolute; + left: 10px; + top: 8px; } + +.wunderbar--active .icon-search { + color: #155B4A; } + +.wunderbar__input { + background: rgba(255, 255, 255, 0.7); + width: 100%; + color: #666; + height: 36px; + line-height: 36px; + padding-left: 38px; + padding-right: 5px; + border: 1px solid #000; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + -ms-border-radius: 2px; + border-radius: 2px; + border: 1px solid #ccc; } + .wunderbar__input:focus { + color: #333333; + box-shadow: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2), 2px 3px 7px 0 rgba(0, 0, 0, 0.12); + border-color: #155B4A; } + +nav.sub-header { + text-transform: uppercase; + padding: 0 0 24px; + max-width: 800px; + margin-left: auto; + margin-right: auto; } + nav.sub-header > a { + display: inline-block; + margin: 0 15px; + padding: 0 5px; + line-height: 34px; + color: #666; } + nav.sub-header > a:first-child { + margin-left: 0; } + nav.sub-header > a:last-child { + margin-right: 0; } + nav.sub-header > a.sub-header-selected { + border-bottom: 2px solid #333333; + color: #333333; } + nav.sub-header > a:hover { + color: #333333; } + +.menu-container { + display: inline-block; } + +.menu { + position: absolute; + white-space: nowrap; + background-color: white; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + border-radius: 2px; + padding-top: 4.8px 0px; + z-index: 1; } + +.menu__menu-item { + display: block; + padding: 6px 12px; } + .menu__menu-item:hover { + background: #D9D9D9; } + +.tooltip { + position: relative; } + +.tooltip__link { + color: #155B4A; + cursor: pointer; } + .tooltip__link .icon:first-child { + padding-right: 5px; } + .tooltip__link .icon:last-child:not(:only-child) { + padding-left: 5px; } + .tooltip__link:not(.no-underline) { + text-decoration: underline; } + .tooltip__link:not(.no-underline) .icon { + text-decoration: none; } + .tooltip__link:hover { + opacity: 0.7; + transition: opacity 0.225s ease; + text-decoration: underline; } + .tooltip__link:hover .icon { + text-decoration: none; } + +.tooltip__body { + position: absolute; + z-index: 1; + left: 50%; + margin-left: -150px; + white-space: normal; + box-sizing: border-box; + padding: 12px; + width: 300px; + border: 1px solid #aaa; + color: #000; + background-color: #ffffff; + font-size: 14px; + line-height: 1.3333; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + +.tooltip--header .tooltip__link { + color: #aaa; + cursor: pointer; + font-size: 12px; + margin-left: 12px; + vertical-align: middle; } + .tooltip--header .tooltip__link .icon:first-child { + padding-right: 5px; } + .tooltip--header .tooltip__link .icon:last-child:not(:only-child) { + padding-left: 5px; } + .tooltip--header .tooltip__link:not(.no-underline) { + text-decoration: underline; } + .tooltip--header .tooltip__link:not(.no-underline) .icon { + text-decoration: none; } + .tooltip--header .tooltip__link:hover { + opacity: 0.7; + transition: opacity 0.225s ease; + text-decoration: underline; } + .tooltip--header .tooltip__link:hover .icon { + text-decoration: none; } + +.load-screen { + color: white; + background: #155B4A; + background-size: cover; + min-height: 100vh; + min-width: 100vw; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; } + +.load-screen__message { + margin-top: 24px; + width: 325px; + text-align: center; } + +.load-screen__details { + color: #c3c3c3; } + +.load-screen__details--warning { + color: white; } + +.load-screen__cancel-link { + color: white; } + +.channel-indicator__icon--invalid { + color: #a94442; } + +.notice { + padding: 10px 20px; + border: 1px solid #000; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-radius: 5px; + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; } + +.notice--error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; } + +.modal-overlay, .error-modal-overlay { + position: fixed; + display: flex; + justify-content: center; + align-items: center; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + background-color: rgba(255, 255, 255, 0.74902); + z-index: 9999; } + +.modal-overlay--clear { + background-color: transparent; } + +.modal { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border: 1px solid #cccccc; + background: white; + overflow: auto; + border-radius: 4px; + padding: 24px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + max-width: 400px; + word-break: break-word; } + +.modal__header { + margin-bottom: 16px; + text-align: center; } + +.modal__buttons { + display: flex; + flex-direction: row; + justify-content: center; + margin-top: 16px; } + +.modal__button { + margin: 0px 6px; } + +.error-modal-overlay { + background: rgba(0, 0, 0, 0.88); } + +.error-modal__content { + display: flex; + padding: 0px 8px 10px 10px; } + +.error-modal__warning-symbol { + margin-top: 6px; + margin-right: 7px; } + +.download-started-modal__file-path { + word-break: break-all; } + +.error-modal { + max-width: none; + width: 400px; } + +.error-modal__error-list { + /*shitty hack/temp fix for long errors making modals unusable*/ + border: 1px solid #eee; + padding: 8px; + list-style: none; + max-height: 400px; + max-width: 400px; + overflow-y: hidden; } + +.snack-bar { + line-height: 36px; + padding: 6px 24px; + position: fixed; + top: 24px; + left: 0; + right: 0; + margin-left: auto; + margin-right: auto; + min-width: 300px; + max-width: 500px; + background: rgba(32, 32, 32, 0.9); + color: #f0f0f0; + display: flex; + justify-content: space-between; + align-items: center; + border-radius: 2px; + transition: all 0.225s ease; + z-index: 10000; + /*hack to get it over react modal */ } + +.snack-bar__action { + display: inline-block; + text-transform: uppercase; + color: #7df2d6; + margin: 0px 0px 0px 24px; + min-width: min-content; } + .snack-bar__action:hover { + text-decoration: underline; } + +video { + object-fit: contain; + box-sizing: border-box; + max-height: 100%; + max-width: 100%; + background-size: contain; + background-position: center center; + background-repeat: no-repeat; } + +.video { + background: #000; + color: white; } + +.video-embedded { + max-width: 800px; + max-height: 450px; + height: 450px; + position: relative; } + .video-embedded video { + height: 100%; + position: absolute; + left: 0; + top: 0; } + .video-embedded.video--hidden { + height: 450px; } + .video-embedded.video--active { + /*background: none;*/ } + +.video--obscured .video__cover { + position: relative; + filter: blur(20px); } + +.video__loading-screen { + height: 100%; + display: flex; + justify-content: center; + align-items: center; } + +.video__loading-spinner { + position: relative; + width: 11em; + height: 11em; + margin: 20px auto; + font-size: 3px; + border-radius: 50%; + background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 50%); + animation: spin 1.4s infinite linear; + transform: translateZ(0); } + +@keyframes spin { + from { + transform: rotate(0deg); } + to { + transform: rotate(360deg); } } + .video__loading-spinner:before, .video__loading-spinner:after { + content: ''; + position: absolute; + top: 0; + left: 0; } + .video__loading-spinner:before { + width: 50%; + height: 50%; + background: #ffffff; + border-radius: 100% 0 0 0; } + .video__loading-spinner:after { + height: 75%; + width: 75%; + margin: auto; + bottom: 0; + right: 0; + background: black; + border-radius: 50%; } + +.video__loading-status { + padding-top: 20px; + color: white; } + +.video__cover { + text-align: center; + height: 100%; + width: 100%; + background-size: auto 100%; + background-position: center center; + background-repeat: no-repeat; + position: relative; } + .video__cover .video__play-button { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-box-align: center; + -moz-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -webkit-box-pack: center; + -moz-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; } + +.video__play-button { + position: absolute; + width: 100%; + height: 100%; + cursor: pointer; + display: none; + font-size: 72px; + color: white; + z-index: 1; + background: rgba(32, 32, 32, 0.9); + opacity: 0.6; + left: 0; + top: 0; } + .video__play-button:hover { + opacity: 1; + transition: opacity 0.225s ease; } + +.pagination { + display: block; + padding: 0; + margin: 0 auto; + text-align: center; } + +.pagination__item { + display: inline-block; + line-height: 36px; + height: 36px; + border-radius: 2px; } + .pagination__item:not(.pagination__item--selected):hover { + background: rgba(0, 0, 0, 0.2); } + .pagination__item:not(.pagination__item--selected):hover > a { + cursor: hand; } + .pagination__item > a { + display: inline-block; + padding: 0 16px; } + +.pagination__item--previous, .pagination__item--next { + font-size: 1.2em; } + +.pagination__item--selected { + color: white; + background: #155B4A; } + +.developer-page__custom-lighthouse-servers { + font: 0.8em monospace; + width: 30em; + height: 10em; } + +.reward-page__details { + background-color: #f9f9f9; } + +.show-page-media { + text-align: center; + margin-bottom: 24px; } + .show-page-media img { + max-width: 100%; } + .show-page-media iframe { + width: 100%; + min-height: 500px; } From b7781f0e40ea1f5cb6213ccb3bc52356ef521f2e Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 6 Aug 2017 12:17:16 -0600 Subject: [PATCH 006/132] fix var names --- ui/js/page/settings/view.jsx | 5 +++-- ui/js/util/getThemes.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 8fa7c93a8..aa9d59f9f 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -85,6 +85,7 @@ class SettingsPage extends React.PureComponent { } onThemeChange(event) { + // Todo: Add better way to handle this const value = event.target.value; const link = document.getElementById("theme"); link.href = `./themes/${value}.css`; @@ -272,8 +273,8 @@ class SettingsPage extends React.PureComponent { defaultValue={lbry.getClientSetting("theme")} className="form-field__input--inline" > - {themes.map((i, k) => - + {themes.map((name, index) => + )} diff --git a/ui/js/util/getThemes.js b/ui/js/util/getThemes.js index d82bc4d0c..09926502c 100644 --- a/ui/js/util/getThemes.js +++ b/ui/js/util/getThemes.js @@ -1,3 +1,4 @@ +// Todo: Add a better way to do this const { readdirSync } = require("fs"); const { extname } = require("path"); const { remote } = require("electron"); From 694f02dc59e3c23d271d9ba9ecf57bdd39d87776 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 6 Aug 2017 18:55:31 -0600 Subject: [PATCH 007/132] implement getThemes action --- ui/js/actions/settings.js | 23 +++++++++++++++++++++++ ui/js/constants/action_types.js | 6 ++++-- ui/js/page/settings/index.js | 7 ++++++- ui/js/page/settings/view.jsx | 11 ++++++----- ui/js/util/getThemes.js | 21 --------------------- 5 files changed, 39 insertions(+), 29 deletions(-) delete mode 100644 ui/js/util/getThemes.js diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index f4fd86142..9b450bb08 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -1,5 +1,8 @@ import * as types from "constants/action_types"; import lbry from "lbry"; +import { readdirSync } from "fs"; +import { extname } from "path"; +import { remote } from "electron"; export function doFetchDaemonSettings() { return function(dispatch, getState) { @@ -41,3 +44,23 @@ export function doSetClientSetting(key, value) { }, }; } + +export function getThemes() { + // Themes path + const themesPath = `${remote.app.getAppPath()}/dist/themes`; + + // Get all .css files + const files = readdirSync(themesPath).filter(function(file) { + return extname(file) === ".css"; + }); + + // Get theme name + const themes = files.map(function(file) { + return file.replace(".css", ""); + }); + + return { + type: types.GET_THEMES, + data: { themes }, + }; +} diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 71d6d8072..25fe50c47 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -85,6 +85,9 @@ export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED"; +// Themes +export const GET_THEMES = "GET_THEMES"; + // User export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED"; export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS"; @@ -112,5 +115,4 @@ export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED"; export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS"; export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; -export const FETCH_REWARD_CONTENT_COMPLETED = - "FETCH_REWARD_CONTENT_COMPLETED"; +export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; diff --git a/ui/js/page/settings/index.js b/ui/js/page/settings/index.js index c74b918af..a202da461 100644 --- a/ui/js/page/settings/index.js +++ b/ui/js/page/settings/index.js @@ -1,7 +1,11 @@ import React from "react"; import { connect } from "react-redux"; import { doClearCache } from "actions/app"; -import { doSetDaemonSetting, doSetClientSetting } from "actions/settings"; +import { + doSetDaemonSetting, + doSetClientSetting, + getThemes, +} from "actions/settings"; import { selectDaemonSettings, selectShowNsfw } from "selectors/settings"; import SettingsPage from "./view"; @@ -13,6 +17,7 @@ const select = state => ({ const perform = dispatch => ({ setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)), clearCache: () => dispatch(doClearCache()), + getThemes: () => dispatch(getThemes()), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), }); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index aa9d59f9f..b6b7ecedd 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -3,10 +3,7 @@ import { FormField, FormRow } from "component/form.js"; import SubHeader from "component/subHeader"; import lbry from "lbry.js"; import Link from "component/link"; -import getThemes from "util/getThemes"; - -const { remote } = require("electron"); -const themes = getThemes(); +import { remote } from "electron"; class SettingsPage extends React.PureComponent { constructor(props) { @@ -37,6 +34,10 @@ class SettingsPage extends React.PureComponent { setTimeout(clear, 1000, { once: true }); } + getThemes() { + return this.props.getThemes().data.themes; + } + setDaemonSetting(name, value) { this.props.setDaemonSetting(name, value); } @@ -273,7 +274,7 @@ class SettingsPage extends React.PureComponent { defaultValue={lbry.getClientSetting("theme")} className="form-field__input--inline" > - {themes.map((name, index) => + {this.getThemes().map((name, index) => )} diff --git a/ui/js/util/getThemes.js b/ui/js/util/getThemes.js deleted file mode 100644 index 09926502c..000000000 --- a/ui/js/util/getThemes.js +++ /dev/null @@ -1,21 +0,0 @@ -// Todo: Add a better way to do this -const { readdirSync } = require("fs"); -const { extname } = require("path"); -const { remote } = require("electron"); - -function getThemes() { - // Themes path - const themesPath = `${remote.app.getAppPath()}/dist/themes`; - - // Get all themes / only .css - const themes = readdirSync(themesPath).filter(function(file) { - return extname(file) === ".css"; - }); - - // Remove file extension (css) - return themes.map(function(theme) { - return theme.replace(".css", ""); - }); -} - -export default getThemes; From 8d1c3531b75460f9fb7dcc412f0c83f20d902160 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 6 Aug 2017 20:23:52 -0600 Subject: [PATCH 008/132] update build all.scss > themes/light.css --- build/build.sh | 2 +- ui/dist/index.html | 2 +- ui/dist/themes/light.css | 4 ++-- ui/watch.sh | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/build.sh b/build/build.sh index 9fa139877..7ac52a232 100755 --- a/build/build.sh +++ b/build/build.sh @@ -63,7 +63,7 @@ yarn install yarn install npm rebuild node-sass node extractLocals.js - node_modules/.bin/node-sass --output dist/css --sourcemap=none scss/ + node_modules/.bin/node-sass --sourcemap=none scss/all.scss dist/themes/light.css node_modules/.bin/webpack cp -r dist/* "$ROOT/app/dist/" ) diff --git a/ui/dist/index.html b/ui/dist/index.html index c5b675312..65372000d 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -6,7 +6,7 @@ - + diff --git a/ui/dist/themes/light.css b/ui/dist/themes/light.css index bdddae868..baafffae0 100644 --- a/ui/dist/themes/light.css +++ b/ui/dist/themes/light.css @@ -2050,13 +2050,13 @@ table.table-stretch { position: relative; z-index: 1; box-shadow: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2), 2px 3px 7px 0 rgba(0, 0, 0, 0.12); - transform: scale(1.1) translate3d(10px, 0, 0); + transform: scale(1.1) translateX(10px); transform-origin: 50% 50%; overflow-x: visible; overflow-y: visible; } .card--link:hover ~ .card--link { - transform: translate3d(20px, 0, 0); } + transform: translateX(20px); } .card__media { background-size: cover; diff --git a/ui/watch.sh b/ui/watch.sh index 4ea14c42b..b3d0e67ab 100755 --- a/ui/watch.sh +++ b/ui/watch.sh @@ -18,8 +18,8 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" fi # run sass once without --watch to force update. then run with --watch to keep watching - node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none $DIR/scss/ - node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none --watch $DIR/scss/ & + node_modules/.bin/node-sass --sourcemap=none $DIR/scss/all.scss $DIR/../app/dist/themes/light.css + node_modules/.bin/node-sass --sourcemap=none --watch $DIR/scss/all.scss $DIR/../app/dist/themes/light.css & node_modules/.bin/webpack --config webpack.dev.config.js --progress --colors --watch -) \ No newline at end of file +) From 0873cb76b066bcab5019a92a2ad06117c778d4f8 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 6 Aug 2017 21:01:10 -0600 Subject: [PATCH 009/132] fix react warning --- ui/js/page/settings/view.jsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 633554735..33d9fb638 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -20,6 +20,7 @@ class SettingsPage extends React.PureComponent { language: lbry.getClientSetting("language"), clearingCache: false, theme: lbry.getClientSetting("theme"), + themes: [], }; } @@ -37,7 +38,8 @@ class SettingsPage extends React.PureComponent { } getThemes() { - return this.props.getThemes().data.themes; + const themes = this.props.getThemes().data.themes; + this.setState({ themes }); } setDaemonSetting(name, value) { @@ -115,6 +117,11 @@ class SettingsPage extends React.PureComponent { onShowUnavailableChange(event) {} + componentDidMount() { + const { themes } = this.state; + this.getThemes(); + } + render() { const { daemonSettings } = this.props; @@ -242,7 +249,7 @@ class SettingsPage extends React.PureComponent { defaultValue={lbry.getClientSetting("theme")} className="form-field__input--inline" > - {this.getThemes().map((name, index) => + {this.state.themes.map((name, index) => )} From c4b8b0ff008a3f96563d6882dde3e66eb19f8983 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 6 Aug 2017 22:57:14 -0600 Subject: [PATCH 010/132] load dark theme --- app/package.json | 3 ++- app/yarn.lock | 4 ++++ build/build.sh | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/package.json b/app/package.json index 81027f7a8..39758862d 100644 --- a/app/package.json +++ b/app/package.json @@ -12,6 +12,7 @@ "install": "^0.8.7", "jayson": "^2.0.2", "keytar": "^4.0.3", + "lbry-dark-theme": "https://github.com/btzr-io/lbry-dark-theme", "npm": "^4.2.0", "semver": "^5.3.0", "tree-kill": "^1.1.0" @@ -22,4 +23,4 @@ "lbrySettings": { "lbrynetDaemonVersion": "0.14.2" } -} \ No newline at end of file +} diff --git a/app/yarn.lock b/app/yarn.lock index 22a12a134..341eeb5dc 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -876,6 +876,10 @@ lazy-req@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4" +"lbry-dark-theme@https://github.com/btzr-io/lbry-dark-theme": + version "2.0.0" + resolved "https://github.com/btzr-io/lbry-dark-theme#5ce4d2ceff67d62fde2eea307be728795b8b8c2f" + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" diff --git a/build/build.sh b/build/build.sh index 7ac52a232..6ea63e000 100755 --- a/build/build.sh +++ b/build/build.sh @@ -65,7 +65,20 @@ yarn install node extractLocals.js node_modules/.bin/node-sass --sourcemap=none scss/all.scss dist/themes/light.css node_modules/.bin/webpack - cp -r dist/* "$ROOT/app/dist/" + cp -r ./dist/ "$ROOT/app" +) + + + +#################### +# DARK-THEME # +################### + +( + cd "$ROOT/app/" + yarn add https://github.com/btzr-io/lbry-dark-theme --production + cd "./node_modules/lbry-dark-theme/dist/" + cp -r dark.css "$ROOT/app/dist/themes" ) From f403260598982b0a0bdd598c15c28748b976d231 Mon Sep 17 00:00:00 2001 From: hackrush Date: Tue, 25 Jul 2017 21:10:46 +0530 Subject: [PATCH 011/132] (WIP) Adds tipping feature to app. For issue #355 --- CHANGELOG.md | 1 + ui/js/component/fileActions/index.js | 8 +++ ui/js/component/fileActions/view.jsx | 101 +++++++++++++++++++++++++++ ui/js/page/filePage/view.jsx | 2 +- 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c4dd3b55..6aa02b84d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### 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 * ### Changed diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 4311823d1..fdfeacf61 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -6,6 +6,11 @@ import { makeSelectDownloadingForUri, makeSelectLoadingForUri, } from "selectors/file_info"; +import { + doSendDraftTransaction, + doSetDraftTransactionAmount, + doSetDraftTransactionAddress, +} from "actions/wallet"; import { makeSelectIsAvailableForUri } from "selectors/availability"; import { selectCurrentModal } from "selectors/app"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; @@ -48,6 +53,9 @@ const perform = dispatch => ({ startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), loadVideo: uri => dispatch(doLoadVideo(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), + sendToAddress: () => dispatch(doSendDraftTransaction()), + setAmount: amount => dispatch(doSetDraftTransactionAmount(amount)), + setAddress: address => dispatch(doSetDraftTransactionAddress(address)), }); export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index df624a345..e6f87f206 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,6 +1,7 @@ import React from "react"; import { Icon, BusyMessage } from "component/common"; import FilePrice from "component/filePrice"; +import { FormField } from "component/form"; import { Modal } from "component/modal"; import Link from "component/link"; import { ToolTip } from "component/tooltip"; @@ -13,6 +14,8 @@ class FileActions extends React.PureComponent { super(props); this.state = { forceShowActions: false, + showTipBox: false, + feeAmount: "1.00", }; } @@ -57,6 +60,37 @@ class FileActions extends React.PureComponent { this.props.loadVideo(this.props.uri); } + handleTipPublisherButtonClicked() { + this.setState({ + showTipBox: true, + }); + } + + handleTipButtonClicked() { + let address = this.props.claim.address; + let amount = this.state.feeAmount; + + this.props.setAddress(address); + this.props.setAmount(amount); + this.props.sendToAddress(); + + this.setState({ + showTipBox: false, + }); + } + + handleTipCancelButtonClicked() { + this.setState({ + showTipBox: false, + }); + } + + handleFeeAmountChange(event) { + this.setState({ + feeAmount: event.target.value, + }); + } + render() { const { fileInfo, @@ -75,6 +109,8 @@ class FileActions extends React.PureComponent { claimIsMine, } = this.props; + const { showTipBox } = this.state; + const metadata = fileInfo ? fileInfo.metadata : null, openInFolderMessage = platform.startsWith("Mac") ? __("Open in Finder") @@ -83,6 +119,40 @@ class FileActions extends React.PureComponent { title = metadata ? metadata.title : uri; let content; + let tipLink = ( + + ); + + let tipBox = ( + + this.handleFeeAmountChange(event)} + /> + {__(" ")} + + + + ); if (loading || downloading) { const progress = fileInfo && fileInfo.written_bytes @@ -180,6 +250,7 @@ class FileActions extends React.PureComponent { /> : ""} + {showTipBox ? tipBox : tipLink} } + {modal == "insufficientBalance" && + + {__( + "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." + )} + } + {modal == "transactionSuccessful" && + + {__( + "The publisher of the content was successfully tipped " + + this.state.feeAmount + + " LBC. Mahalo!" + )} + } + {modal == "transactionFailed" && + + {__("Something went wrong")}: + }
); } diff --git a/ui/js/page/filePage/view.jsx b/ui/js/page/filePage/view.jsx index 3ca23aadc..8bd952a60 100644 --- a/ui/js/page/filePage/view.jsx +++ b/ui/js/page/filePage/view.jsx @@ -126,7 +126,7 @@ class FilePage extends React.PureComponent { : uriIndicator}
- +
From f54f8a4e105d55d581c0a2a48cead088e89d2bbb Mon Sep 17 00:00:00 2001 From: hackrush Date: Thu, 27 Jul 2017 20:18:18 +0530 Subject: [PATCH 012/132] Testing with tip link in different file. --- ui/js/component/fileActions/view.jsx | 103 +--------------------- ui/js/component/tipLink/index.js | 28 ++++++ ui/js/component/tipLink/view.jsx | 123 +++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 101 deletions(-) create mode 100644 ui/js/component/tipLink/index.js create mode 100644 ui/js/component/tipLink/view.jsx diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index e6f87f206..fcffca1b9 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,7 +1,7 @@ import React from "react"; import { Icon, BusyMessage } from "component/common"; import FilePrice from "component/filePrice"; -import { FormField } from "component/form"; +import { TipLink } from "component/tipLink"; import { Modal } from "component/modal"; import Link from "component/link"; import { ToolTip } from "component/tooltip"; @@ -14,8 +14,6 @@ class FileActions extends React.PureComponent { super(props); this.state = { forceShowActions: false, - showTipBox: false, - feeAmount: "1.00", }; } @@ -60,37 +58,6 @@ class FileActions extends React.PureComponent { this.props.loadVideo(this.props.uri); } - handleTipPublisherButtonClicked() { - this.setState({ - showTipBox: true, - }); - } - - handleTipButtonClicked() { - let address = this.props.claim.address; - let amount = this.state.feeAmount; - - this.props.setAddress(address); - this.props.setAmount(amount); - this.props.sendToAddress(); - - this.setState({ - showTipBox: false, - }); - } - - handleTipCancelButtonClicked() { - this.setState({ - showTipBox: false, - }); - } - - handleFeeAmountChange(event) { - this.setState({ - feeAmount: event.target.value, - }); - } - render() { const { fileInfo, @@ -109,8 +76,6 @@ class FileActions extends React.PureComponent { claimIsMine, } = this.props; - const { showTipBox } = this.state; - const metadata = fileInfo ? fileInfo.metadata : null, openInFolderMessage = platform.startsWith("Mac") ? __("Open in Finder") @@ -119,40 +84,6 @@ class FileActions extends React.PureComponent { title = metadata ? metadata.title : uri; let content; - let tipLink = ( - - ); - - let tipBox = ( - - this.handleFeeAmountChange(event)} - /> - {__(" ")} - - - - ); if (loading || downloading) { const progress = fileInfo && fileInfo.written_bytes @@ -250,7 +181,7 @@ class FileActions extends React.PureComponent { /> : ""} - {showTipBox ? tipBox : tipLink} + } - {modal == "insufficientBalance" && - - {__( - "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." - )} - } - {modal == "transactionSuccessful" && - - {__( - "The publisher of the content was successfully tipped " + - this.state.feeAmount + - " LBC. Mahalo!" - )} - } - {modal == "transactionFailed" && - - {__("Something went wrong")}: - } ); } diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js new file mode 100644 index 000000000..41a894efb --- /dev/null +++ b/ui/js/component/tipLink/index.js @@ -0,0 +1,28 @@ +import React from "react"; +import { connect } from "react-redux"; +import { + doSendDraftTransaction, + doSetDraftTransactionAmount, + doSetDraftTransactionAddress, +} from "actions/wallet"; +import { selectCurrentModal } from "selectors/app"; +import { doCloseModal, doOpenModal } from "actions/app"; +import TipLink from "./view"; + +const makeSelect = () => { + const select = (state, props) => ({ + modal: selectCurrentModal(state), + }); + + return select; +}; + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), + openModal: modal => dispatch(doOpenModal(modal)), + sendToAddress: () => dispatch(doSendDraftTransaction()), + setAmount: amount => dispatch(doSetDraftTransactionAmount(amount)), + setAddress: address => dispatch(doSetDraftTransactionAddress(address)), +}); + +export default connect(makeSelect, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx new file mode 100644 index 000000000..caa0a767b --- /dev/null +++ b/ui/js/component/tipLink/view.jsx @@ -0,0 +1,123 @@ +import React from "react"; +import { Modal } from "component/modal"; +import Link from "component/link"; +import { FormField } from "component/form"; + +class TipLink extends React.PureComponent { + constructor(props) { + super(props); + + this.state = { + showTipBox: false, + feeAmount: "1.00", + }; + } + + handleTipPublisherButtonClicked() { + this.setState({ + showTipBox: true, + }); + } + + handleTipButtonClicked() { + let address = this.props.claim.address; + let amount = this.state.feeAmount; + + this.props.setAddress(address); + this.props.setAmount(amount); + this.props.sendToAddress(); + + this.setState({ + showTipBox: false, + }); + } + + handleTipCancelButtonClicked() { + this.setState({ + showTipBox: false, + }); + } + + handleFeeAmountChange(event) { + this.setState({ + feeAmount: event.target.value, + }); + } + + render() { + const { showTipBox } = this.state; + + let tipLink = ( + + ); + + let tipBox = ( + + this.handleFeeAmountChange(event)} + /> + {__(" ")} + + + + ); + + return ( +
+ {showTipBox ? tipBox : tipLink} + {modal == "insufficientBalance" && + + {__( + "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." + )} + } + {modal == "transactionSuccessful" && + + {__( + "The publisher of the content was successfully tipped " + + this.state.feeAmount + + " LBC. Mahalo!" + )} + } + {modal == "transactionFailed" && + + {__("Something went wrong")}: + } +
+ ); + } +} + +export default TipLink; From a74d61d6856b12386d5e1104702b79b8b8f5ef75 Mon Sep 17 00:00:00 2001 From: hackrush Date: Thu, 27 Jul 2017 22:25:51 +0530 Subject: [PATCH 013/132] Added tip related code in different file. --- ui/js/component/fileActions/index.js | 8 -------- ui/js/component/fileActions/view.jsx | 2 +- ui/js/component/tipLink/view.jsx | 5 +++-- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index fdfeacf61..4311823d1 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -6,11 +6,6 @@ import { makeSelectDownloadingForUri, makeSelectLoadingForUri, } from "selectors/file_info"; -import { - doSendDraftTransaction, - doSetDraftTransactionAmount, - doSetDraftTransactionAddress, -} from "actions/wallet"; import { makeSelectIsAvailableForUri } from "selectors/availability"; import { selectCurrentModal } from "selectors/app"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; @@ -53,9 +48,6 @@ const perform = dispatch => ({ startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), loadVideo: uri => dispatch(doLoadVideo(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), - sendToAddress: () => dispatch(doSendDraftTransaction()), - setAmount: amount => dispatch(doSetDraftTransactionAmount(amount)), - setAddress: address => dispatch(doSetDraftTransactionAddress(address)), }); export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index fcffca1b9..0f006ad60 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,7 +1,7 @@ import React from "react"; import { Icon, BusyMessage } from "component/common"; import FilePrice from "component/filePrice"; -import { TipLink } from "component/tipLink"; +import TipLink from "component/tipLink"; import { Modal } from "component/modal"; import Link from "component/link"; import { ToolTip } from "component/tooltip"; diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index caa0a767b..68452b085 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -45,6 +45,7 @@ class TipLink extends React.PureComponent { } render() { + const { modal, closeModal } = this.props; const { showTipBox } = this.state; let tipLink = ( @@ -83,7 +84,7 @@ class TipLink extends React.PureComponent { ); return ( -
+
{showTipBox ? tipBox : tipLink} {modal == "insufficientBalance" && {__("Something went wrong")}: } -
+
); } } From b8b3a6ffd2093d891789ba7590e8688ba562f03a Mon Sep 17 00:00:00 2001 From: hackrush Date: Fri, 28 Jul 2017 01:45:13 +0530 Subject: [PATCH 014/132] Changed modals to use constants. --- ui/js/actions/wallet.js | 9 +++-- ui/js/component/app/view.jsx | 7 ++++ .../modalInsufficientBalance/index.js | 16 ++++++++ .../modalInsufficientBalance/view.jsx | 26 +++++++++++++ .../component/modalTransactionFailed/index.js | 12 ++++++ .../component/modalTransactionFailed/view.jsx | 20 ++++++++++ .../modalTransactionSuccessful/index.js | 12 ++++++ .../modalTransactionSuccessful/view.jsx | 20 ++++++++++ ui/js/component/tipLink/index.js | 14 +------ ui/js/component/tipLink/view.jsx | 32 ---------------- ui/js/component/walletSend/index.js | 4 -- ui/js/component/walletSend/view.jsx | 37 +------------------ ui/js/constants/modal_types.js | 5 ++- 13 files changed, 125 insertions(+), 89 deletions(-) create mode 100644 ui/js/component/modalInsufficientBalance/index.js create mode 100644 ui/js/component/modalInsufficientBalance/view.jsx create mode 100644 ui/js/component/modalTransactionFailed/index.js create mode 100644 ui/js/component/modalTransactionFailed/view.jsx create mode 100644 ui/js/component/modalTransactionSuccessful/index.js create mode 100644 ui/js/component/modalTransactionSuccessful/view.jsx diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 17c4be201..3eeb3810f 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -6,6 +6,7 @@ import { selectBalance, } from "selectors/wallet"; import { doOpenModal } from "actions/app"; +import * as modals from "constants/modal_types"; export function doUpdateBalance(balance) { return { @@ -73,7 +74,7 @@ export function doSendDraftTransaction() { const amount = selectDraftTransactionAmount(state); if (balance - amount < 1) { - return dispatch(doOpenModal("insufficientBalance")); + return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); } dispatch({ @@ -85,13 +86,13 @@ export function doSendDraftTransaction() { dispatch({ type: types.SEND_TRANSACTION_COMPLETED, }); - dispatch(doOpenModal("transactionSuccessful")); + dispatch(doOpenModal(modals.TRANSACTION_SUCCESSFUL)); } else { dispatch({ type: types.SEND_TRANSACTION_FAILED, data: { error: results }, }); - dispatch(doOpenModal("transactionFailed")); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); } }; @@ -100,7 +101,7 @@ export function doSendDraftTransaction() { type: types.SEND_TRANSACTION_FAILED, data: { error: error.message }, }); - dispatch(doOpenModal("transactionFailed")); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); }; lbry diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index e8ebbcd09..b2782151e 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -8,6 +8,9 @@ import ModalInsufficientCredits from "component/modalInsufficientCredits"; import ModalUpgrade from "component/modalUpgrade"; import ModalWelcome from "component/modalWelcome"; import ModalFirstReward from "component/modalFirstReward"; +import ModalTransactionSuccessful from "component/modalTransactionSuccessful"; +import ModalTransactionFailed from "component/modalTransactionFailed"; +import ModalInsufficientBalance from "component/modalInsufficientBalance"; import lbry from "lbry"; import * as modals from "constants/modal_types"; @@ -78,6 +81,10 @@ class App extends React.PureComponent { {modal == modals.WELCOME && } {modal == modals.FIRST_REWARD && } {modal == modals.AUTHENTICATION_FAILURE && } + {modal == modals.TRANSACTION_SUCCESSFUL && + } + {modal == modals.TRANSACTION_FAILED && } + {modal == modals.INSUFFICIENT_BALANCE && } ); } diff --git a/ui/js/component/modalInsufficientBalance/index.js b/ui/js/component/modalInsufficientBalance/index.js new file mode 100644 index 000000000..c56232caf --- /dev/null +++ b/ui/js/component/modalInsufficientBalance/index.js @@ -0,0 +1,16 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal, doNavigate } from "actions/app"; +import ModalInsufficientBalance from "./view"; + +const select = state => ({}); + +const perform = dispatch => ({ + addBalance: () => { + dispatch(doNavigate("/wallet")); + dispatch(doCloseModal()); + }, + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalInsufficientBalance); diff --git a/ui/js/component/modalInsufficientBalance/view.jsx b/ui/js/component/modalInsufficientBalance/view.jsx new file mode 100644 index 000000000..f9ac56138 --- /dev/null +++ b/ui/js/component/modalInsufficientBalance/view.jsx @@ -0,0 +1,26 @@ +import React from "react"; +import { Modal } from "component/modal"; + +class ModalInsufficientBalance extends React.PureComponent { + render() { + const { addBalance, closeModal } = this.props; + + return ( + + {__( + "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." + )} + + ); + } +} + +export default ModalInsufficientBalance; diff --git a/ui/js/component/modalTransactionFailed/index.js b/ui/js/component/modalTransactionFailed/index.js new file mode 100644 index 000000000..4b370a7c8 --- /dev/null +++ b/ui/js/component/modalTransactionFailed/index.js @@ -0,0 +1,12 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal } from "actions/app"; +import ModalTransactionFailed from "./view"; + +const select = state => ({}); + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalTransactionFailed); diff --git a/ui/js/component/modalTransactionFailed/view.jsx b/ui/js/component/modalTransactionFailed/view.jsx new file mode 100644 index 000000000..f22038e78 --- /dev/null +++ b/ui/js/component/modalTransactionFailed/view.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { Modal } from "component/modal"; + +class ModalTransactionFailed extends React.PureComponent { + render() { + const { closeModal } = this.props; + + return ( + + {__("Something went wrong")}: + + ); + } +} + +export default ModalTransactionFailed; diff --git a/ui/js/component/modalTransactionSuccessful/index.js b/ui/js/component/modalTransactionSuccessful/index.js new file mode 100644 index 000000000..3e239d997 --- /dev/null +++ b/ui/js/component/modalTransactionSuccessful/index.js @@ -0,0 +1,12 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal } from "actions/app"; +import ModalTransactionSuccessful from "./view"; + +const select = state => ({}); + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalTransactionSuccessful); diff --git a/ui/js/component/modalTransactionSuccessful/view.jsx b/ui/js/component/modalTransactionSuccessful/view.jsx new file mode 100644 index 000000000..6f9f68f81 --- /dev/null +++ b/ui/js/component/modalTransactionSuccessful/view.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { Modal } from "component/modal"; + +class ModalTransactionSuccessful extends React.PureComponent { + render() { + const { closeModal } = this.props; + + return ( + + {__("Your transaction was successfully placed in the queue.")} + + ); + } +} + +export default ModalTransactionSuccessful; diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js index 41a894efb..3e093833e 100644 --- a/ui/js/component/tipLink/index.js +++ b/ui/js/component/tipLink/index.js @@ -5,24 +5,14 @@ import { doSetDraftTransactionAmount, doSetDraftTransactionAddress, } from "actions/wallet"; -import { selectCurrentModal } from "selectors/app"; -import { doCloseModal, doOpenModal } from "actions/app"; import TipLink from "./view"; -const makeSelect = () => { - const select = (state, props) => ({ - modal: selectCurrentModal(state), - }); - - return select; -}; +const select = state => ({}); const perform = dispatch => ({ - closeModal: () => dispatch(doCloseModal()), - openModal: modal => dispatch(doOpenModal(modal)), sendToAddress: () => dispatch(doSendDraftTransaction()), setAmount: amount => dispatch(doSetDraftTransactionAmount(amount)), setAddress: address => dispatch(doSetDraftTransactionAddress(address)), }); -export default connect(makeSelect, perform)(TipLink); +export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 68452b085..4003cd25d 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -1,5 +1,4 @@ import React from "react"; -import { Modal } from "component/modal"; import Link from "component/link"; import { FormField } from "component/form"; @@ -45,7 +44,6 @@ class TipLink extends React.PureComponent { } render() { - const { modal, closeModal } = this.props; const { showTipBox } = this.state; let tipLink = ( @@ -86,36 +84,6 @@ class TipLink extends React.PureComponent { return (
{showTipBox ? tipBox : tipLink} - {modal == "insufficientBalance" && - - {__( - "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." - )} - } - {modal == "transactionSuccessful" && - - {__( - "The publisher of the content was successfully tipped " + - this.state.feeAmount + - " LBC. Mahalo!" - )} - } - {modal == "transactionFailed" && - - {__("Something went wrong")}: - }
); } diff --git a/ui/js/component/walletSend/index.js b/ui/js/component/walletSend/index.js index ab13440db..50712e14c 100644 --- a/ui/js/component/walletSend/index.js +++ b/ui/js/component/walletSend/index.js @@ -1,12 +1,10 @@ import React from "react"; import { connect } from "react-redux"; -import { doCloseModal } from "actions/app"; import { doSendDraftTransaction, doSetDraftTransactionAmount, doSetDraftTransactionAddress, } from "actions/wallet"; -import { selectCurrentModal } from "selectors/app"; import { selectDraftTransactionAmount, selectDraftTransactionAddress, @@ -15,13 +13,11 @@ import { import WalletSend from "./view"; const select = state => ({ - modal: selectCurrentModal(state), address: selectDraftTransactionAddress(state), amount: selectDraftTransactionAmount(state), }); const perform = dispatch => ({ - closeModal: () => dispatch(doCloseModal()), sendToAddress: () => dispatch(doSendDraftTransaction()), setAmount: event => dispatch(doSetDraftTransactionAmount(event.target.value)), setAddress: event => diff --git a/ui/js/component/walletSend/view.jsx b/ui/js/component/walletSend/view.jsx index 4d4de0fd6..28e62de68 100644 --- a/ui/js/component/walletSend/view.jsx +++ b/ui/js/component/walletSend/view.jsx @@ -1,18 +1,9 @@ import React from "react"; import Link from "component/link"; -import Modal from "component/modal"; import { FormRow } from "component/form"; const WalletSend = props => { - const { - sendToAddress, - closeModal, - modal, - setAmount, - setAddress, - amount, - address, - } = props; + const { sendToAddress, setAmount, setAddress, amount, address } = props; return (
@@ -52,32 +43,6 @@ const WalletSend = props => { - {modal == "insufficientBalance" && - - {__( - "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." - )} - } - {modal == "transactionSuccessful" && - - {__("Your transaction was successfully placed in the queue.")} - } - {modal == "transactionFailed" && - - {__("Something went wrong")}: - }
); }; diff --git a/ui/js/constants/modal_types.js b/ui/js/constants/modal_types.js index 153996e00..9c2d25af0 100644 --- a/ui/js/constants/modal_types.js +++ b/ui/js/constants/modal_types.js @@ -6,4 +6,7 @@ export const INSUFFICIENT_CREDITS = "insufficient_credits"; export const UPGRADE = "upgrade"; export const WELCOME = "welcome"; export const FIRST_REWARD = "first_reward"; -export const AUTHENTICATION_FAILURE = "auth_failure"; \ No newline at end of file +export const AUTHENTICATION_FAILURE = "auth_failure"; +export const TRANSACTION_SUCCESSFUL = "transaction_successful"; +export const TRANSACTION_FAILED = "transaction_failed"; +export const INSUFFICIENT_BALANCE = "insufficient_balance"; From ba6d093d1c3e02c5f8eb177a978ea1db387c9ac3 Mon Sep 17 00:00:00 2001 From: hackrush Date: Fri, 28 Jul 2017 05:04:42 +0530 Subject: [PATCH 015/132] Added new component form for price, also only tipping form is shown when clicked. --- ui/js/component/fileActions/view.jsx | 26 +++++++++++++++--- ui/js/component/priceForm/index.js | 5 ++++ ui/js/component/priceForm/view.jsx | 39 +++++++++++++++++++++++++++ ui/js/component/tipLink/view.jsx | 40 ++++++++++++++-------------- 4 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 ui/js/component/priceForm/index.js create mode 100644 ui/js/component/priceForm/view.jsx diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 0f006ad60..216202205 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -14,6 +14,7 @@ class FileActions extends React.PureComponent { super(props); this.state = { forceShowActions: false, + showTipBox: false, }; } @@ -58,6 +59,18 @@ class FileActions extends React.PureComponent { this.props.loadVideo(this.props.uri); } + handleTipShow() { + this.setState({ + showTipBox: true, + }); + } + + handleTipHide() { + this.setState({ + showTipBox: false, + }); + } + render() { const { fileInfo, @@ -76,6 +89,8 @@ class FileActions extends React.PureComponent { claimIsMine, } = this.props; + const { showTipBox } = this.state; + const metadata = fileInfo ? fileInfo.metadata : null, openInFolderMessage = platform.startsWith("Mac") ? __("Open in Finder") @@ -166,8 +181,14 @@ class FileActions extends React.PureComponent { return (
- {content} - {showMenu + {showTipBox ? "" : content} + + {showMenu && !showTipBox ? : ""} - { + const { + onFeeChange, + onCurrencyChange, + defaultFeeValue, + defaultCurrencyValue, + placeholder, + min, + step, + } = props; + + return ( + + + + + + + + ); +}; + +export default PriceForm; diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 4003cd25d..25740298a 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -1,21 +1,20 @@ import React from "react"; import Link from "component/link"; import { FormField } from "component/form"; +import PriceForm from "component/priceForm"; class TipLink extends React.PureComponent { constructor(props) { super(props); this.state = { - showTipBox: false, feeAmount: "1.00", + currency: "LBC", }; } handleTipPublisherButtonClicked() { - this.setState({ - showTipBox: true, - }); + this.props.onTipShow(); } handleTipButtonClicked() { @@ -26,15 +25,11 @@ class TipLink extends React.PureComponent { this.props.setAmount(amount); this.props.sendToAddress(); - this.setState({ - showTipBox: false, - }); + this.props.onTipHide(); } handleTipCancelButtonClicked() { - this.setState({ - showTipBox: false, - }); + this.props.onTipHide(); } handleFeeAmountChange(event) { @@ -43,12 +38,18 @@ class TipLink extends React.PureComponent { }); } + handleCurrencyChange(event) { + this.setState({ + currency: event.target.value, + }); + } + render() { - const { showTipBox } = this.state; + const { showTipBox } = this.props; let tipLink = ( - this.handleFeeAmountChange(event)} + placeholder="1.00" + step="0.1" + onFeeChange={event => this.handleFeeAmountChange(event)} + defaultFeeValue="1.00" + onCurrencyChange={event => this.handleCurrencyChange(event)} + defaultCurrencyValue="LBC" /> {__(" ")} Date: Sat, 29 Jul 2017 12:20:17 +0530 Subject: [PATCH 016/132] Displays snackBar for any successful trasaction. Also, minor changes to tip form css, to increase gap between select box and tip button. --- ui/js/actions/wallet.js | 10 ++++++++-- ui/js/component/app/view.jsx | 3 --- .../modalTransactionSuccessful/index.js | 12 ----------- .../modalTransactionSuccessful/view.jsx | 20 ------------------- ui/js/component/priceForm/view.jsx | 3 ++- ui/js/component/tipLink/view.jsx | 12 +++++++++-- ui/js/constants/modal_types.js | 1 - ui/scss/component/_form-field.scss | 4 ++++ 8 files changed, 24 insertions(+), 41 deletions(-) delete mode 100644 ui/js/component/modalTransactionSuccessful/index.js delete mode 100644 ui/js/component/modalTransactionSuccessful/view.jsx diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 3eeb3810f..565ca478d 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -5,7 +5,7 @@ import { selectDraftTransactionAmount, selectBalance, } from "selectors/wallet"; -import { doOpenModal } from "actions/app"; +import { doOpenModal, doShowSnackBar } from "actions/app"; import * as modals from "constants/modal_types"; export function doUpdateBalance(balance) { @@ -86,7 +86,13 @@ export function doSendDraftTransaction() { dispatch({ type: types.SEND_TRANSACTION_COMPLETED, }); - dispatch(doOpenModal(modals.TRANSACTION_SUCCESSFUL)); + dispatch( + doShowSnackBar({ + message: __(`You sent ${amount} LBC`), + linkText: __("History"), + linkTarget: __("/wallet"), + }) + ); } else { dispatch({ type: types.SEND_TRANSACTION_FAILED, diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index b2782151e..6cedc6096 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -8,7 +8,6 @@ import ModalInsufficientCredits from "component/modalInsufficientCredits"; import ModalUpgrade from "component/modalUpgrade"; import ModalWelcome from "component/modalWelcome"; import ModalFirstReward from "component/modalFirstReward"; -import ModalTransactionSuccessful from "component/modalTransactionSuccessful"; import ModalTransactionFailed from "component/modalTransactionFailed"; import ModalInsufficientBalance from "component/modalInsufficientBalance"; import lbry from "lbry"; @@ -81,8 +80,6 @@ class App extends React.PureComponent { {modal == modals.WELCOME && } {modal == modals.FIRST_REWARD && } {modal == modals.AUTHENTICATION_FAILURE && } - {modal == modals.TRANSACTION_SUCCESSFUL && - } {modal == modals.TRANSACTION_FAILED && } {modal == modals.INSUFFICIENT_BALANCE && } diff --git a/ui/js/component/modalTransactionSuccessful/index.js b/ui/js/component/modalTransactionSuccessful/index.js deleted file mode 100644 index 3e239d997..000000000 --- a/ui/js/component/modalTransactionSuccessful/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { doCloseModal } from "actions/app"; -import ModalTransactionSuccessful from "./view"; - -const select = state => ({}); - -const perform = dispatch => ({ - closeModal: () => dispatch(doCloseModal()), -}); - -export default connect(select, perform)(ModalTransactionSuccessful); diff --git a/ui/js/component/modalTransactionSuccessful/view.jsx b/ui/js/component/modalTransactionSuccessful/view.jsx deleted file mode 100644 index 6f9f68f81..000000000 --- a/ui/js/component/modalTransactionSuccessful/view.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react"; -import { Modal } from "component/modal"; - -class ModalTransactionSuccessful extends React.PureComponent { - render() { - const { closeModal } = this.props; - - return ( - - {__("Your transaction was successfully placed in the queue.")} - - ); - } -} - -export default ModalTransactionSuccessful; diff --git a/ui/js/component/priceForm/view.jsx b/ui/js/component/priceForm/view.jsx index b4c8318c0..bba0173f5 100644 --- a/ui/js/component/priceForm/view.jsx +++ b/ui/js/component/priceForm/view.jsx @@ -10,10 +10,11 @@ const PriceForm = props => { placeholder, min, step, + isTip, } = props; return ( - + this.handleFeeAmountChange(event)} - defaultFeeValue="1.00" + defaultFeeValue={this.state.feeAmount} onCurrencyChange={event => this.handleCurrencyChange(event)} defaultCurrencyValue="LBC" /> - {__(" ")} Date: Sat, 29 Jul 2017 13:51:03 +0530 Subject: [PATCH 017/132] Removed useless passing of claim arg in filePage --- ui/js/component/fileActions/index.js | 7 ++++++- ui/js/component/fileActions/view.jsx | 3 ++- ui/js/component/tipLink/view.jsx | 2 +- ui/js/page/filePage/view.jsx | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 4311823d1..5802526af 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -12,7 +12,10 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doCloseModal, doOpenModal } from "actions/app"; import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; -import { makeSelectClaimForUriIsMine } from "selectors/claims"; +import { + makeSelectClaimForUriIsMine, + makeSelectClaimForUri, +} from "selectors/claims"; import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; import FileActions from "./view"; @@ -23,6 +26,7 @@ const makeSelect = () => { const selectCostInfoForUri = makeSelectCostInfoForUri(); const selectLoadingForUri = makeSelectLoadingForUri(); const selectClaimForUriIsMine = makeSelectClaimForUriIsMine(); + const selectClaimForUri = makeSelectClaimForUri(); const select = (state, props) => ({ fileInfo: selectFileInfoForUri(state, props), @@ -34,6 +38,7 @@ const makeSelect = () => { costInfo: selectCostInfoForUri(state, props), loading: selectLoadingForUri(state, props), claimIsMine: selectClaimForUriIsMine(state, props), + claimInfo: selectClaimForUri(state, props), }); return select; diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 216202205..79bfbf506 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -87,6 +87,7 @@ class FileActions extends React.PureComponent { costInfo, loading, claimIsMine, + claimInfo, } = this.props; const { showTipBox } = this.state; @@ -186,7 +187,7 @@ class FileActions extends React.PureComponent { onTipShow={this.handleTipShow.bind(this)} onTipHide={this.handleTipHide.bind(this)} showTipBox={showTipBox} - claim={this.props.claim} + address={claimInfo.address} /> {showMenu && !showTipBox ? diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 3f710007f..7138e95aa 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -19,7 +19,7 @@ class TipLink extends React.PureComponent { } handleTipButtonClicked() { - let address = this.props.claim.address; + let address = this.props.address; let amount = this.state.feeAmount; this.props.setAddress(address); diff --git a/ui/js/page/filePage/view.jsx b/ui/js/page/filePage/view.jsx index 8bd952a60..3ca23aadc 100644 --- a/ui/js/page/filePage/view.jsx +++ b/ui/js/page/filePage/view.jsx @@ -126,7 +126,7 @@ class FilePage extends React.PureComponent { : uriIndicator}
- +
From 4d60f96b85154adc4b8f35df14e1090dbc9d3af7 Mon Sep 17 00:00:00 2001 From: hackrush Date: Sat, 29 Jul 2017 14:06:42 +0530 Subject: [PATCH 018/132] The form now displays a help message. --- ui/js/component/tipLink/view.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 7138e95aa..373f46257 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -86,6 +86,9 @@ class TipLink extends React.PureComponent { button="alt" onClick={this.handleTipCancelButtonClicked.bind(this)} /> +
+ {__("This sends the entered amount of LBCs to the publisher.")} +
); From 03ee864af0bef0372551f6e31c215e1a360eb116 Mon Sep 17 00:00:00 2001 From: hackrush Date: Tue, 8 Aug 2017 03:43:58 +0530 Subject: [PATCH 019/132] (WIP) Tip as support Functionality Only. --- ui/js/actions/claims.js | 76 ++++++++++++++++++++++++++++ ui/js/component/fileActions/view.jsx | 2 +- ui/js/component/priceForm/index.js | 5 -- ui/js/component/priceForm/view.jsx | 40 --------------- ui/js/component/tipLink/index.js | 14 ++--- ui/js/component/tipLink/view.jsx | 48 ++++++++---------- ui/js/constants/action_types.js | 10 +++- ui/js/reducers/claims.js | 58 ++++++++++++++++++++- ui/js/selectors/claims.js | 10 ++++ 9 files changed, 179 insertions(+), 84 deletions(-) create mode 100644 ui/js/actions/claims.js delete mode 100644 ui/js/component/priceForm/index.js delete mode 100644 ui/js/component/priceForm/view.jsx diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js new file mode 100644 index 000000000..5d72a9f5f --- /dev/null +++ b/ui/js/actions/claims.js @@ -0,0 +1,76 @@ +import lbry from "lbry"; +import { selectBalance } from "selectors/wallet"; +import { + selectSupportTransaction, + selectSupportTransactionAmount, +} from "selectors/claims"; +import { doOpenModal, doShowSnackBar } from "actions/app"; +import * as types from "constants/action_types"; +import * as modals from "constants/modal_types"; + +export function doSendSupport() { + return function(dispatch, getState) { + const state = getState(); + const supportTx = selectSupportTransaction(state); + const balance = selectBalance(state); + const amount = selectSupportTransactionAmount(state); + + if (balance - amount < 1) { + return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); + } + + dispatch({ + type: types.SUPPORT_TRANSACTION_STARTED, + }); + + const successCallback = results => { + if (results.txid) { + dispatch({ + type: types.SUPPORT_TRANSACTION_COMPLETED, + }); + dispatch( + doShowSnackBar({ + message: __(`You sent ${amount} LBC as support, Mahalo!`), + linkText: __("History"), + linkTarget: __("/wallet"), + }) + ); + } else { + dispatch({ + type: types.SUPPORT_TRANSACTION_FAILED, + data: { error: results }, + }); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + } + }; + + const errorCallback = error => { + dispatch({ + type: types.SUPPORT_TRANSACTION_FAILED, + data: { error: error.message }, + }); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + }; + + lbry + .claim_send_tip({ + claim_id: supportTx.claim_id, + amount: supportTx.amount, + }) + .then(successCallback, errorCallback); + }; +} + +export function doSetSupportAmount(amount) { + return { + type: types.SET_SUPPORT_AMOUNT, + data: { amount }, + }; +} + +export function doSetSupportClaimID(claim_id) { + return { + type: types.SET_SUPPORT_CLAIMID, + data: { claim_id }, + }; +} diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 79bfbf506..1b0c2670a 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -187,7 +187,7 @@ class FileActions extends React.PureComponent { onTipShow={this.handleTipShow.bind(this)} onTipHide={this.handleTipHide.bind(this)} showTipBox={showTipBox} - address={claimInfo.address} + claim_id={claimInfo.claim_id} /> {showMenu && !showTipBox ? diff --git a/ui/js/component/priceForm/index.js b/ui/js/component/priceForm/index.js deleted file mode 100644 index 5370b8ed1..000000000 --- a/ui/js/component/priceForm/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import PriceForm from "./view"; - -export default connect(null, null)(PriceForm); diff --git a/ui/js/component/priceForm/view.jsx b/ui/js/component/priceForm/view.jsx deleted file mode 100644 index bba0173f5..000000000 --- a/ui/js/component/priceForm/view.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import { FormField } from "component/form"; - -const PriceForm = props => { - const { - onFeeChange, - onCurrencyChange, - defaultFeeValue, - defaultCurrencyValue, - placeholder, - min, - step, - isTip, - } = props; - - return ( - - - - - - - - ); -}; - -export default PriceForm; diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js index 3e093833e..b969bfb57 100644 --- a/ui/js/component/tipLink/index.js +++ b/ui/js/component/tipLink/index.js @@ -1,18 +1,18 @@ import React from "react"; import { connect } from "react-redux"; import { - doSendDraftTransaction, - doSetDraftTransactionAmount, - doSetDraftTransactionAddress, -} from "actions/wallet"; + doSendSupport, + doSetSupportAmount, + doSetSupportClaimID, +} from "actions/claims"; import TipLink from "./view"; const select = state => ({}); const perform = dispatch => ({ - sendToAddress: () => dispatch(doSendDraftTransaction()), - setAmount: amount => dispatch(doSetDraftTransactionAmount(amount)), - setAddress: address => dispatch(doSetDraftTransactionAddress(address)), + sendSupport: () => dispatch(doSendSupport()), + setAmount: amount => dispatch(doSetSupportAmount(amount)), + setClaimID: claim_id => dispatch(doSetSupportClaimID(claim_id)), }); export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 373f46257..295afc3db 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -1,7 +1,6 @@ import React from "react"; import Link from "component/link"; -import { FormField } from "component/form"; -import PriceForm from "component/priceForm"; +import FormFieldPrice from "component/formFieldPrice"; class TipLink extends React.PureComponent { constructor(props) { @@ -13,35 +12,30 @@ class TipLink extends React.PureComponent { }; } - handleTipPublisherButtonClicked() { + handleSupportButtonClicked() { this.resetDefaults(); this.props.onTipShow(); } - handleTipButtonClicked() { - let address = this.props.address; + handleSendButtonClicked() { + let claim_id = this.props.claim_id; let amount = this.state.feeAmount; - this.props.setAddress(address); + this.props.setClaimID(claim_id); this.props.setAmount(amount); - this.props.sendToAddress(); + this.props.sendSupport(); this.props.onTipHide(); } - handleTipCancelButtonClicked() { + handleSupportCancelButtonClicked() { this.props.onTipHide(); } - handleFeeAmountChange(event) { + handleSupportPriceChange(newValue) { this.setState({ - feeAmount: event.target.value, - }); - } - - handleCurrencyChange(event) { - this.setState({ - currency: event.target.value, + feeAmount: newValue.amount, + feeCurrency: newValue.currency, }); } @@ -54,37 +48,35 @@ class TipLink extends React.PureComponent { render() { const { showTipBox } = this.props; + const { feeAmount, currency } = this.state; let tipLink = ( ); let tipBox = ( - this.handleFeeAmountChange(event)} - defaultFeeValue={this.state.feeAmount} - onCurrencyChange={event => this.handleCurrencyChange(event)} - defaultCurrencyValue="LBC" + onChange={value => this.handleSupportPriceChange(value)} + defaultValue={{ amount: feeAmount, currency: currency }} />
{__("This sends the entered amount of LBCs to the publisher.")} diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 71d6d8072..8d53d0806 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -112,5 +112,11 @@ export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED"; export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS"; export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; -export const FETCH_REWARD_CONTENT_COMPLETED = - "FETCH_REWARD_CONTENT_COMPLETED"; +export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; + +// Supports +export const SET_SUPPORT_CLAIMID = "SET_SUPPORT_CLAIMID"; +export const SET_SUPPORT_AMOUNT = "SET_SUPPORT_AMOUNT"; +export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; +export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; +export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js index c70fd45e0..8d913438d 100644 --- a/ui/js/reducers/claims.js +++ b/ui/js/reducers/claims.js @@ -2,7 +2,14 @@ import * as types from "constants/action_types"; import lbryuri from "lbryuri"; const reducers = {}; -const defaultState = {}; +const buildSupportTransaction = () => ({ + claim_id: undefined, + amount: undefined, +}); + +const defaultState = { + supportTransaction: buildSupportTransaction(), +}; reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) { const { uri, certificate, claim } = action.data; @@ -190,6 +197,55 @@ reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) { }); }; +reducers[types.SET_SUPPORT_AMOUNT] = function(state, action) { + const oldDraft = state.supportTransaction; + const newDraft = Object.assign({}, oldDraft, { + amount: parseFloat(action.data.amount), + }); + + return Object.assign({}, state, { + supportTransaction: newDraft, + }); +}; + +reducers[types.SET_SUPPORT_CLAIMID] = function(state, action) { + const oldDraft = state.supportTransaction; + const newDraft = Object.assign({}, oldDraft, { + claim_id: action.data.claim_id, + }); + + return Object.assign({}, state, { + supportTransaction: newDraft, + }); +}; + +reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { + const newSupportTransaction = Object.assign({}, state.supportTransaction, { + sendingSupport: true, + }); + + return Object.assign({}, state, { + supportTransaction: newSupportTransaction, + }); +}; + +reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { + return Object.assign({}, state, { + supportTransaction: buildSupportTransaction(), + }); +}; + +reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { + const newSupportTransaction = Object.assign({}, state.supportTransaction, { + sendingSupport: false, + error: action.data.error, + }); + + return Object.assign({}, state, { + supportTransaction: newSupportTransaction, + }); +}; + export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 2c4b4b511..4676eb77a 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -215,3 +215,13 @@ export const selectMyChannelClaims = createSelector( return claims; } ); + +export const selectSupportTransaction = createSelector( + _selectState, + state => state.supportTransaction || {} +); + +export const selectSupportTransactionAmount = createSelector( + selectSupportTransaction, + supportTxAmount => supportTxAmount.amount +); From beffda09bdb3a8155b8d3603e6927e8dc71f20f9 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 11 Aug 2017 17:29:35 -0600 Subject: [PATCH 020/132] update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c4d8d48..bf3b16dff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added * Added a new component, `FormFieldPrice` which is now used in Publish and Settings + * Added a theme system to select different themes in Settings. + * New Dark theme. * ### Changed From c9c50349b8e81a100ed7c0830796289d59a23a49 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 12:46:10 -0600 Subject: [PATCH 021/132] implement initial fallback for missing theme load last theme selected --- ui/js/main.js | 4 ++++ ui/js/page/settings/view.jsx | 15 +++++++++------ ui/js/util/setTheme.js | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 ui/js/util/setTheme.js diff --git a/ui/js/main.js b/ui/js/main.js index 48f838331..999a13c64 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -8,6 +8,7 @@ import store from "store.js"; import SplashScreen from "component/splash"; import { doChangePath, doNavigate, doDaemonReady } from "actions/app"; import { toQueryString } from "util/query_params"; +import setTheme from "util/setTheme"; import * as types from "constants/action_types"; const env = ENV; @@ -71,6 +72,9 @@ document.addEventListener("click", event => { } }); +// Load initial theme +setTheme(lbry.getClientSetting("theme")); + const application = remote.app; const dock = application.dock; const win = remote.getCurrentWindow(); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 33d9fb638..37b9e4a6a 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -6,6 +6,7 @@ import lbry from "lbry.js"; import Link from "component/link"; import FormFieldPrice from "component/formFieldPrice"; import { remote } from "electron"; +import setTheme from "util/setTheme"; class SettingsPage extends React.PureComponent { constructor(props) { @@ -38,7 +39,7 @@ class SettingsPage extends React.PureComponent { } getThemes() { - const themes = this.props.getThemes().data.themes; + const { themes } = this.props.getThemes().data; this.setState({ themes }); } @@ -51,6 +52,11 @@ class SettingsPage extends React.PureComponent { this._onSettingSaveSuccess(); } + setTheme(value) { + setTheme(value); + this.props.setClientSetting("theme", value); + } + onRunOnStartChange(event) { this.setDaemonSetting("run_on_startup", event.target.checked); } @@ -72,11 +78,8 @@ class SettingsPage extends React.PureComponent { } onThemeChange(event) { - // Todo: Add better way to handle this - const value = event.target.value; - const link = document.getElementById("theme"); - link.href = `./themes/${value}.css`; - this.props.setClientSetting("theme", value); + const { value } = event.target; + this.setTheme(value); } // onMaxUploadPrefChange(isLimited) { diff --git a/ui/js/util/setTheme.js b/ui/js/util/setTheme.js new file mode 100644 index 000000000..3e7e94fd2 --- /dev/null +++ b/ui/js/util/setTheme.js @@ -0,0 +1,18 @@ +import lbry from "lbry"; +import { existsSync } from "fs"; +import { remote } from "electron"; + +function setTheme(name) { + const link = document.getElementById("theme"); + const file = `${name}.css`; + const path = `${remote.app.getAppPath()}/dist/themes/${file}`; + + if (existsSync(path)) { + link.href = `./themes/${file}`; + lbry.setClientSetting("theme", name); + } else { + lbry.setClientSetting("theme", "light"); + } +} + +export default setTheme; From 8a416856e3a06b06d534c2b808ba47d41dd060e1 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 13:51:16 -0600 Subject: [PATCH 022/132] load light theme as fallback --- ui/js/util/setTheme.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/js/util/setTheme.js b/ui/js/util/setTheme.js index 3e7e94fd2..71c101298 100644 --- a/ui/js/util/setTheme.js +++ b/ui/js/util/setTheme.js @@ -11,6 +11,7 @@ function setTheme(name) { link.href = `./themes/${file}`; lbry.setClientSetting("theme", name); } else { + link.href = `./themes/light.css`; lbry.setClientSetting("theme", "light"); } } From a71426b119fafba0f0eca530dc1381d995325f88 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 19:57:02 -0600 Subject: [PATCH 023/132] remove compiled css --- ui/dist/themes/light.css | 2859 -------------------------------------- 1 file changed, 2859 deletions(-) delete mode 100644 ui/dist/themes/light.css diff --git a/ui/dist/themes/light.css b/ui/dist/themes/light.css deleted file mode 100644 index baafffae0..000000000 --- a/ui/dist/themes/light.css +++ /dev/null @@ -1,2859 +0,0 @@ -body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, select, textarea, p, blockquote, th, td, iframe { - margin: 0; - padding: 0; } - -:focus { - outline: 0; } - -input::-webkit-search-cancel-button { - /* Remove default */ - -webkit-appearance: none; } - -table { - border-collapse: collapse; - border-spacing: 0; } - -fieldset, img, iframe { - border: 0; } - -h1, h2, h3, h4, h5, h6 { - font-weight: normal; } - -ol, ul { - list-style-position: inside; } - ol > li, ul > li { - list-style-position: inside; } - -input, textarea, select { - font-family: inherit; - font-size: inherit; - font-weight: inherit; - border: 0 none; } - -img { - width: auto\9; - height: auto; - vertical-align: middle; - -ms-interpolation-mode: bicubic; } - -a { - color: inherit; - text-decoration: none; } - -@font-face { - font-family: 'FontAwesome'; - src: url("../font/fontawesome-webfont.eot?v=4.3.0"); - src: url("../font/fontawesome-webfont.eot?#iefix&v=4.3.0") format("embedded-opentype"), url("../font/fontawesome-webfont.woff2?v=4.3.0") format("woff2"), url("../font/fontawesome-webfont.woff?v=4.3.0") format("woff"), url("../font/fontawesome-webfont.ttf?v=4.3.0") format("truetype"), url("../font/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular") format("svg"); - font-weight: normal; - font-style: normal; } - -[class*="icon-"] { - display: inline-block; - text-align: center; - font-family: "FontAwesome"; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - speak: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-size: inherit; - text-rendering: auto; - transform: translate(0, 0); } - -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.icon-glass:before { - content: "\f000"; } - -.icon-music:before { - content: "\f001"; } - -.icon-search:before { - content: "\f002"; } - -.icon-envelope-o:before { - content: "\f003"; } - -.icon-heart:before { - content: "\f004"; } - -.icon-star:before { - content: "\f005"; } - -.icon-star-o:before { - content: "\f006"; } - -.icon-user:before { - content: "\f007"; } - -.icon-film:before { - content: "\f008"; } - -.icon-th-large:before { - content: "\f009"; } - -.icon-th:before { - content: "\f00a"; } - -.icon-th-list:before { - content: "\f00b"; } - -.icon-check:before { - content: "\f00c"; } - -.icon-remove:before, -.icon-close:before, -.icon-times:before { - content: "\f00d"; } - -.icon-search-plus:before { - content: "\f00e"; } - -.icon-search-minus:before { - content: "\f010"; } - -.icon-power-off:before { - content: "\f011"; } - -.icon-signal:before { - content: "\f012"; } - -.icon-gear:before, -.icon-cog:before { - content: "\f013"; } - -.icon-trash-o:before { - content: "\f014"; } - -.icon-home:before { - content: "\f015"; } - -.icon-file-o:before { - content: "\f016"; } - -.icon-clock-o:before { - content: "\f017"; } - -.icon-road:before { - content: "\f018"; } - -.icon-download:before { - content: "\f019"; } - -.icon-arrow-circle-o-down:before { - content: "\f01a"; } - -.icon-arrow-circle-o-up:before { - content: "\f01b"; } - -.icon-inbox:before { - content: "\f01c"; } - -.icon-play-circle-o:before { - content: "\f01d"; } - -.icon-rotate-right:before, -.icon-repeat:before { - content: "\f01e"; } - -.icon-refresh:before { - content: "\f021"; } - -.icon-list-alt:before { - content: "\f022"; } - -.icon-lock:before { - content: "\f023"; } - -.icon-flag:before { - content: "\f024"; } - -.icon-headphones:before { - content: "\f025"; } - -.icon-volume-off:before { - content: "\f026"; } - -.icon-volume-down:before { - content: "\f027"; } - -.icon-volume-up:before { - content: "\f028"; } - -.icon-qrcode:before { - content: "\f029"; } - -.icon-barcode:before { - content: "\f02a"; } - -.icon-tag:before { - content: "\f02b"; } - -.icon-tags:before { - content: "\f02c"; } - -.icon-book:before { - content: "\f02d"; } - -.icon-bookmark:before { - content: "\f02e"; } - -.icon-print:before { - content: "\f02f"; } - -.icon-camera:before { - content: "\f030"; } - -.icon-font:before { - content: "\f031"; } - -.icon-bold:before { - content: "\f032"; } - -.icon-italic:before { - content: "\f033"; } - -.icon-text-height:before { - content: "\f034"; } - -.icon-text-width:before { - content: "\f035"; } - -.icon-align-left:before { - content: "\f036"; } - -.icon-align-center:before { - content: "\f037"; } - -.icon-align-right:before { - content: "\f038"; } - -.icon-align-justify:before { - content: "\f039"; } - -.icon-list:before { - content: "\f03a"; } - -.icon-dedent:before, -.icon-outdent:before { - content: "\f03b"; } - -.icon-indent:before { - content: "\f03c"; } - -.icon-video-camera:before { - content: "\f03d"; } - -.icon-photo:before, -.icon-image:before, -.icon-picture-o:before { - content: "\f03e"; } - -.icon-pencil:before { - content: "\f040"; } - -.icon-map-marker:before { - content: "\f041"; } - -.icon-adjust:before { - content: "\f042"; } - -.icon-tint:before { - content: "\f043"; } - -.icon-edit:before, -.icon-pencil-square-o:before { - content: "\f044"; } - -.icon-share-square-o:before { - content: "\f045"; } - -.icon-check-square-o:before { - content: "\f046"; } - -.icon-arrows:before { - content: "\f047"; } - -.icon-step-backward:before { - content: "\f048"; } - -.icon-fast-backward:before { - content: "\f049"; } - -.icon-backward:before { - content: "\f04a"; } - -.icon-play:before { - content: "\f04b"; } - -.icon-pause:before { - content: "\f04c"; } - -.icon-stop:before { - content: "\f04d"; } - -.icon-forward:before { - content: "\f04e"; } - -.icon-fast-forward:before { - content: "\f050"; } - -.icon-step-forward:before { - content: "\f051"; } - -.icon-eject:before { - content: "\f052"; } - -.icon-chevron-left:before { - content: "\f053"; } - -.icon-chevron-right:before { - content: "\f054"; } - -.icon-plus-circle:before { - content: "\f055"; } - -.icon-minus-circle:before { - content: "\f056"; } - -.icon-times-circle:before { - content: "\f057"; } - -.icon-check-circle:before { - content: "\f058"; } - -.icon-question-circle:before { - content: "\f059"; } - -.icon-info-circle:before { - content: "\f05a"; } - -.icon-crosshairs:before { - content: "\f05b"; } - -.icon-times-circle-o:before { - content: "\f05c"; } - -.icon-check-circle-o:before { - content: "\f05d"; } - -.icon-ban:before { - content: "\f05e"; } - -.icon-arrow-left:before { - content: "\f060"; } - -.icon-arrow-right:before { - content: "\f061"; } - -.icon-arrow-up:before { - content: "\f062"; } - -.icon-arrow-down:before { - content: "\f063"; } - -.icon-mail-forward:before, -.icon-share:before { - content: "\f064"; } - -.icon-expand:before { - content: "\f065"; } - -.icon-compress:before { - content: "\f066"; } - -.icon-plus:before { - content: "\f067"; } - -.icon-minus:before { - content: "\f068"; } - -.icon-asterisk:before { - content: "\f069"; } - -.icon-exclamation-circle:before { - content: "\f06a"; } - -.icon-gift:before { - content: "\f06b"; } - -.icon-leaf:before { - content: "\f06c"; } - -.icon-fire:before { - content: "\f06d"; } - -.icon-eye:before { - content: "\f06e"; } - -.icon-eye-slash:before { - content: "\f070"; } - -.icon-warning:before, -.icon-exclamation-triangle:before { - content: "\f071"; } - -.icon-plane:before { - content: "\f072"; } - -.icon-calendar:before { - content: "\f073"; } - -.icon-random:before { - content: "\f074"; } - -.icon-comment:before { - content: "\f075"; } - -.icon-magnet:before { - content: "\f076"; } - -.icon-chevron-up:before { - content: "\f077"; } - -.icon-chevron-down:before { - content: "\f078"; } - -.icon-retweet:before { - content: "\f079"; } - -.icon-shopping-cart:before { - content: "\f07a"; } - -.icon-folder:before { - content: "\f07b"; } - -.icon-folder-open:before { - content: "\f07c"; } - -.icon-arrows-v:before { - content: "\f07d"; } - -.icon-arrows-h:before { - content: "\f07e"; } - -.icon-bar-chart-o:before, -.icon-bar-chart:before { - content: "\f080"; } - -.icon-twitter-square:before { - content: "\f081"; } - -.icon-facebook-square:before { - content: "\f082"; } - -.icon-camera-retro:before { - content: "\f083"; } - -.icon-key:before { - content: "\f084"; } - -.icon-gears:before, -.icon-cogs:before { - content: "\f085"; } - -.icon-comments:before { - content: "\f086"; } - -.icon-thumbs-o-up:before { - content: "\f087"; } - -.icon-thumbs-o-down:before { - content: "\f088"; } - -.icon-star-half:before { - content: "\f089"; } - -.icon-heart-o:before { - content: "\f08a"; } - -.icon-sign-out:before { - content: "\f08b"; } - -.icon-linkedin-square:before { - content: "\f08c"; } - -.icon-thumb-tack:before { - content: "\f08d"; } - -.icon-external-link:before { - content: "\f08e"; } - -.icon-sign-in:before { - content: "\f090"; } - -.icon-trophy:before { - content: "\f091"; } - -.icon-github-square:before { - content: "\f092"; } - -.icon-upload:before { - content: "\f093"; } - -.icon-lemon-o:before { - content: "\f094"; } - -.icon-phone:before { - content: "\f095"; } - -.icon-square-o:before { - content: "\f096"; } - -.icon-bookmark-o:before { - content: "\f097"; } - -.icon-phone-square:before { - content: "\f098"; } - -.icon-twitter:before { - content: "\f099"; } - -.icon-facebook-f:before, -.icon-facebook:before { - content: "\f09a"; } - -.icon-github:before { - content: "\f09b"; } - -.icon-unlock:before { - content: "\f09c"; } - -.icon-credit-card:before { - content: "\f09d"; } - -.icon-rss:before { - content: "\f09e"; } - -.icon-hdd-o:before { - content: "\f0a0"; } - -.icon-bullhorn:before { - content: "\f0a1"; } - -.icon-bell:before { - content: "\f0f3"; } - -.icon-certificate:before { - content: "\f0a3"; } - -.icon-hand-o-right:before { - content: "\f0a4"; } - -.icon-hand-o-left:before { - content: "\f0a5"; } - -.icon-hand-o-up:before { - content: "\f0a6"; } - -.icon-hand-o-down:before { - content: "\f0a7"; } - -.icon-arrow-circle-left:before { - content: "\f0a8"; } - -.icon-arrow-circle-right:before { - content: "\f0a9"; } - -.icon-arrow-circle-up:before { - content: "\f0aa"; } - -.icon-arrow-circle-down:before { - content: "\f0ab"; } - -.icon-globe:before { - content: "\f0ac"; } - -.icon-wrench:before { - content: "\f0ad"; } - -.icon-tasks:before { - content: "\f0ae"; } - -.icon-filter:before { - content: "\f0b0"; } - -.icon-briefcase:before { - content: "\f0b1"; } - -.icon-arrows-alt:before { - content: "\f0b2"; } - -.icon-group:before, -.icon-users:before { - content: "\f0c0"; } - -.icon-chain:before, -.icon-link:before { - content: "\f0c1"; } - -.icon-cloud:before { - content: "\f0c2"; } - -.icon-flask:before { - content: "\f0c3"; } - -.icon-cut:before, -.icon-scissors:before { - content: "\f0c4"; } - -.icon-copy:before, -.icon-files-o:before { - content: "\f0c5"; } - -.icon-paperclip:before { - content: "\f0c6"; } - -.icon-save:before, -.icon-floppy-o:before { - content: "\f0c7"; } - -.icon-square:before { - content: "\f0c8"; } - -.icon-navicon:before, -.icon-reorder:before, -.icon-bars:before { - content: "\f0c9"; } - -.icon-list-ul:before { - content: "\f0ca"; } - -.icon-list-ol:before { - content: "\f0cb"; } - -.icon-strikethrough:before { - content: "\f0cc"; } - -.icon-underline:before { - content: "\f0cd"; } - -.icon-table:before { - content: "\f0ce"; } - -.icon-magic:before { - content: "\f0d0"; } - -.icon-truck:before { - content: "\f0d1"; } - -.icon-pinterest:before { - content: "\f0d2"; } - -.icon-pinterest-square:before { - content: "\f0d3"; } - -.icon-google-plus-square:before { - content: "\f0d4"; } - -.icon-google-plus:before { - content: "\f0d5"; } - -.icon-money:before { - content: "\f0d6"; } - -.icon-caret-down:before { - content: "\f0d7"; } - -.icon-caret-up:before { - content: "\f0d8"; } - -.icon-caret-left:before { - content: "\f0d9"; } - -.icon-caret-right:before { - content: "\f0da"; } - -.icon-columns:before { - content: "\f0db"; } - -.icon-unsorted:before, -.icon-sort:before { - content: "\f0dc"; } - -.icon-sort-down:before, -.icon-sort-desc:before { - content: "\f0dd"; } - -.icon-sort-up:before, -.icon-sort-asc:before { - content: "\f0de"; } - -.icon-envelope:before { - content: "\f0e0"; } - -.icon-linkedin:before { - content: "\f0e1"; } - -.icon-rotate-left:before, -.icon-undo:before { - content: "\f0e2"; } - -.icon-legal:before, -.icon-gavel:before { - content: "\f0e3"; } - -.icon-dashboard:before, -.icon-tachometer:before { - content: "\f0e4"; } - -.icon-comment-o:before { - content: "\f0e5"; } - -.icon-comments-o:before { - content: "\f0e6"; } - -.icon-flash:before, -.icon-bolt:before { - content: "\f0e7"; } - -.icon-sitemap:before { - content: "\f0e8"; } - -.icon-umbrella:before { - content: "\f0e9"; } - -.icon-paste:before, -.icon-clipboard:before { - content: "\f0ea"; } - -.icon-lightbulb-o:before { - content: "\f0eb"; } - -.icon-exchange:before { - content: "\f0ec"; } - -.icon-cloud-download:before { - content: "\f0ed"; } - -.icon-cloud-upload:before { - content: "\f0ee"; } - -.icon-user-md:before { - content: "\f0f0"; } - -.icon-stethoscope:before { - content: "\f0f1"; } - -.icon-suitcase:before { - content: "\f0f2"; } - -.icon-bell-o:before { - content: "\f0a2"; } - -.icon-coffee:before { - content: "\f0f4"; } - -.icon-cutlery:before { - content: "\f0f5"; } - -.icon-file-text-o:before { - content: "\f0f6"; } - -.icon-building-o:before { - content: "\f0f7"; } - -.icon-hospital-o:before { - content: "\f0f8"; } - -.icon-ambulance:before { - content: "\f0f9"; } - -.icon-medkit:before { - content: "\f0fa"; } - -.icon-fighter-jet:before { - content: "\f0fb"; } - -.icon-beer:before { - content: "\f0fc"; } - -.icon-h-square:before { - content: "\f0fd"; } - -.icon-plus-square:before { - content: "\f0fe"; } - -.icon-angle-double-left:before { - content: "\f100"; } - -.icon-angle-double-right:before { - content: "\f101"; } - -.icon-angle-double-up:before { - content: "\f102"; } - -.icon-angle-double-down:before { - content: "\f103"; } - -.icon-angle-left:before { - content: "\f104"; } - -.icon-angle-right:before { - content: "\f105"; } - -.icon-angle-up:before { - content: "\f106"; } - -.icon-angle-down:before { - content: "\f107"; } - -.icon-desktop:before { - content: "\f108"; } - -.icon-laptop:before { - content: "\f109"; } - -.icon-tablet:before { - content: "\f10a"; } - -.icon-mobile-phone:before, -.icon-mobile:before { - content: "\f10b"; } - -.icon-circle-o:before { - content: "\f10c"; } - -.icon-quote-left:before { - content: "\f10d"; } - -.icon-quote-right:before { - content: "\f10e"; } - -.icon-spinner:before { - content: "\f110"; } - -.icon-circle:before { - content: "\f111"; } - -.icon-mail-reply:before, -.icon-reply:before { - content: "\f112"; } - -.icon-github-alt:before { - content: "\f113"; } - -.icon-folder-o:before { - content: "\f114"; } - -.icon-folder-open-o:before { - content: "\f115"; } - -.icon-smile-o:before { - content: "\f118"; } - -.icon-frown-o:before { - content: "\f119"; } - -.icon-meh-o:before { - content: "\f11a"; } - -.icon-gamepad:before { - content: "\f11b"; } - -.icon-keyboard-o:before { - content: "\f11c"; } - -.icon-flag-o:before { - content: "\f11d"; } - -.icon-flag-checkered:before { - content: "\f11e"; } - -.icon-terminal:before { - content: "\f120"; } - -.icon-code:before { - content: "\f121"; } - -.icon-mail-reply-all:before, -.icon-reply-all:before { - content: "\f122"; } - -.icon-star-half-empty:before, -.icon-star-half-full:before, -.icon-star-half-o:before { - content: "\f123"; } - -.icon-location-arrow:before { - content: "\f124"; } - -.icon-crop:before { - content: "\f125"; } - -.icon-code-fork:before { - content: "\f126"; } - -.icon-unlink:before, -.icon-chain-broken:before { - content: "\f127"; } - -.icon-question:before { - content: "\f128"; } - -.icon-info:before { - content: "\f129"; } - -.icon-exclamation:before { - content: "\f12a"; } - -.icon-superscript:before { - content: "\f12b"; } - -.icon-subscript:before { - content: "\f12c"; } - -.icon-eraser:before { - content: "\f12d"; } - -.icon-puzzle-piece:before { - content: "\f12e"; } - -.icon-microphone:before { - content: "\f130"; } - -.icon-microphone-slash:before { - content: "\f131"; } - -.icon-shield:before { - content: "\f132"; } - -.icon-calendar-o:before { - content: "\f133"; } - -.icon-fire-extinguisher:before { - content: "\f134"; } - -.icon-rocket:before { - content: "\f135"; } - -.icon-maxcdn:before { - content: "\f136"; } - -.icon-chevron-circle-left:before { - content: "\f137"; } - -.icon-chevron-circle-right:before { - content: "\f138"; } - -.icon-chevron-circle-up:before { - content: "\f139"; } - -.icon-chevron-circle-down:before { - content: "\f13a"; } - -.icon-html5:before { - content: "\f13b"; } - -.icon-css3:before { - content: "\f13c"; } - -.icon-anchor:before { - content: "\f13d"; } - -.icon-unlock-alt:before { - content: "\f13e"; } - -.icon-bullseye:before { - content: "\f140"; } - -.icon-ellipsis-h:before { - content: "\f141"; } - -.icon-ellipsis-v:before { - content: "\f142"; } - -.icon-rss-square:before { - content: "\f143"; } - -.icon-play-circle:before { - content: "\f144"; } - -.icon-ticket:before { - content: "\f145"; } - -.icon-minus-square:before { - content: "\f146"; } - -.icon-minus-square-o:before { - content: "\f147"; } - -.icon-level-up:before { - content: "\f148"; } - -.icon-level-down:before { - content: "\f149"; } - -.icon-check-square:before { - content: "\f14a"; } - -.icon-pencil-square:before { - content: "\f14b"; } - -.icon-external-link-square:before { - content: "\f14c"; } - -.icon-share-square:before { - content: "\f14d"; } - -.icon-compass:before { - content: "\f14e"; } - -.icon-toggle-down:before, -.icon-caret-square-o-down:before { - content: "\f150"; } - -.icon-toggle-up:before, -.icon-caret-square-o-up:before { - content: "\f151"; } - -.icon-toggle-right:before, -.icon-caret-square-o-right:before { - content: "\f152"; } - -.icon-euro:before, -.icon-eur:before { - content: "\f153"; } - -.icon-gbp:before { - content: "\f154"; } - -.icon-dollar:before, -.icon-usd:before { - content: "\f155"; } - -.icon-rupee:before, -.icon-inr:before { - content: "\f156"; } - -.icon-cny:before, -.icon-rmb:before, -.icon-yen:before, -.icon-jpy:before { - content: "\f157"; } - -.icon-ruble:before, -.icon-rouble:before, -.icon-rub:before { - content: "\f158"; } - -.icon-won:before, -.icon-krw:before { - content: "\f159"; } - -.icon-bitcoin:before, -.icon-btc:before { - content: "\f15a"; } - -.icon-file:before { - content: "\f15b"; } - -.icon-file-text:before { - content: "\f15c"; } - -.icon-sort-alpha-asc:before { - content: "\f15d"; } - -.icon-sort-alpha-desc:before { - content: "\f15e"; } - -.icon-sort-amount-asc:before { - content: "\f160"; } - -.icon-sort-amount-desc:before { - content: "\f161"; } - -.icon-sort-numeric-asc:before { - content: "\f162"; } - -.icon-sort-numeric-desc:before { - content: "\f163"; } - -.icon-thumbs-up:before { - content: "\f164"; } - -.icon-thumbs-down:before { - content: "\f165"; } - -.icon-youtube-square:before { - content: "\f166"; } - -.icon-youtube:before { - content: "\f167"; } - -.icon-xing:before { - content: "\f168"; } - -.icon-xing-square:before { - content: "\f169"; } - -.icon-youtube-play:before { - content: "\f16a"; } - -.icon-dropbox:before { - content: "\f16b"; } - -.icon-stack-overflow:before { - content: "\f16c"; } - -.icon-instagram:before { - content: "\f16d"; } - -.icon-flickr:before { - content: "\f16e"; } - -.icon-adn:before { - content: "\f170"; } - -.icon-bitbucket:before { - content: "\f171"; } - -.icon-bitbucket-square:before { - content: "\f172"; } - -.icon-tumblr:before { - content: "\f173"; } - -.icon-tumblr-square:before { - content: "\f174"; } - -.icon-long-arrow-down:before { - content: "\f175"; } - -.icon-long-arrow-up:before { - content: "\f176"; } - -.icon-long-arrow-left:before { - content: "\f177"; } - -.icon-long-arrow-right:before { - content: "\f178"; } - -.icon-apple:before { - content: "\f179"; } - -.icon-windows:before { - content: "\f17a"; } - -.icon-android:before { - content: "\f17b"; } - -.icon-linux:before { - content: "\f17c"; } - -.icon-dribbble:before { - content: "\f17d"; } - -.icon-skype:before { - content: "\f17e"; } - -.icon-foursquare:before { - content: "\f180"; } - -.icon-trello:before { - content: "\f181"; } - -.icon-female:before { - content: "\f182"; } - -.icon-male:before { - content: "\f183"; } - -.icon-gittip:before, -.icon-gratipay:before { - content: "\f184"; } - -.icon-sun-o:before { - content: "\f185"; } - -.icon-moon-o:before { - content: "\f186"; } - -.icon-archive:before { - content: "\f187"; } - -.icon-bug:before { - content: "\f188"; } - -.icon-vk:before { - content: "\f189"; } - -.icon-weibo:before { - content: "\f18a"; } - -.icon-renren:before { - content: "\f18b"; } - -.icon-pagelines:before { - content: "\f18c"; } - -.icon-stack-exchange:before { - content: "\f18d"; } - -.icon-arrow-circle-o-right:before { - content: "\f18e"; } - -.icon-arrow-circle-o-left:before { - content: "\f190"; } - -.icon-toggle-left:before, -.icon-caret-square-o-left:before { - content: "\f191"; } - -.icon-dot-circle-o:before { - content: "\f192"; } - -.icon-wheelchair:before { - content: "\f193"; } - -.icon-vimeo-square:before { - content: "\f194"; } - -.icon-turkish-lira:before, -.icon-try:before { - content: "\f195"; } - -.icon-plus-square-o:before { - content: "\f196"; } - -.icon-space-shuttle:before { - content: "\f197"; } - -.icon-slack:before { - content: "\f198"; } - -.icon-envelope-square:before { - content: "\f199"; } - -.icon-wordpress:before { - content: "\f19a"; } - -.icon-openid:before { - content: "\f19b"; } - -.icon-institution:before, -.icon-bank:before, -.icon-university:before { - content: "\f19c"; } - -.icon-mortar-board:before, -.icon-graduation-cap:before { - content: "\f19d"; } - -.icon-yahoo:before { - content: "\f19e"; } - -.icon-google:before { - content: "\f1a0"; } - -.icon-reddit:before { - content: "\f1a1"; } - -.icon-reddit-square:before { - content: "\f1a2"; } - -.icon-stumbleupon-circle:before { - content: "\f1a3"; } - -.icon-stumbleupon:before { - content: "\f1a4"; } - -.icon-delicious:before { - content: "\f1a5"; } - -.icon-digg:before { - content: "\f1a6"; } - -.icon-pied-piper:before { - content: "\f1a7"; } - -.icon-pied-piper-alt:before { - content: "\f1a8"; } - -.icon-drupal:before { - content: "\f1a9"; } - -.icon-joomla:before { - content: "\f1aa"; } - -.icon-language:before { - content: "\f1ab"; } - -.icon-fax:before { - content: "\f1ac"; } - -.icon-building:before { - content: "\f1ad"; } - -.icon-child:before { - content: "\f1ae"; } - -.icon-paw:before { - content: "\f1b0"; } - -.icon-spoon:before { - content: "\f1b1"; } - -.icon-cube:before { - content: "\f1b2"; } - -.icon-cubes:before { - content: "\f1b3"; } - -.icon-behance:before { - content: "\f1b4"; } - -.icon-behance-square:before { - content: "\f1b5"; } - -.icon-steam:before { - content: "\f1b6"; } - -.icon-steam-square:before { - content: "\f1b7"; } - -.icon-recycle:before { - content: "\f1b8"; } - -.icon-automobile:before, -.icon-car:before { - content: "\f1b9"; } - -.icon-cab:before, -.icon-taxi:before { - content: "\f1ba"; } - -.icon-tree:before { - content: "\f1bb"; } - -.icon-spotify:before { - content: "\f1bc"; } - -.icon-deviantart:before { - content: "\f1bd"; } - -.icon-soundcloud:before { - content: "\f1be"; } - -.icon-database:before { - content: "\f1c0"; } - -.icon-file-pdf-o:before { - content: "\f1c1"; } - -.icon-file-word-o:before { - content: "\f1c2"; } - -.icon-file-excel-o:before { - content: "\f1c3"; } - -.icon-file-powerpoint-o:before { - content: "\f1c4"; } - -.icon-file-photo-o:before, -.icon-file-picture-o:before, -.icon-file-image-o:before { - content: "\f1c5"; } - -.icon-file-zip-o:before, -.icon-file-archive-o:before { - content: "\f1c6"; } - -.icon-file-sound-o:before, -.icon-file-audio-o:before { - content: "\f1c7"; } - -.icon-file-movie-o:before, -.icon-file-video-o:before { - content: "\f1c8"; } - -.icon-file-code-o:before { - content: "\f1c9"; } - -.icon-vine:before { - content: "\f1ca"; } - -.icon-codepen:before { - content: "\f1cb"; } - -.icon-jsfiddle:before { - content: "\f1cc"; } - -.icon-life-bouy:before, -.icon-life-buoy:before, -.icon-life-saver:before, -.icon-support:before, -.icon-life-ring:before { - content: "\f1cd"; } - -.icon-circle-o-notch:before { - content: "\f1ce"; } - -.icon-ra:before, -.icon-rebel:before { - content: "\f1d0"; } - -.icon-ge:before, -.icon-empire:before { - content: "\f1d1"; } - -.icon-git-square:before { - content: "\f1d2"; } - -.icon-git:before { - content: "\f1d3"; } - -.icon-hacker-news:before { - content: "\f1d4"; } - -.icon-tencent-weibo:before { - content: "\f1d5"; } - -.icon-qq:before { - content: "\f1d6"; } - -.icon-wechat:before, -.icon-weixin:before { - content: "\f1d7"; } - -.icon-send:before, -.icon-paper-plane:before { - content: "\f1d8"; } - -.icon-send-o:before, -.icon-paper-plane-o:before { - content: "\f1d9"; } - -.icon-history:before { - content: "\f1da"; } - -.icon-genderless:before, -.icon-circle-thin:before { - content: "\f1db"; } - -.icon-header:before { - content: "\f1dc"; } - -.icon-paragraph:before { - content: "\f1dd"; } - -.icon-sliders:before { - content: "\f1de"; } - -.icon-share-alt:before { - content: "\f1e0"; } - -.icon-share-alt-square:before { - content: "\f1e1"; } - -.icon-bomb:before { - content: "\f1e2"; } - -.icon-soccer-ball-o:before, -.icon-futbol-o:before { - content: "\f1e3"; } - -.icon-tty:before { - content: "\f1e4"; } - -.icon-binoculars:before { - content: "\f1e5"; } - -.icon-plug:before { - content: "\f1e6"; } - -.icon-slideshare:before { - content: "\f1e7"; } - -.icon-twitch:before { - content: "\f1e8"; } - -.icon-yelp:before { - content: "\f1e9"; } - -.icon-newspaper-o:before { - content: "\f1ea"; } - -.icon-wifi:before { - content: "\f1eb"; } - -.icon-calculator:before { - content: "\f1ec"; } - -.icon-paypal:before { - content: "\f1ed"; } - -.icon-google-wallet:before { - content: "\f1ee"; } - -.icon-cc-visa:before { - content: "\f1f0"; } - -.icon-cc-mastercard:before { - content: "\f1f1"; } - -.icon-cc-discover:before { - content: "\f1f2"; } - -.icon-cc-amex:before { - content: "\f1f3"; } - -.icon-cc-paypal:before { - content: "\f1f4"; } - -.icon-cc-stripe:before { - content: "\f1f5"; } - -.icon-bell-slash:before { - content: "\f1f6"; } - -.icon-bell-slash-o:before { - content: "\f1f7"; } - -.icon-trash:before { - content: "\f1f8"; } - -.icon-copyright:before { - content: "\f1f9"; } - -.icon-at:before { - content: "\f1fa"; } - -.icon-eyedropper:before { - content: "\f1fb"; } - -.icon-paint-brush:before { - content: "\f1fc"; } - -.icon-birthday-cake:before { - content: "\f1fd"; } - -.icon-area-chart:before { - content: "\f1fe"; } - -.icon-pie-chart:before { - content: "\f200"; } - -.icon-line-chart:before { - content: "\f201"; } - -.icon-lastfm:before { - content: "\f202"; } - -.icon-lastfm-square:before { - content: "\f203"; } - -.icon-toggle-off:before { - content: "\f204"; } - -.icon-toggle-on:before { - content: "\f205"; } - -.icon-bicycle:before { - content: "\f206"; } - -.icon-bus:before { - content: "\f207"; } - -.icon-ioxhost:before { - content: "\f208"; } - -.icon-angellist:before { - content: "\f209"; } - -.icon-cc:before { - content: "\f20a"; } - -.icon-shekel:before, -.icon-sheqel:before, -.icon-ils:before { - content: "\f20b"; } - -.icon-meanpath:before { - content: "\f20c"; } - -.icon-buysellads:before { - content: "\f20d"; } - -.icon-connectdevelop:before { - content: "\f20e"; } - -.icon-dashcube:before { - content: "\f210"; } - -.icon-forumbee:before { - content: "\f211"; } - -.icon-leanpub:before { - content: "\f212"; } - -.icon-sellsy:before { - content: "\f213"; } - -.icon-shirtsinbulk:before { - content: "\f214"; } - -.icon-simplybuilt:before { - content: "\f215"; } - -.icon-skyatlas:before { - content: "\f216"; } - -.icon-cart-plus:before { - content: "\f217"; } - -.icon-cart-arrow-down:before { - content: "\f218"; } - -.icon-diamond:before { - content: "\f219"; } - -.icon-ship:before { - content: "\f21a"; } - -.icon-user-secret:before { - content: "\f21b"; } - -.icon-motorcycle:before { - content: "\f21c"; } - -.icon-street-view:before { - content: "\f21d"; } - -.icon-heartbeat:before { - content: "\f21e"; } - -.icon-venus:before { - content: "\f221"; } - -.icon-mars:before { - content: "\f222"; } - -.icon-mercury:before { - content: "\f223"; } - -.icon-transgender:before { - content: "\f224"; } - -.icon-transgender-alt:before { - content: "\f225"; } - -.icon-venus-double:before { - content: "\f226"; } - -.icon-mars-double:before { - content: "\f227"; } - -.icon-venus-mars:before { - content: "\f228"; } - -.icon-mars-stroke:before { - content: "\f229"; } - -.icon-mars-stroke-v:before { - content: "\f22a"; } - -.icon-mars-stroke-h:before { - content: "\f22b"; } - -.icon-neuter:before { - content: "\f22c"; } - -.icon-facebook-official:before { - content: "\f230"; } - -.icon-pinterest-p:before { - content: "\f231"; } - -.icon-whatsapp:before { - content: "\f232"; } - -.icon-server:before { - content: "\f233"; } - -.icon-user-plus:before { - content: "\f234"; } - -.icon-user-times:before { - content: "\f235"; } - -.icon-hotel:before, -.icon-bed:before { - content: "\f236"; } - -.icon-viacoin:before { - content: "\f237"; } - -.icon-train:before { - content: "\f238"; } - -.icon-subway:before { - content: "\f239"; } - -.icon-medium:before { - content: "\f23a"; } - -html { - height: 100%; - font-size: 16px; } - -body { - font-family: 'Source Sans Pro', sans-serif; - line-height: 1.3333; } - -#window { - min-height: 100vh; - background: #f5f5f5; } - -.badge { - background: #216C2A; - display: inline-block; - padding: 2px; - color: white; - border-radius: 2px; } - -.credit-amount--indicator { - font-weight: bold; - color: #216C2A; } - -#main-content { - padding: 24px; - margin-top: 60px; - display: flex; - flex-direction: column; } - #main-content main { - margin-left: auto; - margin-right: auto; - max-width: 100%; } - #main-content main.main--single-column { - width: 800px; } - -main.main--refreshing:before { - position: absolute; - background: url("../img/busy.gif") no-repeat center center; - width: 30px; - height: 24px; - content: ""; - left: 50%; - margin-left: -15px; - display: inline-block; } - -.icon-fixed-width { - /* This borrowed is from a component of Font Awesome we're not using, maybe add it? */ - width: 1.28571em; - text-align: center; } - -h2 { - font-size: 1.75em; } - -h3 { - font-size: 1.4em; } - -h4 { - font-size: 1.2em; } - -h5 { - font-size: 1.1em; } - -sup, sub { - vertical-align: baseline; - position: relative; } - -sup { - top: -0.4em; } - -sub { - top: 0.4em; } - -code { - font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace; - background-color: #eee; } - -p { - margin-bottom: 0.8em; } - p:last-child { - margin-bottom: 0; } - -.hidden { - display: none; } - -.disabled { - pointer-events: none; - opacity: 0.7; } - -.truncated-text { - display: -webkit-box; - overflow: hidden; - -webkit-box-orient: vertical; } - -.busy-indicator { - background: url("../img/busy.gif") no-repeat center center; - display: inline-block; - margin: -1em 0; - min-width: 16px; - min-height: 8px; - vertical-align: middle; - padding: 0 30px; } - .busy-indicator:last-child { - padding-right: 2px; } - .busy-indicator:first-child { - padding-left: 2px; } - -/*should this be here or work this way? had to hack additional rule below*/ -.icon:only-child { - position: relative; - top: 0.16em; } - -.icon-featured > .icon { - top: 0; } - -.help { - font-size: .85em; - color: rgba(0, 0, 0, 0.6); } - -.meta { - font-size: 0.9em; - color: #505050; } - -.empty { - color: #505050; - font-style: italic; } - -/*should be redone/moved*/ -.file-list__header .busy-indicator { - float: left; - margin-top: 12px; } - -.sort-section { - display: block; - margin-bottom: 16px; - text-align: right; - line-height: 1; - font-size: 0.85em; - color: rgba(0, 0, 0, 0.6); } - -section.section-spaced { - margin-bottom: 24px; } - -.text-center { - text-align: center; } - -table.table-standard { - word-wrap: break-word; - max-width: 100%; } - table.table-standard th, table.table-standard td { - padding: 12px 8px; } - table.table-standard th { - font-weight: bold; - font-size: 0.9em; } - table.table-standard td { - vertical-align: top; } - table.table-standard thead th, table.table-standard > tr:first-child th { - vertical-align: bottom; - font-weight: bold; - font-size: 0.9em; - padding: 7px 8px 4px; - text-align: left; - border-bottom: 1px solid #e2e2e2; } - table.table-standard thead th img, table.table-standard > tr:first-child th img { - vertical-align: text-bottom; } - table.table-standard tr.thead:not(:first-child) th { - border-top: 1px solid #e2e2e2; } - table.table-standard tfoot td { - padding: 12px 8px; - font-size: .85em; } - table.table-standard tbody tr:nth-child(even):not(.odd) { - background-color: #f4f4f4; } - table.table-standard tbody tr:nth-child(odd):not(.even) { - background-color: white; } - table.table-standard tbody tr.thead { - background: none; } - table.table-standard tbody tr td { - border: 0 none; } - -table.table-stretch { - width: 100%; } - -.button-set-item { - position: relative; - display: inline-block; } - .button-set-item + .button-set-item { - margin-left: 12px; } - -.button-block, .faux-button-block { - display: inline-block; - height: 36px; - line-height: 36px; - text-decoration: none; - border: 0 none; - text-align: center; - border-radius: 2px; - text-transform: uppercase; } - .button-block .icon, .faux-button-block .icon { - top: 0em; } - .button-block .icon:first-child, .faux-button-block .icon:first-child { - padding-right: 5px; } - .button-block .icon:last-child, .faux-button-block .icon:last-child { - padding-left: 5px; } - .button-block .icon:only-child, .faux-button-block .icon:only-child { - padding-left: 0; - padding-right: 0; } - -.button-block { - cursor: pointer; } - -.button__content { - margin: 0 12px; } - -.button-primary { - color: #f0f0f0; - background-color: #155B4A; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } - .button-primary:focus { - color: white; - background-color: #125041; } - -.button-alt { - background-color: #D9D9D9; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } - -.button-text { - color: #155B4A; - cursor: pointer; - display: inline-block; } - .button-text .icon:first-child { - padding-right: 5px; } - .button-text .icon:last-child:not(:only-child) { - padding-left: 5px; } - .button-text:not(.no-underline) { - text-decoration: underline; } - .button-text:not(.no-underline) .icon { - text-decoration: none; } - .button-text:hover { - opacity: 0.7; - transition: opacity 0.225s ease; - text-decoration: underline; } - .button-text:hover .icon { - text-decoration: none; } - .button-text .button__content { - margin: 0 4px; } - -.button-text-help { - color: #aaa; - cursor: pointer; - font-size: 0.8em; } - .button-text-help .icon:first-child { - padding-right: 5px; } - .button-text-help .icon:last-child:not(:only-child) { - padding-left: 5px; } - .button-text-help:not(.no-underline) { - text-decoration: underline; } - .button-text-help:not(.no-underline) .icon { - text-decoration: none; } - .button-text-help:hover { - opacity: 0.7; - transition: opacity 0.225s ease; - text-decoration: underline; } - .button-text-help:hover .icon { - text-decoration: none; } - -.button--flat { - box-shadow: none !important; } - -.card { - margin-left: auto; - margin-right: auto; - max-width: 800px; - background: #ffffff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); - border-radius: 2px; - margin-bottom: 16px; - overflow: auto; } - -.card--obscured { - position: relative; } - -.card--obscured .card__inner { - filter: blur(20px); } - -.card__title-primary, -.card__title-identity, -.card__actions, -.card__content, -.card__subtext { - padding: 0 16px; } - -.card--small .card__title-primary, -.card--small .card__title-identity, -.card--small .card__actions, -.card--small .card__content, -.card--small .card__subtext { - padding: 0 8px; } - -.card__title-primary { - margin-top: 16px; } - -.card__title-identity { - margin-top: 8px; - margin-bottom: 8px; } - -.card__actions { - margin-top: 16px; } - -.card__actions--bottom { - margin-top: 8px; - margin-bottom: 8px; } - -.card__actions--form-submit { - margin-top: 24px; - margin-bottom: 16px; } - -.card__content { - margin-top: 16px; - margin-bottom: 16px; } - -.card__subtext { - color: #505050; - font-size: 0.82em; - margin-top: 8px; - margin-bottom: 8px; } - -.card__subtext--allow-newlines { - white-space: pre-wrap; } - -.card__subtext--two-lines { - height: 34.98579px; - /*this is so one line text still has the proper height*/ } - -.card-overlay { - position: absolute; - left: 0px; - right: 0px; - top: 0px; - bottom: 0px; - padding: 20px; - background-color: rgba(128, 128, 128, 0.8); - color: #fff; - display: flex; - align-items: center; - font-weight: 600; } - -.card__link { - display: block; } - -.card--link { - transition: transform 120ms ease-in-out; } - -.card--link:hover { - position: relative; - z-index: 1; - box-shadow: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2), 2px 3px 7px 0 rgba(0, 0, 0, 0.12); - transform: scale(1.1) translateX(10px); - transform-origin: 50% 50%; - overflow-x: visible; - overflow-y: visible; } - -.card--link:hover ~ .card--link { - transform: translateX(20px); } - -.card__media { - background-size: cover; - background-repeat: no-repeat; - background-position: 50% 50%; } - -.card__media--autothumb { - position: relative; } - -.card__media--autothumb.purple { - background-color: #9c27b0; } - -.card__media--autothumb.red { - background-color: #e53935; } - -.card__media--autothumb.pink { - background-color: #e91e63; } - -.card__media--autothumb.indigo { - background-color: #3f51b5; } - -.card__media--autothumb.blue { - background-color: #2196f3; } - -.card__media--autothumb.light-blue { - background-color: #039be5; } - -.card__media--autothumb.cyan { - background-color: #00acc1; } - -.card__media--autothumb.teal { - background-color: #009688; } - -.card__media--autothumb.green { - background-color: #43a047; } - -.card__media--autothumb.yellow { - background-color: #ffeb3b; } - -.card__media--autothumb.orange { - background-color: #ffa726; } - -.card__media--autothumb .card__autothumb__text { - font-size: 2.0em; - width: 100%; - color: #ffffff; - text-align: center; - position: absolute; - top: 36%; } - -.card--small { - width: 240px; - overflow-x: hidden; - white-space: normal; } - -.card--small .card__media { - height: 135px; } - -.card--form { - width: 362px; } - -.card__subtitle { - color: rgba(0, 0, 0, 0.6); - font-size: 0.85em; - line-height: 1.56859; } - -.card-series-submit { - margin-left: auto; - margin-right: auto; - max-width: 800px; - padding: 12px; } - -.card-row + .card-row { - margin-top: 8px; } - -.card-row__items { - width: 100%; - overflow: hidden; - /*hacky way to give space for hover */ - padding-top: 20px; - margin-top: -20px; - padding-right: 30px; - margin-right: -30px; } - .card-row__items > .card { - vertical-align: top; - display: inline-block; } - .card-row__items > .card + .card { - margin-left: 8px; } - -.card-row--small { - overflow: hidden; - white-space: nowrap; - /*hacky way to give space for hover */ - padding-right: 30px; } - -.card-row__header { - margin-bottom: 8px; } - -.card-row__scrollhouse { - position: relative; } - -.card-row__nav { - position: absolute; - padding: 0 16px; - height: 100%; - top: 4px; } - -.card-row__nav .card-row__scroll-button { - background: #ffffff; - color: rgba(0, 0, 0, 0.6); - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); - padding: 24px 12px; - position: absolute; - cursor: pointer; - left: 0; - top: 36%; - z-index: 2; - opacity: 0.8; - transition: transform 60ms ease-in-out; } - .card-row__nav .card-row__scroll-button:hover { - opacity: 1.0; - transform: scale(1.21); } - -.card-row__nav--left { - left: 0; } - -.card-row__nav--right { - right: -30px; } - -.card__icon-featured-content { - color: orangered; } - -.file-actions { - line-height: 36px; - min-height: 36px; } - -.file-actions__download-status-bar .button__content, .file-actions__download-status-bar-overlay .button__content { - margin: 0 4px; } - -.file-actions__download-status-bar { - position: relative; - color: #444; } - -.file-actions__download-status-bar-overlay { - background: #444; - color: white; - position: absolute; - white-space: nowrap; - overflow: hidden; - z-index: 1; - top: 0px; - left: 0px; } - -.file-selector__choose-button { - font-size: 13px; } - -.file-selector__path { - font-size: 14px; } - -.file-tile__row { - overflow: hidden; - height: 144px; } - .file-tile__row .credit-amount { - float: right; } - .file-tile__row .icon-featured { - float: right; } - .file-tile__row .card__media { - height: 144px; - max-width: 144px; - width: 144px; - margin-right: 12px; - float: left; } - .file-tile__row .file-tile__content { - padding-top: 8px; - margin-left: 156px; } - .file-tile__row .card__title-primary { - margin-top: 0; } - -.form-row-submit { - margin-top: 24px; } - -.form-row-submit--with-footer { - margin-bottom: 24px; } - -.form-row__label-row { - margin-top: 20px; - margin-bottom: 4px; - line-height: 1; - font-size: 14.4px; } - -.form-row__label-row--prefix { - float: left; - margin-right: 5px; } - -input[type="text"].input-copyable { - border: 1px solid rgba(160, 160, 160, 0.5); - line-height: 1; - padding-top: 8px; - padding-bottom: 8px; - width: 330px; - padding-left: 5px; - padding-right: 5px; - width: 100%; } - input[type="text"].input-copyable:focus { - border-color: black; } - -.form-field { - display: inline-block; } - .form-field input[type="checkbox"], - .form-field input[type="radio"] { - cursor: pointer; } - .form-field select { - transition: outline 0.225s ease; - cursor: pointer; - box-sizing: border-box; - padding-left: 5px; - padding-right: 5px; - height: 24px; } - .form-field select:focus { - outline: 2px solid #155B4A; } - .form-field textarea, - .form-field input[type="text"], - .form-field input[type="password"], - .form-field input[type="email"], - .form-field input[type="number"], - .form-field input[type="search"], - .form-field input[type="date"] { - transition: all 0.225s ease; - cursor: pointer; - padding-left: 1px; - padding-right: 1px; - box-sizing: border-box; - -webkit-appearance: none; } - .form-field textarea::-webkit-input-placeholder, - .form-field input[type="text"]::-webkit-input-placeholder, - .form-field input[type="password"]::-webkit-input-placeholder, - .form-field input[type="email"]::-webkit-input-placeholder, - .form-field input[type="number"]::-webkit-input-placeholder, - .form-field input[type="search"]::-webkit-input-placeholder, - .form-field input[type="date"]::-webkit-input-placeholder { - color: #999999; } - .form-field textarea:-moz-placeholder, - .form-field input[type="text"]:-moz-placeholder, - .form-field input[type="password"]:-moz-placeholder, - .form-field input[type="email"]:-moz-placeholder, - .form-field input[type="number"]:-moz-placeholder, - .form-field input[type="search"]:-moz-placeholder, - .form-field input[type="date"]:-moz-placeholder { - color: #999999; } - .form-field textarea:-ms-input-placeholder, - .form-field input[type="text"]:-ms-input-placeholder, - .form-field input[type="password"]:-ms-input-placeholder, - .form-field input[type="email"]:-ms-input-placeholder, - .form-field input[type="number"]:-ms-input-placeholder, - .form-field input[type="search"]:-ms-input-placeholder, - .form-field input[type="date"]:-ms-input-placeholder { - color: #999999; } - .form-field textarea[readonly], - .form-field input[type="text"][readonly], - .form-field input[type="password"][readonly], - .form-field input[type="email"][readonly], - .form-field input[type="number"][readonly], - .form-field input[type="search"][readonly], - .form-field input[type="date"][readonly] { - background-color: #bbb; } - .form-field input[type="text"], - .form-field input[type="password"], - .form-field input[type="email"], - .form-field input[type="number"], - .form-field input[type="search"], - .form-field input[type="date"] { - border-bottom: 2px solid rgba(160, 160, 160, 0.5); - line-height: 1; - padding-top: 8px; - padding-bottom: 8px; } - .form-field input[type="text"].form-field__input--error, - .form-field input[type="password"].form-field__input--error, - .form-field input[type="email"].form-field__input--error, - .form-field input[type="number"].form-field__input--error, - .form-field input[type="search"].form-field__input--error, - .form-field input[type="date"].form-field__input--error { - border-color: #a94442; } - .form-field input[type="text"].form-field__input--inline, - .form-field input[type="password"].form-field__input--inline, - .form-field input[type="email"].form-field__input--inline, - .form-field input[type="number"].form-field__input--inline, - .form-field input[type="search"].form-field__input--inline, - .form-field input[type="date"].form-field__input--inline { - padding-top: 0; - padding-bottom: 0; - border-bottom-width: 1px; - margin-left: 8px; - margin-right: 8px; } - .form-field textarea:focus, - .form-field input[type="text"]:focus, - .form-field input[type="password"]:focus, - .form-field input[type="email"]:focus, - .form-field input[type="number"]:focus, - .form-field input[type="search"]:focus, - .form-field input[type="date"]:focus { - border-color: #155B4A; } - .form-field textarea { - padding: 2px; - border: 2px solid rgba(160, 160, 160, 0.5); } - -.form-field--SimpleMDE { - display: block; } - -.form-field__label[for] { - cursor: pointer; } - -.form-field__label > input[type="checkbox"], .form-field__label input[type="radio"] { - margin-right: 6px; } - -.form-field__label--error { - color: #a94442; } - -.form-field__input-text { - width: 330px; } - -.form-field__prefix { - margin-right: 4px; } - -.form-field__postfix { - margin-left: 4px; } - -.form-field__input-number { - width: 70px; - text-align: right; } - -.form-field--textarea { - width: 100%; } - -.form-field__input-textarea { - width: 100%; } - -.form-field__error, .form-field__helper { - margin-top: 8px; - font-size: 0.8em; - transition: opacity 0.225s ease; } - -.form-field__error { - color: #a94442; } - -.form-field__helper { - color: rgba(0, 0, 0, 0.6); } - -.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll { - height: auto; } - -#header { - color: #666; - background: #fff; - display: flex; - position: fixed; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); - top: 0; - left: 0; - width: 100%; - z-index: 3; - padding: 12px; - box-sizing: border-box; } - -.header__item { - flex: 0 0 content; - padding-left: 6px; - padding-right: 6px; } - -.header__item--wunderbar { - flex-grow: 1; } - -.wunderbar { - position: relative; } - .wunderbar .icon { - position: absolute; - left: 10px; - top: 8px; } - -.wunderbar--active .icon-search { - color: #155B4A; } - -.wunderbar__input { - background: rgba(255, 255, 255, 0.7); - width: 100%; - color: #666; - height: 36px; - line-height: 36px; - padding-left: 38px; - padding-right: 5px; - border: 1px solid #000; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - -ms-border-radius: 2px; - border-radius: 2px; - border: 1px solid #ccc; } - .wunderbar__input:focus { - color: #333333; - box-shadow: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2), 2px 3px 7px 0 rgba(0, 0, 0, 0.12); - border-color: #155B4A; } - -nav.sub-header { - text-transform: uppercase; - padding: 0 0 24px; - max-width: 800px; - margin-left: auto; - margin-right: auto; } - nav.sub-header > a { - display: inline-block; - margin: 0 15px; - padding: 0 5px; - line-height: 34px; - color: #666; } - nav.sub-header > a:first-child { - margin-left: 0; } - nav.sub-header > a:last-child { - margin-right: 0; } - nav.sub-header > a.sub-header-selected { - border-bottom: 2px solid #333333; - color: #333333; } - nav.sub-header > a:hover { - color: #333333; } - -.menu-container { - display: inline-block; } - -.menu { - position: absolute; - white-space: nowrap; - background-color: white; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); - border-radius: 2px; - padding-top: 4.8px 0px; - z-index: 1; } - -.menu__menu-item { - display: block; - padding: 6px 12px; } - .menu__menu-item:hover { - background: #D9D9D9; } - -.tooltip { - position: relative; } - -.tooltip__link { - color: #155B4A; - cursor: pointer; } - .tooltip__link .icon:first-child { - padding-right: 5px; } - .tooltip__link .icon:last-child:not(:only-child) { - padding-left: 5px; } - .tooltip__link:not(.no-underline) { - text-decoration: underline; } - .tooltip__link:not(.no-underline) .icon { - text-decoration: none; } - .tooltip__link:hover { - opacity: 0.7; - transition: opacity 0.225s ease; - text-decoration: underline; } - .tooltip__link:hover .icon { - text-decoration: none; } - -.tooltip__body { - position: absolute; - z-index: 1; - left: 50%; - margin-left: -150px; - white-space: normal; - box-sizing: border-box; - padding: 12px; - width: 300px; - border: 1px solid #aaa; - color: #000; - background-color: #ffffff; - font-size: 14px; - line-height: 1.3333; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } - -.tooltip--header .tooltip__link { - color: #aaa; - cursor: pointer; - font-size: 12px; - margin-left: 12px; - vertical-align: middle; } - .tooltip--header .tooltip__link .icon:first-child { - padding-right: 5px; } - .tooltip--header .tooltip__link .icon:last-child:not(:only-child) { - padding-left: 5px; } - .tooltip--header .tooltip__link:not(.no-underline) { - text-decoration: underline; } - .tooltip--header .tooltip__link:not(.no-underline) .icon { - text-decoration: none; } - .tooltip--header .tooltip__link:hover { - opacity: 0.7; - transition: opacity 0.225s ease; - text-decoration: underline; } - .tooltip--header .tooltip__link:hover .icon { - text-decoration: none; } - -.load-screen { - color: white; - background: #155B4A; - background-size: cover; - min-height: 100vh; - min-width: 100vw; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; } - -.load-screen__message { - margin-top: 24px; - width: 325px; - text-align: center; } - -.load-screen__details { - color: #c3c3c3; } - -.load-screen__details--warning { - color: white; } - -.load-screen__cancel-link { - color: white; } - -.channel-indicator__icon--invalid { - color: #a94442; } - -.notice { - padding: 10px 20px; - border: 1px solid #000; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - border-radius: 5px; - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; } - -.notice--error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; } - -.modal-overlay, .error-modal-overlay { - position: fixed; - display: flex; - justify-content: center; - align-items: center; - top: 0px; - left: 0px; - right: 0px; - bottom: 0px; - background-color: rgba(255, 255, 255, 0.74902); - z-index: 9999; } - -.modal-overlay--clear { - background-color: transparent; } - -.modal { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border: 1px solid #cccccc; - background: white; - overflow: auto; - border-radius: 4px; - padding: 24px; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); - max-width: 400px; - word-break: break-word; } - -.modal__header { - margin-bottom: 16px; - text-align: center; } - -.modal__buttons { - display: flex; - flex-direction: row; - justify-content: center; - margin-top: 16px; } - -.modal__button { - margin: 0px 6px; } - -.error-modal-overlay { - background: rgba(0, 0, 0, 0.88); } - -.error-modal__content { - display: flex; - padding: 0px 8px 10px 10px; } - -.error-modal__warning-symbol { - margin-top: 6px; - margin-right: 7px; } - -.download-started-modal__file-path { - word-break: break-all; } - -.error-modal { - max-width: none; - width: 400px; } - -.error-modal__error-list { - /*shitty hack/temp fix for long errors making modals unusable*/ - border: 1px solid #eee; - padding: 8px; - list-style: none; - max-height: 400px; - max-width: 400px; - overflow-y: hidden; } - -.snack-bar { - line-height: 36px; - padding: 6px 24px; - position: fixed; - top: 24px; - left: 0; - right: 0; - margin-left: auto; - margin-right: auto; - min-width: 300px; - max-width: 500px; - background: rgba(32, 32, 32, 0.9); - color: #f0f0f0; - display: flex; - justify-content: space-between; - align-items: center; - border-radius: 2px; - transition: all 0.225s ease; - z-index: 10000; - /*hack to get it over react modal */ } - -.snack-bar__action { - display: inline-block; - text-transform: uppercase; - color: #7df2d6; - margin: 0px 0px 0px 24px; - min-width: min-content; } - .snack-bar__action:hover { - text-decoration: underline; } - -video { - object-fit: contain; - box-sizing: border-box; - max-height: 100%; - max-width: 100%; - background-size: contain; - background-position: center center; - background-repeat: no-repeat; } - -.video { - background: #000; - color: white; } - -.video-embedded { - max-width: 800px; - max-height: 450px; - height: 450px; - position: relative; } - .video-embedded video { - height: 100%; - position: absolute; - left: 0; - top: 0; } - .video-embedded.video--hidden { - height: 450px; } - .video-embedded.video--active { - /*background: none;*/ } - -.video--obscured .video__cover { - position: relative; - filter: blur(20px); } - -.video__loading-screen { - height: 100%; - display: flex; - justify-content: center; - align-items: center; } - -.video__loading-spinner { - position: relative; - width: 11em; - height: 11em; - margin: 20px auto; - font-size: 3px; - border-radius: 50%; - background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 50%); - animation: spin 1.4s infinite linear; - transform: translateZ(0); } - -@keyframes spin { - from { - transform: rotate(0deg); } - to { - transform: rotate(360deg); } } - .video__loading-spinner:before, .video__loading-spinner:after { - content: ''; - position: absolute; - top: 0; - left: 0; } - .video__loading-spinner:before { - width: 50%; - height: 50%; - background: #ffffff; - border-radius: 100% 0 0 0; } - .video__loading-spinner:after { - height: 75%; - width: 75%; - margin: auto; - bottom: 0; - right: 0; - background: black; - border-radius: 50%; } - -.video__loading-status { - padding-top: 20px; - color: white; } - -.video__cover { - text-align: center; - height: 100%; - width: 100%; - background-size: auto 100%; - background-position: center center; - background-repeat: no-repeat; - position: relative; } - .video__cover .video__play-button { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - -webkit-box-align: center; - -moz-box-align: center; - -ms-flex-align: center; - -webkit-align-items: center; - align-items: center; - -webkit-box-pack: center; - -moz-box-pack: center; - -ms-flex-pack: center; - -webkit-justify-content: center; - justify-content: center; } - -.video__play-button { - position: absolute; - width: 100%; - height: 100%; - cursor: pointer; - display: none; - font-size: 72px; - color: white; - z-index: 1; - background: rgba(32, 32, 32, 0.9); - opacity: 0.6; - left: 0; - top: 0; } - .video__play-button:hover { - opacity: 1; - transition: opacity 0.225s ease; } - -.pagination { - display: block; - padding: 0; - margin: 0 auto; - text-align: center; } - -.pagination__item { - display: inline-block; - line-height: 36px; - height: 36px; - border-radius: 2px; } - .pagination__item:not(.pagination__item--selected):hover { - background: rgba(0, 0, 0, 0.2); } - .pagination__item:not(.pagination__item--selected):hover > a { - cursor: hand; } - .pagination__item > a { - display: inline-block; - padding: 0 16px; } - -.pagination__item--previous, .pagination__item--next { - font-size: 1.2em; } - -.pagination__item--selected { - color: white; - background: #155B4A; } - -.developer-page__custom-lighthouse-servers { - font: 0.8em monospace; - width: 30em; - height: 10em; } - -.reward-page__details { - background-color: #f9f9f9; } - -.show-page-media { - text-align: center; - margin-bottom: 24px; } - .show-page-media img { - max-width: 100%; } - .show-page-media iframe { - width: 100%; - min-height: 500px; } From 01e82bba1c3d15e0af087122f2cb8c7c0cd40bd1 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 20:04:25 -0600 Subject: [PATCH 024/132] remove external theme dependency --- app/package.json | 1 - app/yarn.lock | 4 ---- 2 files changed, 5 deletions(-) diff --git a/app/package.json b/app/package.json index 39758862d..0c00d98da 100644 --- a/app/package.json +++ b/app/package.json @@ -12,7 +12,6 @@ "install": "^0.8.7", "jayson": "^2.0.2", "keytar": "^4.0.3", - "lbry-dark-theme": "https://github.com/btzr-io/lbry-dark-theme", "npm": "^4.2.0", "semver": "^5.3.0", "tree-kill": "^1.1.0" diff --git a/app/yarn.lock b/app/yarn.lock index 341eeb5dc..22a12a134 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -876,10 +876,6 @@ lazy-req@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4" -"lbry-dark-theme@https://github.com/btzr-io/lbry-dark-theme": - version "2.0.0" - resolved "https://github.com/btzr-io/lbry-dark-theme#5ce4d2ceff67d62fde2eea307be728795b8b8c2f" - lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" From 02091861aff94b18baceeb2a5887f6a9e2acbd44 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 20:12:37 -0600 Subject: [PATCH 025/132] revert build --- build/build.sh | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/build/build.sh b/build/build.sh index 6ea63e000..c0e60e79c 100755 --- a/build/build.sh +++ b/build/build.sh @@ -63,22 +63,9 @@ yarn install yarn install npm rebuild node-sass node extractLocals.js - node_modules/.bin/node-sass --sourcemap=none scss/all.scss dist/themes/light.css + node_modules/.bin/node-sass --output dist/css --sourcemap=none scss/ node_modules/.bin/webpack - cp -r ./dist/ "$ROOT/app" -) - - - -#################### -# DARK-THEME # -################### - -( - cd "$ROOT/app/" - yarn add https://github.com/btzr-io/lbry-dark-theme --production - cd "./node_modules/lbry-dark-theme/dist/" - cp -r dark.css "$ROOT/app/dist/themes" + cp -r dist/* "$ROOT/app/dist/" ) @@ -93,7 +80,8 @@ else OSNAME="linux" fi 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)") +DAEMON_URL=$(echo ${DAEMON_URL_TEMPLATE//DAEMONVER/$DAEMON_VER} | sed "s/OSNAME/$OSNAME/g") wget --quiet "$DAEMON_URL" -O "$BUILD_DIR/daemon.zip" unzip "$BUILD_DIR/daemon.zip" -d "$ROOT/app/dist/" rm "$BUILD_DIR/daemon.zip" From fa1ba091a386e257e95506650a1ed35c4fb5d19e Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 20:18:55 -0600 Subject: [PATCH 026/132] revert ui/watch.sh --- ui/watch.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/watch.sh b/ui/watch.sh index b3d0e67ab..6a60eb10c 100755 --- a/ui/watch.sh +++ b/ui/watch.sh @@ -18,8 +18,8 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" fi # run sass once without --watch to force update. then run with --watch to keep watching - node_modules/.bin/node-sass --sourcemap=none $DIR/scss/all.scss $DIR/../app/dist/themes/light.css - node_modules/.bin/node-sass --sourcemap=none --watch $DIR/scss/all.scss $DIR/../app/dist/themes/light.css & + node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none $DIR/scss/ + node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none --watch $DIR/scss/ & node_modules/.bin/webpack --config webpack.dev.config.js --progress --colors --watch ) From f5e69c57d2f528a8191536eee82f5af4144cf82a Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 20:24:53 -0600 Subject: [PATCH 027/132] load all.css from index.html --- ui/dist/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/dist/index.html b/ui/dist/index.html index 65372000d..d951dddd1 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -6,7 +6,7 @@ - + From a655bdd1d65c6ee52abbf6a038a8710d05dbf282 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 23:03:15 -0600 Subject: [PATCH 028/132] init css vars implementation --- ui/scss/_global.scss | 74 +++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/ui/scss/_global.scss b/ui/scss/_global.scss index b554b77a1..d9ffa3949 100644 --- a/ui/scss/_global.scss +++ b/ui/scss/_global.scss @@ -1,46 +1,50 @@ @charset "UTF-8"; -$spacing-vertical: 24px; +:root { -$padding-button: 12px; -$padding-text-link: 4px; + --spacing-vertical: 24px; -$color-primary: #155B4A; -$color-primary-light: saturate(lighten($color-primary, 50%), 20%); -$color-light-alt: hsl(hue($color-primary), 15, 85); -$color-text-dark: #000; -$color-black-transparent: rgba(32,32,32,0.9); -$color-help: rgba(0,0,0,.6); -$color-notice: #8a6d3b; -$color-error: #a94442; -$color-load-screen-text: #c3c3c3; -$color-canvas: #f5f5f5; -$color-bg: #ffffff; -$color-bg-alt: #D9D9D9; -$color-money: #216C2A; -$color-meta-light: #505050; -$color-form-border: rgba(160,160,160,.5); + --padding-button: 12px; + --padding-text-link: 4px; -$font-size: 16px; -$font-line-height: 1.3333; + --color-primary: #155B4A; + /* --color-primary-light: saturate(lighten(--color-primary, 50%), 20%); */ + /* --color-light-alt: hsl(hue(--color-primary), 15, 85); */ + --color-text-dark: #000; + --color-black-transparent: rgba(32,32,32,0.9); + --color-help: rgba(0,0,0,.6); + --color-notice: #8a6d3b; + --color-error: #a94442; + --color-load-screen-text: #c3c3c3; + --color-canvas: #f5f5f5; + --color-bg: #ffffff; + --color-bg-alt: #D9D9D9; + --color-money: #216C2A; + --color-meta-light: #505050; + --color-form-border: rgba(160,160,160,.5); -$mobile-width-threshold: 801px; -$max-content-width: 1000px; -$max-text-width: 660px; + --font-size: 16px; + --font-line-height: 1.3333; -$width-page-constrained: 800px; -$width-input-text: 330px; + --mobile-width-threshold: 801px; + --max-content-width: 1000px; + --max-text-width: 660px; -$height-button: $spacing-vertical * 1.5; -$height-header: $spacing-vertical * 2.5; -$height-video-embedded: $width-page-constrained * 9 / 16; + --width-page-constrained: 800px; + --width-input-text: 330px; -$box-shadow-layer: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); -$box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); + --height-button: --spacing-vertical * 1.5; + --height-header: --spacing-vertical * 2.5; + --height-video-embedded: --width-page-constrained * 9 / 16; -$transition-standard: .225s ease; + --box-shadow-layer: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); + --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); -$blur-intensity-nsfw: 20px; + --transition-standard: .225s ease; + + --blur-intensity-nsfw: 20px; + +} @mixin clearfix() { @@ -163,7 +167,7 @@ $blur-intensity-nsfw: 20px; overflow:hidden; } -@mixin text-link($color: $color-primary, $hover-opacity: 0.70) { +@mixin text-link($color: var(--color-primary), $hover-opacity: 0.70) { .icon { &:first-child { @@ -183,7 +187,7 @@ $blur-intensity-nsfw: 20px; &:hover { opacity: $hover-opacity; - transition: opacity $transition-standard; + transition: opacity var(--transition-standard); text-decoration: underline; .icon { text-decoration: none; @@ -192,4 +196,4 @@ $blur-intensity-nsfw: 20px; color: $color; cursor: pointer; -} \ No newline at end of file +} From 71ad127f0e9cfe91ab9102b4de1abe4f2451d998 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 12 Aug 2017 23:37:33 -0600 Subject: [PATCH 029/132] move vars -> _vars.scss --- ui/scss/_global.scss | 46 -------------------------------------------- ui/scss/_vars.scss | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 46 deletions(-) create mode 100644 ui/scss/_vars.scss diff --git a/ui/scss/_global.scss b/ui/scss/_global.scss index d9ffa3949..b2ccb4231 100644 --- a/ui/scss/_global.scss +++ b/ui/scss/_global.scss @@ -1,51 +1,5 @@ @charset "UTF-8"; -:root { - - --spacing-vertical: 24px; - - --padding-button: 12px; - --padding-text-link: 4px; - - --color-primary: #155B4A; - /* --color-primary-light: saturate(lighten(--color-primary, 50%), 20%); */ - /* --color-light-alt: hsl(hue(--color-primary), 15, 85); */ - --color-text-dark: #000; - --color-black-transparent: rgba(32,32,32,0.9); - --color-help: rgba(0,0,0,.6); - --color-notice: #8a6d3b; - --color-error: #a94442; - --color-load-screen-text: #c3c3c3; - --color-canvas: #f5f5f5; - --color-bg: #ffffff; - --color-bg-alt: #D9D9D9; - --color-money: #216C2A; - --color-meta-light: #505050; - --color-form-border: rgba(160,160,160,.5); - - --font-size: 16px; - --font-line-height: 1.3333; - - --mobile-width-threshold: 801px; - --max-content-width: 1000px; - --max-text-width: 660px; - - --width-page-constrained: 800px; - --width-input-text: 330px; - - --height-button: --spacing-vertical * 1.5; - --height-header: --spacing-vertical * 2.5; - --height-video-embedded: --width-page-constrained * 9 / 16; - - --box-shadow-layer: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); - --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); - - --transition-standard: .225s ease; - - --blur-intensity-nsfw: 20px; - -} - @mixin clearfix() { &:before, &:after diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss new file mode 100644 index 000000000..83b8fcc91 --- /dev/null +++ b/ui/scss/_vars.scss @@ -0,0 +1,46 @@ +:root { + + --spacing-vertical: 24px; + --padding-button: 12px; + --padding-text-link: 4px; + + /* Colors */ + --color-primary: #155B4A; + --color-primary-light: #155B4A; + --color-light-alt: #155B4A; + --color-text-dark: #000; + --color-black-transparent: rgba(32,32,32,0.9); + --color-help: rgba(0,0,0,.6); + --color-notice: #8a6d3b; + --color-error: #a94442; + --color-load-screen-text: #c3c3c3; + --color-canvas: #f5f5f5; + --color-bg: #ffffff; + --color-bg-alt: #D9D9D9; + --color-money: #216C2A; + --color-meta-light: #505050; + --color-form-border: rgba(160,160,160,.5); + + /* Font */ + --font-size: 16px; + --font-line-height: 1.3333; + + --mobile-width-threshold: 801px; + --max-content-width: 1000px; + --max-text-width: 660px; + + --width-page-constrained: 800px; + --width-input-text: 330px; + + --height-button: --spacing-vertical * 1.5; + --height-header: --spacing-vertical * 2.5; + --height-video-embedded: --width-page-constrained * 9 / 16; + + --box-shadow-layer: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); + --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); + + --transition-standard: .225s ease; + + --blur-intensity-nsfw: 20px; + +} From de4057860867125d6dc9aa7d23beee4d07a4d848 Mon Sep 17 00:00:00 2001 From: hackrush Date: Mon, 14 Aug 2017 15:13:40 +0530 Subject: [PATCH 030/132] Passing params directly w/o using redux store --- ui/js/actions/claims.js | 28 ++++--------------------- ui/js/component/tipLink/index.js | 10 ++------- ui/js/component/tipLink/view.jsx | 4 +--- ui/js/constants/action_types.js | 2 -- ui/js/reducers/claims.js | 35 ++------------------------------ ui/js/selectors/claims.js | 10 --------- 6 files changed, 9 insertions(+), 80 deletions(-) diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js index 5d72a9f5f..46557da57 100644 --- a/ui/js/actions/claims.js +++ b/ui/js/actions/claims.js @@ -1,21 +1,15 @@ import lbry from "lbry"; import { selectBalance } from "selectors/wallet"; -import { - selectSupportTransaction, - selectSupportTransactionAmount, -} from "selectors/claims"; import { doOpenModal, doShowSnackBar } from "actions/app"; import * as types from "constants/action_types"; import * as modals from "constants/modal_types"; -export function doSendSupport() { +export function doSendSupport(amount, claim_id) { return function(dispatch, getState) { const state = getState(); - const supportTx = selectSupportTransaction(state); const balance = selectBalance(state); - const amount = selectSupportTransactionAmount(state); - if (balance - amount < 1) { + if (balance - amount <= 0) { return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); } @@ -54,23 +48,9 @@ export function doSendSupport() { lbry .claim_send_tip({ - claim_id: supportTx.claim_id, - amount: supportTx.amount, + claim_id: claim_id, + amount: amount, }) .then(successCallback, errorCallback); }; } - -export function doSetSupportAmount(amount) { - return { - type: types.SET_SUPPORT_AMOUNT, - data: { amount }, - }; -} - -export function doSetSupportClaimID(claim_id) { - return { - type: types.SET_SUPPORT_CLAIMID, - data: { claim_id }, - }; -} diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js index b969bfb57..b43f225ac 100644 --- a/ui/js/component/tipLink/index.js +++ b/ui/js/component/tipLink/index.js @@ -1,18 +1,12 @@ import React from "react"; import { connect } from "react-redux"; -import { - doSendSupport, - doSetSupportAmount, - doSetSupportClaimID, -} from "actions/claims"; +import { doSendSupport } from "actions/claims"; import TipLink from "./view"; const select = state => ({}); const perform = dispatch => ({ - sendSupport: () => dispatch(doSendSupport()), - setAmount: amount => dispatch(doSetSupportAmount(amount)), - setClaimID: claim_id => dispatch(doSetSupportClaimID(claim_id)), + sendSupport: (amount, claim_id) => dispatch(doSendSupport(amount, claim_id)), }); export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 295afc3db..432e24004 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -21,9 +21,7 @@ class TipLink extends React.PureComponent { let claim_id = this.props.claim_id; let amount = this.state.feeAmount; - this.props.setClaimID(claim_id); - this.props.setAmount(amount); - this.props.sendSupport(); + this.props.sendSupport(amount, claim_id); this.props.onTipHide(); } diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 8d53d0806..6333ab11c 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -115,8 +115,6 @@ export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; // Supports -export const SET_SUPPORT_CLAIMID = "SET_SUPPORT_CLAIMID"; -export const SET_SUPPORT_AMOUNT = "SET_SUPPORT_AMOUNT"; export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js index 8d913438d..46a0db309 100644 --- a/ui/js/reducers/claims.js +++ b/ui/js/reducers/claims.js @@ -2,14 +2,7 @@ import * as types from "constants/action_types"; import lbryuri from "lbryuri"; const reducers = {}; -const buildSupportTransaction = () => ({ - claim_id: undefined, - amount: undefined, -}); - -const defaultState = { - supportTransaction: buildSupportTransaction(), -}; +const defaultState = {}; reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) { const { uri, certificate, claim } = action.data; @@ -197,28 +190,6 @@ reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) { }); }; -reducers[types.SET_SUPPORT_AMOUNT] = function(state, action) { - const oldDraft = state.supportTransaction; - const newDraft = Object.assign({}, oldDraft, { - amount: parseFloat(action.data.amount), - }); - - return Object.assign({}, state, { - supportTransaction: newDraft, - }); -}; - -reducers[types.SET_SUPPORT_CLAIMID] = function(state, action) { - const oldDraft = state.supportTransaction; - const newDraft = Object.assign({}, oldDraft, { - claim_id: action.data.claim_id, - }); - - return Object.assign({}, state, { - supportTransaction: newDraft, - }); -}; - reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { const newSupportTransaction = Object.assign({}, state.supportTransaction, { sendingSupport: true, @@ -230,9 +201,7 @@ reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { }; reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { - return Object.assign({}, state, { - supportTransaction: buildSupportTransaction(), - }); + return Object.assign({}, state); }; reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 4676eb77a..2c4b4b511 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -215,13 +215,3 @@ export const selectMyChannelClaims = createSelector( return claims; } ); - -export const selectSupportTransaction = createSelector( - _selectState, - state => state.supportTransaction || {} -); - -export const selectSupportTransactionAmount = createSelector( - selectSupportTransaction, - supportTxAmount => supportTxAmount.amount -); From 9bf654e05fcc1e85f9946cc1abdb43a5c91fd5ee Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 17 Aug 2017 23:37:35 -0600 Subject: [PATCH 031/132] init migration to css vars --- ui/scss/_global.scss | 3 + ui/scss/_gui.scss | 20 +++--- ui/scss/_vars.scss | 72 +++++++++++++------- ui/scss/component/_button.scss | 28 ++++---- ui/scss/component/_card.scss | 80 +++++++++++------------ ui/scss/component/_channel-indicator.scss | 2 +- ui/scss/component/_file-actions.scss | 8 +-- ui/scss/component/_form-field.scss | 31 ++++----- ui/scss/component/_header.scss | 22 +++---- ui/scss/component/_load-screen.scss | 4 +- ui/scss/component/_menu.scss | 6 +- ui/scss/component/_modal.scss | 4 +- ui/scss/component/_pagination.scss | 2 +- ui/scss/component/_snack-bar.scss | 6 +- ui/scss/component/_tooltip.scss | 23 +++---- ui/scss/component/_video.scss | 7 +- ui/scss/page/_reward.scss | 4 +- 17 files changed, 171 insertions(+), 151 deletions(-) diff --git a/ui/scss/_global.scss b/ui/scss/_global.scss index b2ccb4231..5e25adf46 100644 --- a/ui/scss/_global.scss +++ b/ui/scss/_global.scss @@ -1,5 +1,8 @@ @charset "UTF-8"; +$spacing-vertical: 24px; +$width-page-constrained: 800px; + @mixin clearfix() { &:before, &:after diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index af2e7ebad..cc2fde586 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -3,23 +3,23 @@ html { height: 100%; - font-size: $font-size; + font-size: var(--font-size); } body { font-family: 'Source Sans Pro', sans-serif; - line-height: $font-line-height; + line-height: var(--font-line-height); } #window { min-height: 100vh; - background: $color-canvas; + background: var(--window-bg); } .badge { - background: $color-money; + background: var(--color-money); display: inline-block; padding: 2px; color: white; @@ -28,13 +28,13 @@ body .credit-amount--indicator { font-weight: bold; - color: $color-money; + color: var(--color-money); } #main-content { padding: $spacing-vertical; - margin-top: $height-header; + margin-top: var(--header-height); display: flex; flex-direction: column; main { @@ -145,18 +145,18 @@ p .help { font-size: .85em; - color: $color-help; + color: var(--color-help); } .meta { font-size: 0.9em; - color: $color-meta-light; + color: var(--color-meta-light); } .empty { - color: $color-meta-light; + color:var(--color-meta-light); font-style: italic; } @@ -176,7 +176,7 @@ p text-align: right; line-height: 1; font-size: 0.85em; - color: $color-help; + color: var(--color-help); } section.section-spaced { diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 83b8fcc91..c2006d588 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -1,46 +1,70 @@ -:root { +@import "global"; - --spacing-vertical: 24px; - --padding-button: 12px; - --padding-text-link: 4px; +:root { /* Colors */ --color-primary: #155B4A; - --color-primary-light: #155B4A; - --color-light-alt: #155B4A; - --color-text-dark: #000; --color-black-transparent: rgba(32,32,32,0.9); --color-help: rgba(0,0,0,.6); --color-notice: #8a6d3b; --color-error: #a94442; --color-load-screen-text: #c3c3c3; - --color-canvas: #f5f5f5; - --color-bg: #ffffff; - --color-bg-alt: #D9D9D9; --color-money: #216C2A; --color-meta-light: #505050; - --color-form-border: rgba(160,160,160,.5); /* Font */ --font-size: 16px; --font-line-height: 1.3333; + --font-size-subtext-multiple: 0.82; - --mobile-width-threshold: 801px; - --max-content-width: 1000px; - --max-text-width: 660px; - - --width-page-constrained: 800px; - --width-input-text: 330px; - - --height-button: --spacing-vertical * 1.5; - --height-header: --spacing-vertical * 2.5; - --height-video-embedded: --width-page-constrained * 9 / 16; - + /* Shadows */ --box-shadow-layer: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); - --transition-standard: .225s ease; + /* Misc */ + --page-constrained-width: 800px; + --mobile-width-threshold: 801px; + --content-max-width: 1000px; + --standard-transition: .225s ease; + --nsfw-blur-intensity: 20px; + --height-video-embedded: $width-page-constrained * 9 / 16 ; - --blur-intensity-nsfw: 20px; + /* Text */ + --text-color: #000; + --text-max-width: 660px; + --text-link-padding: 4px; + /* Input */ + --input-width: 330px; + + /* Button */ + --button-primary-bg: var(--color-primary); + --button-primary-color: #FFF; + --button-padding: 12px; + --button-height: $spacing-vertical * 1.5; + + /* Header */ + --header-bg: #FFF; + --header-color: #666; + --header-height: $spacing-vertical * 2.5; + + /* Window */ + --window-bg: #f5f5f5; + + /* Card */ + --card-bg: #FFF; + --card-hover-translate: 10px; + --card-margin: $spacing-vertical * 2/3; + --card-max-width: $width-page-constrained; + --card-padding: var(--card-margin); + --card-radius: 2px; + --card-link-scaling: 1.1; + --card-shadow: var(--box-shadow-layer); + --card-small-width: $spacing-vertical * 10; + + /* Tooltip */ + --tooltip-body-width: 300px; + --tooltip-bg: #FFF; + --tooltip-color: var(--text-color); + --tooltip-shadow: var(--box-shadow-layer); } diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 5c6fed22f..9f8646f54 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -8,15 +8,15 @@ $button-focus-shift: 12%; + .button-set-item { - margin-left: $padding-button; + margin-left: var(--button-padding); } } .button-block, .faux-button-block { display: inline-block; - height: $height-button; - line-height: $height-button; + height: var(--button-height); + line-height: var(--button-height); text-decoration: none; border: 0 none; text-align: center; @@ -46,25 +46,25 @@ $button-focus-shift: 12%; } .button__content { - margin: 0 $padding-button; + margin: 0 var(--button-padding); } .button-primary { - $color-button-text: white; - color: darken($color-button-text, $button-focus-shift * 0.5); - background-color: $color-primary; - box-shadow: $box-shadow-layer; + + color: inherit; + background-color: var(--button-primary-bg); + box-shadow: var(--box-shadow-layer); &:focus { - color: $color-button-text; + color: var(--button-primary-color); //box-shadow: $box-shadow-focus; - background-color: mix(black, $color-primary, $button-focus-shift) + //background-color: mix(black, $color-primary, $button-focus-shift) } } .button-alt { - background-color: $color-bg-alt; - box-shadow: $box-shadow-layer; + background-color: var(--color-bg-alt); + box-shadow: var(--box-shadow-layer); } .button-text @@ -73,7 +73,7 @@ $button-focus-shift: 12%; display: inline-block; .button__content { - margin: 0 $padding-text-link; + margin: 0 var(--text-link-padding); } } .button-text-help @@ -84,4 +84,4 @@ $button-focus-shift: 12%; .button--flat { box-shadow: none !important; -} \ No newline at end of file +} diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 712eb9ea7..65179d7ac 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -1,17 +1,13 @@ @import "../global"; -$padding-card-horizontal: $spacing-vertical * 2/3; -$translate-card-hover: 10px; -$width-card-small: $spacing-vertical * 10; - .card { margin-left: auto; margin-right: auto; - max-width: $width-page-constrained; - background: $color-bg; - box-shadow: $box-shadow-layer; - border-radius: 2px; - margin-bottom: $spacing-vertical * 2/3; + max-width: var(--card-max-width); + background: var(--card-bg); + box-shadow: var(--card-shadow); + border-radius: var(--card-radius); + margin-bottom: var(--card-margin); overflow: auto; } .card--obscured @@ -19,14 +15,14 @@ $width-card-small: $spacing-vertical * 10; position: relative; } .card--obscured .card__inner { - filter: blur($blur-intensity-nsfw); + filter: blur( var(--nsfw-blur-intensity) ); } .card__title-primary, .card__title-identity, .card__actions, .card__content, .card__subtext { - padding: 0 $padding-card-horizontal; + padding: 0 var(--card-padding); } .card--small { .card__title-primary, @@ -34,18 +30,18 @@ $width-card-small: $spacing-vertical * 10; .card__actions, .card__content, .card__subtext { - padding: 0 $padding-card-horizontal / 2; + padding: 0 cacl(var(--card-padding) / 2); } } .card__title-primary { - margin-top: $spacing-vertical * 2/3; + margin-top: var(--card-margin); } .card__title-identity { margin-top: $spacing-vertical * 1/3; margin-bottom: $spacing-vertical * 1/3; } .card__actions { - margin-top: $spacing-vertical * 2/3; + margin-top: var(--card-margin); } .card__actions--bottom { margin-top: $spacing-vertical * 1/3; @@ -53,16 +49,16 @@ $width-card-small: $spacing-vertical * 10; } .card__actions--form-submit { margin-top: $spacing-vertical; - margin-bottom: $spacing-vertical * 2/3; + margin-bottom: var(--card-margin); } .card__content { - margin-top: $spacing-vertical * 2/3; - margin-bottom: $spacing-vertical * 2/3; + margin-top: var(--card-margin); + margin-bottom: var(--card-margin); } $font-size-subtext-multiple: 0.82; .card__subtext { - color: $color-meta-light; - font-size: $font-size-subtext-multiple * 1.0em; + color: var(--color-meta-light); + font-size: calc( var(--font-size-subtext-multiple) * 1.0em ); margin-top: $spacing-vertical * 1/3; margin-bottom: $spacing-vertical * 1/3; } @@ -70,7 +66,7 @@ $font-size-subtext-multiple: 0.82; white-space: pre-wrap; } .card__subtext--two-lines { - height: $font-size * $font-size-subtext-multiple * $font-line-height * 2; /*this is so one line text still has the proper height*/ + height: calc( var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2); /*this is so one line text still has the proper height*/ } .card-overlay { position: absolute; @@ -86,7 +82,6 @@ $font-size-subtext-multiple: 0.82; font-weight: 600; } -$card-link-scaling: 1.1; .card__link { display: block; } @@ -96,14 +91,14 @@ $card-link-scaling: 1.1; .card--link:hover { position: relative; z-index: 1; - box-shadow: $box-shadow-focus; - transform: scale($card-link-scaling) translateX($translate-card-hover); + box-shadow: var(--box-shadow-focus); + transform: scale(var(--card-link-scaling)) translateX(var(--card-hover-translate)); transform-origin: 50% 50%; overflow-x: visible; overflow-y: visible } .card--link:hover ~ .card--link { - transform: translateX($translate-card-hover * 2); + transform: translateX(calc(var(--translate-card-hover) * 2)); } .card__media { @@ -157,43 +152,42 @@ $card-link-scaling: 1.1; position: absolute; top: 36% } - - - .card--small { - width: $width-card-small; + width: var(--card-small-width); overflow-x: hidden; white-space: normal; } .card--small .card__media { - height: $width-card-small * 9 / 16; + height: calc( var(--card-small-width) * 9 / 16); } .card--form { - width: $width-input-text + $padding-card-horizontal * 2; + width: calc( var(--input-width) + var(--card-padding * 2); } .card__subtitle { - color: $color-help; + color: var(--color-help); font-size: 0.85em; - line-height: $font-line-height * 1 / 0.85; + line-height: calc( var(--font-line-height) * 1 / 0.85); } .card-series-submit { margin-left: auto; margin-right: auto; - max-width: $width-page-constrained; - padding: $spacing-vertical / 2; + max-width: var(--card-max-width); + padding: calc(var(--vertical-spacing) / 2); } .card-row { + .card-row { - margin-top: $spacing-vertical * 1/3; + margin-top: calc(var(--vertical-spacing) * 1/3); } } + $padding-top-card-hover-hack: 20px; $padding-right-card-hover-hack: 30px; + .card-row__items { width: 100%; overflow: hidden; @@ -219,7 +213,7 @@ $padding-right-card-hover-hack: 30px; padding-right: $padding-right-card-hover-hack; } .card-row__header { - margin-bottom: $spacing-vertical / 3; + margin-bottom: $spacing-vertical; } .card-row__scrollhouse { @@ -228,14 +222,14 @@ $padding-right-card-hover-hack: 30px; .card-row__nav { position: absolute; - padding: 0 $spacing-vertical * 2 / 3; + padding: 0 var(--card-margin); height: 100%; - top: $padding-top-card-hover-hack - $spacing-vertical * 2 / 3; + top: calc( $padding-top-card-hover-hack - var(--card-margin) ); } .card-row__nav .card-row__scroll-button { - background: $color-bg; - color: $color-help; - box-shadow: $box-shadow-layer; + background: var(--card-bg); + color: var(--color-help); + box-shadow: var(--box-shadow-layer); padding: $spacing-vertical $spacing-vertical / 2; position: absolute; cursor: pointer; @@ -247,7 +241,7 @@ $padding-right-card-hover-hack: 30px; &:hover { opacity: 1.0; - transform: scale($card-link-scaling * 1.1) + transform: scale(calc( var(--card-link-scaling) * 1.1)); } } .card-row__nav--left { @@ -259,4 +253,4 @@ $padding-right-card-hover-hack: 30px; .card__icon-featured-content { color: orangered; -} \ No newline at end of file +} diff --git a/ui/scss/component/_channel-indicator.scss b/ui/scss/component/_channel-indicator.scss index 52a0baed6..8b72bd36d 100644 --- a/ui/scss/component/_channel-indicator.scss +++ b/ui/scss/component/_channel-indicator.scss @@ -1,5 +1,5 @@ @import "../global"; .channel-indicator__icon--invalid { - color: $color-error; + color: var(--color-error); } diff --git a/ui/scss/component/_file-actions.scss b/ui/scss/component/_file-actions.scss index 4eda16b51..84aef8471 100644 --- a/ui/scss/component/_file-actions.scss +++ b/ui/scss/component/_file-actions.scss @@ -4,13 +4,13 @@ $color-download: #444; .file-actions { - line-height: $height-button; - min-height: $height-button; + line-height: var(--button-height); + min-height: var(--button-height); } .file-actions__download-status-bar, .file-actions__download-status-bar-overlay { .button__content { - margin: 0 $padding-text-link; + margin: 0 var(--text-link-padding); } } @@ -29,4 +29,4 @@ $color-download: #444; z-index: 1; top: 0px; left: 0px; -} \ No newline at end of file +} diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index 9dee7240b..ab0656f1f 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -1,6 +1,7 @@ @import "../global"; $width-input-border: 2px; +$color-form-border: #000; .form-row-submit { @@ -15,7 +16,7 @@ $width-input-border: 2px; margin-top: $spacing-vertical * 5/6; margin-bottom: $spacing-vertical * 1/6; line-height: 1; - font-size: 0.9 * $font-size; + font-size:calc( 0.9 * var(--font-size)); } .form-row__label-row--prefix { float: left; @@ -23,11 +24,11 @@ $width-input-border: 2px; } input[type="text"].input-copyable { - border: 1px solid $color-form-border; + border: 1px solid var(--color-form-border); line-height: 1; padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; - width: $width-input-text; + width: var(--input-width); padding-left: 5px; padding-right: 5px; width: 100%; @@ -43,14 +44,14 @@ input[type="text"].input-copyable { } select { - transition: outline $transition-standard; + transition: outline var(--standar-transition); cursor: pointer; box-sizing: border-box; padding-left: 5px; padding-right: 5px; height: $spacing-vertical; &:focus { - outline: $width-input-border solid $color-primary; + outline: $width-input-border solid var(--color-primary); } } @@ -62,9 +63,9 @@ input[type="text"].input-copyable { input[type="search"], input[type="date"] { @include placeholder { - color: lighten($color-text-dark, 60%); + //color: lighten($color-text-dark, 60%); } - transition: all $transition-standard; + transition: all var(--standar-transition); cursor: pointer; padding-left: 1px; padding-right: 1px; @@ -86,7 +87,7 @@ input[type="text"].input-copyable { padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; &.form-field__input--error { - border-color: $color-error; + border-color: var(--color-error); } &.form-field__input--inline { padding-top: 0; @@ -104,7 +105,7 @@ input[type="text"].input-copyable { input[type="number"]:focus, input[type="search"]:focus, input[type="date"]:focus { - border-color: $color-primary; + border-color: var(--color-primary); } textarea { @@ -124,11 +125,11 @@ input[type="text"].input-copyable { } .form-field__label--error { - color: $color-error; + color: var(--color-error); } .form-field__input-text { - width: $width-input-text; + width: var(--input-width); } .form-field__prefix { @@ -153,16 +154,16 @@ input[type="text"].input-copyable { .form-field__error, .form-field__helper { margin-top: $spacing-vertical * 1/3; font-size: 0.8em; - transition: opacity $transition-standard; + transition: opacity var(--standar-transition); } .form-field__error { - color: $color-error; + color: var(--color-error); } .form-field__helper { - color: $color-help; + color:var(--color-help); } .form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll { height: auto; -} \ No newline at end of file +} diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index 5cc51541e..f107d991b 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -9,7 +9,7 @@ $color-header-active: darken($color-header, 20%); background: #fff; display: flex; position: fixed; - box-shadow: $box-shadow-layer; + box-shadow: var(--header-shadow); top: 0; left: 0; width: 100%; @@ -36,7 +36,7 @@ $color-header-active: darken($color-header, 20%); } } -.wunderbar--active .icon-search { color: $color-primary; } +.wunderbar--active .icon-search { color: var(--color-primary); } .wunderbar__input { background: rgba(255, 255, 255, 0.7); @@ -46,13 +46,13 @@ $color-header-active: darken($color-header, 20%); line-height: $spacing-vertical * 1.5; padding-left: 38px; padding-right: 5px; - border: 1px solid $color-text-dark; + border: 1px solid var(--text-color); @include border-radius(2px); border: 1px solid #ccc; &:focus { - color: $color-header-active; - box-shadow: $box-shadow-focus; - border-color: $color-primary; + color: var(--color-header-active); + box-shadow: var(--box-shadow-focus); + border-color: var(--color-primary); } } @@ -69,8 +69,8 @@ nav.sub-header display: inline-block; margin: 0 15px; padding: 0 5px; - line-height: $height-header - $spacing-vertical - $sub-header-selected-underline-height; - color: $color-header; + line-height:calc(var(--header-height) - $spacing-vertical - $sub-header-selected-underline-height); + color: var(--header-color); &:first-child { margin-left: 0; @@ -81,12 +81,12 @@ nav.sub-header } &.sub-header-selected { - border-bottom: $sub-header-selected-underline-height solid $color-header-active; + border-bottom: $sub-header-selected-underline-height solid var(--color-header-active); color: $color-header-active; } &:hover { - color: $color-header-active; + color: var(--color-header-active); } } -} \ No newline at end of file +} diff --git a/ui/scss/component/_load-screen.scss b/ui/scss/component/_load-screen.scss index 0caa74f65..43d84b116 100644 --- a/ui/scss/component/_load-screen.scss +++ b/ui/scss/component/_load-screen.scss @@ -2,7 +2,7 @@ .load-screen { color: white; - background: $color-primary; + background: var(--color-primary); background-size: cover; min-height: 100vh; min-width: 100vw; @@ -19,7 +19,7 @@ } .load-screen__details { - color: $color-load-screen-text; + color: var(--color-load-screen-text); } .load-screen__details--warning { diff --git a/ui/scss/component/_menu.scss b/ui/scss/component/_menu.scss index d8e79be28..2b59c6079 100644 --- a/ui/scss/component/_menu.scss +++ b/ui/scss/component/_menu.scss @@ -10,7 +10,7 @@ $border-radius-menu: 2px; position: absolute; white-space: nowrap; background-color: white; - box-shadow: $box-shadow-layer; + box-shadow: var(--box-shadow-layer); border-radius: $border-radius-menu; padding-top: ($spacing-vertical / 5) 0px; z-index: 1; @@ -20,6 +20,6 @@ $border-radius-menu: 2px; display: block; padding: ($spacing-vertical / 4) ($spacing-vertical / 2); &:hover { - background: $color-bg-alt; + background: var(--color-bg-alt); } -} \ No newline at end of file +} diff --git a/ui/scss/component/_modal.scss b/ui/scss/component/_modal.scss index c28ba313e..9cf14410e 100644 --- a/ui/scss/component/_modal.scss +++ b/ui/scss/component/_modal.scss @@ -29,7 +29,7 @@ overflow: auto; border-radius: 4px; padding: $spacing-vertical; - box-shadow: $box-shadow-layer; + box-shadow: var(--modal-shadow); max-width: 400px; word-break: break-word; @@ -52,7 +52,7 @@ } .error-modal-overlay { - background: rgba(#000, .88); + background: var(--color-dark-transparent); } .error-modal__content { diff --git a/ui/scss/component/_pagination.scss b/ui/scss/component/_pagination.scss index fd5ca528e..6ea2a14c6 100644 --- a/ui/scss/component/_pagination.scss +++ b/ui/scss/component/_pagination.scss @@ -32,5 +32,5 @@ .pagination__item--selected { color: white; - background: $color-primary; + background: var(--color-primary); } diff --git a/ui/scss/component/_snack-bar.scss b/ui/scss/component/_snack-bar.scss index c3df3ab92..be517ee41 100644 --- a/ui/scss/component/_snack-bar.scss +++ b/ui/scss/component/_snack-bar.scss @@ -16,7 +16,7 @@ $padding-snack-horizontal: $spacing-vertical; margin-right: auto; min-width: 300px; max-width: 500px; - background: $color-black-transparent; + background: var(--color-black-transparent); color: #f0f0f0; display: flex; @@ -25,7 +25,7 @@ $padding-snack-horizontal: $spacing-vertical; border-radius: 2px; - transition: all $transition-standard; + transition: all var(--standard-transition); z-index: 10000; /*hack to get it over react modal */ } @@ -33,7 +33,7 @@ $padding-snack-horizontal: $spacing-vertical; .snack-bar__action { display: inline-block; text-transform: uppercase; - color: $color-primary-light; + color: var(--color-primary-light); margin: 0px 0px 0px $padding-snack-horizontal; min-width: min-content; &:hover { diff --git a/ui/scss/component/_tooltip.scss b/ui/scss/component/_tooltip.scss index 0be9b1db8..12dc1ee89 100644 --- a/ui/scss/component/_tooltip.scss +++ b/ui/scss/component/_tooltip.scss @@ -9,28 +9,25 @@ } .tooltip__body { - $tooltip-body-width: 300px; - position: absolute; z-index: 1; left: 50%; - margin-left: $tooltip-body-width * -1 / 2; + margin-left: calc(var(--tooltip-width) * -1 / 2); white-space: normal; - box-sizing: border-box; padding: $spacing-vertical / 2; - width: $tooltip-body-width; + width: var(--tooltip-width); border: 1px solid #aaa; - color: $color-text-dark; - background-color: $color-bg; - font-size: $font-size * 7/8; - line-height: $font-line-height; - box-shadow: $box-shadow-layer; + color: var(--tooltip-color); + background-color: var(--tooltip-bg); + font-size: calc(var(--font-size) * 7/8); + line-height: var(--font-line-height); + box-shadow: var(--tooltip-shadow); } .tooltip--header .tooltip__link { @include text-link(#aaa); - font-size: $font-size * 3/4; - margin-left: $padding-button; + font-size: calc( var(--font-size) * 3/4 ); + margin-left: var(--button-padding); vertical-align: middle; -} \ No newline at end of file +} diff --git a/ui/scss/component/_video.scss b/ui/scss/component/_video.scss index 5515cbf8a..5540c635a 100644 --- a/ui/scss/component/_video.scss +++ b/ui/scss/component/_video.scss @@ -1,3 +1,4 @@ +$height-video-embedded: $width-page-constrained * 9 / 16; video { object-fit: contain; box-sizing: border-box; @@ -35,7 +36,7 @@ video { .video--obscured .video__cover { position: relative; - filter: blur($blur-intensity-nsfw); + filter: blur(var(--nsfw-blur-intensity)); } @@ -118,12 +119,12 @@ video { font-size: $spacing-vertical * 3; color: white; z-index: 1; - background: $color-black-transparent; + background: var(--color-black-transparent); opacity: 0.6; left: 0; top: 0; &:hover { opacity: 1; - transition: opacity $transition-standard; + transition: opacity var(--standar-transition); } } diff --git a/ui/scss/page/_reward.scss b/ui/scss/page/_reward.scss index a550c01c3..5e6180dc5 100644 --- a/ui/scss/page/_reward.scss +++ b/ui/scss/page/_reward.scss @@ -1,5 +1,5 @@ @import "../global"; .reward-page__details { - background-color: lighten($color-canvas, 1.5%); -} \ No newline at end of file + //background-color: lighten($color-canvas, 1.5%); +} From 1e465d80b1e1c91b309d7fb8bd970ce97c9f5ef5 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 17:25:35 -0600 Subject: [PATCH 032/132] add missing colors --- ui/js/util/setTheme.js | 2 ++ ui/scss/_vars.scss | 15 +++++++++------ ui/scss/component/_modal.scss | 2 +- ui/scss/component/_snack-bar.scss | 2 +- ui/scss/component/_video.scss | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/ui/js/util/setTheme.js b/ui/js/util/setTheme.js index 71c101298..9add03811 100644 --- a/ui/js/util/setTheme.js +++ b/ui/js/util/setTheme.js @@ -3,6 +3,7 @@ import { existsSync } from "fs"; import { remote } from "electron"; function setTheme(name) { + /* const link = document.getElementById("theme"); const file = `${name}.css`; const path = `${remote.app.getAppPath()}/dist/themes/${file}`; @@ -14,6 +15,7 @@ function setTheme(name) { link.href = `./themes/light.css`; lbry.setClientSetting("theme", "light"); } + */ } export default setTheme; diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index c2006d588..5d9e3a75c 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -4,13 +4,18 @@ /* Colors */ --color-primary: #155B4A; - --color-black-transparent: rgba(32,32,32,0.9); + --color-primary-light: saturate(lighten(#155B4A, 50%), 20%); + --color-light-alt: hsl(hue(#155B4A), 15, 85); + --color-dark-overlay: rgba(32,32,32,0.9); --color-help: rgba(0,0,0,.6); --color-notice: #8a6d3b; --color-error: #a94442; --color-load-screen-text: #c3c3c3; --color-money: #216C2A; --color-meta-light: #505050; + --color-canvas: #f5f5f5; + --color-bg: #ffffff; + --color-bg-alt: #D9D9D9; /* Font */ --font-size: 16px; @@ -22,8 +27,6 @@ --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); /* Misc */ - --page-constrained-width: 800px; - --mobile-width-threshold: 801px; --content-max-width: 1000px; --standard-transition: .225s ease; --nsfw-blur-intensity: 20px; @@ -49,10 +52,10 @@ --header-height: $spacing-vertical * 2.5; /* Window */ - --window-bg: #f5f5f5; + --window-bg: var(--color-canvas); /* Card */ - --card-bg: #FFF; + --card-bg: var(--color-bg); --card-hover-translate: 10px; --card-margin: $spacing-vertical * 2/3; --card-max-width: $width-page-constrained; @@ -64,7 +67,7 @@ /* Tooltip */ --tooltip-body-width: 300px; - --tooltip-bg: #FFF; + --tooltip-bg: var(--color-bg); --tooltip-color: var(--text-color); --tooltip-shadow: var(--box-shadow-layer); } diff --git a/ui/scss/component/_modal.scss b/ui/scss/component/_modal.scss index f1cd56834..c320a6475 100644 --- a/ui/scss/component/_modal.scss +++ b/ui/scss/component/_modal.scss @@ -52,7 +52,7 @@ } .error-modal-overlay { - background: var(--color-dark-transparent); + background: var(--color-dark-overlay); } .error-modal__content { diff --git a/ui/scss/component/_snack-bar.scss b/ui/scss/component/_snack-bar.scss index be517ee41..1d057b16f 100644 --- a/ui/scss/component/_snack-bar.scss +++ b/ui/scss/component/_snack-bar.scss @@ -16,7 +16,7 @@ $padding-snack-horizontal: $spacing-vertical; margin-right: auto; min-width: 300px; max-width: 500px; - background: var(--color-black-transparent); + background: var(--color-dark-overlay); color: #f0f0f0; display: flex; diff --git a/ui/scss/component/_video.scss b/ui/scss/component/_video.scss index 5540c635a..0f7f860ff 100644 --- a/ui/scss/component/_video.scss +++ b/ui/scss/component/_video.scss @@ -119,7 +119,7 @@ video { font-size: $spacing-vertical * 3; color: white; z-index: 1; - background: var(--color-black-transparent); + background: var(--color-dark-overlay); opacity: 0.6; left: 0; top: 0; From 5a9fdcdd26b4b28d1ab9bbed792a86a8f48ecf70 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 17:35:52 -0600 Subject: [PATCH 033/132] import css vars --- ui/scss/all.scss | 1 + ui/scss/component/_card.scss | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/scss/all.scss b/ui/scss/all.scss index d899566ab..a63c6ec13 100644 --- a/ui/scss/all.scss +++ b/ui/scss/all.scss @@ -1,4 +1,5 @@ @import "_reset"; +@import "_vars"; @import "_icons"; @import "_gui"; @import "component/_table"; diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 65179d7ac..29869925b 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -75,7 +75,7 @@ $font-size-subtext-multiple: 0.82; top: 0px; bottom: 0px; padding: 20px; - background-color: rgba(128, 128, 128, 0.8); + background-color: var(--color-dark-overlay); color: #fff; display: flex; align-items: center; @@ -98,7 +98,7 @@ $font-size-subtext-multiple: 0.82; overflow-y: visible } .card--link:hover ~ .card--link { - transform: translateX(calc(var(--translate-card-hover) * 2)); + transform: translateX(calc(var(--card-hover-translate) * 2)); } .card__media { @@ -162,7 +162,7 @@ $font-size-subtext-multiple: 0.82; } .card--form { - width: calc( var(--input-width) + var(--card-padding * 2); + width: calc( var(--input-width) + var(--card-padding) * 2); } .card__subtitle { From 6455f499562d7d4d2f19b08ab948b92c3a0e6896 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 18:06:53 -0600 Subject: [PATCH 034/132] minor fix for broken styles / animation --- ui/scss/_global.scss | 2 +- ui/scss/_vars.scss | 8 ++++++-- ui/scss/component/_button.scss | 2 +- ui/scss/component/_form-field.scss | 7 +++---- ui/scss/component/_header.scss | 6 +++--- ui/scss/component/_video.scss | 2 +- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ui/scss/_global.scss b/ui/scss/_global.scss index 5e25adf46..f3ce3fea0 100644 --- a/ui/scss/_global.scss +++ b/ui/scss/_global.scss @@ -144,7 +144,7 @@ $width-page-constrained: 800px; &:hover { opacity: $hover-opacity; - transition: opacity var(--transition-standard); + transition: opacity var(--transition-duration) var(--transition-type); text-decoration: underline; .icon { text-decoration: none; diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 5d9e3a75c..22f992f6f 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -28,10 +28,13 @@ /* Misc */ --content-max-width: 1000px; - --standard-transition: .225s ease; --nsfw-blur-intensity: 20px; --height-video-embedded: $width-page-constrained * 9 / 16 ; + /* Transitions */ + --transition-duration: .225s; + --transition-type: ease; + /* Text */ --text-color: #000; --text-max-width: 660px; @@ -47,9 +50,10 @@ --button-height: $spacing-vertical * 1.5; /* Header */ - --header-bg: #FFF; + --header-bg: var(--color-bg); --header-color: #666; --header-height: $spacing-vertical * 2.5; + --header-shadow: var(--box-shadow-layer); /* Window */ --window-bg: var(--color-canvas); diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 9f8646f54..8a2d945f0 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -52,7 +52,7 @@ $button-focus-shift: 12%; .button-primary { - color: inherit; + color: var(--button-primary-color); background-color: var(--button-primary-bg); box-shadow: var(--box-shadow-layer); &:focus { diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index ab0656f1f..050a4cd27 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -44,8 +44,7 @@ input[type="text"].input-copyable { } select { - transition: outline var(--standar-transition); - cursor: pointer; + transition: outline var(--transition-duration) var(--transition-type); box-sizing: border-box; padding-left: 5px; padding-right: 5px; @@ -65,7 +64,7 @@ input[type="text"].input-copyable { @include placeholder { //color: lighten($color-text-dark, 60%); } - transition: all var(--standar-transition); + transition: all var(--transition-duration) var(--transition-type); cursor: pointer; padding-left: 1px; padding-right: 1px; @@ -154,7 +153,7 @@ input[type="text"].input-copyable { .form-field__error, .form-field__helper { margin-top: $spacing-vertical * 1/3; font-size: 0.8em; - transition: opacity var(--standar-transition); + transition: opacity var(--transition-duration) var(--transition-type); } .form-field__error { diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index f107d991b..9e6498c8e 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -50,7 +50,7 @@ $color-header-active: darken($color-header, 20%); @include border-radius(2px); border: 1px solid #ccc; &:focus { - color: var(--color-header-active); + color: $color-header-active; box-shadow: var(--box-shadow-focus); border-color: var(--color-primary); } @@ -81,12 +81,12 @@ nav.sub-header } &.sub-header-selected { - border-bottom: $sub-header-selected-underline-height solid var(--color-header-active); + border-bottom: $sub-header-selected-underline-height solid $color-header-active; color: $color-header-active; } &:hover { - color: var(--color-header-active); + color: $color-header-active; } } } diff --git a/ui/scss/component/_video.scss b/ui/scss/component/_video.scss index 0f7f860ff..563e726d1 100644 --- a/ui/scss/component/_video.scss +++ b/ui/scss/component/_video.scss @@ -125,6 +125,6 @@ video { top: 0; &:hover { opacity: 1; - transition: opacity var(--standar-transition); + transition: opacity var(--transition-duration) var(--transition-type); } } From 95f68cbda8c9be7a4b41e5d842fc7fab4ee474c9 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 18:42:45 -0600 Subject: [PATCH 035/132] fix load screen styles --- app/main.js | 2 +- ui/scss/_vars.scss | 1 + ui/scss/component/_load-screen.scss | 2 +- ui/scss/component/_snack-bar.scss | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/main.js b/app/main.js index 27c8f72c8..c14528cca 100644 --- a/app/main.js +++ b/app/main.js @@ -402,4 +402,4 @@ ipcMain.on('get-auth-token', (event) => { ipcMain.on('set-auth-token', (event, token) => { keytar.setPassword("LBRY", "auth_token", token ? token.toString().trim() : null); -}); \ No newline at end of file +}); diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 22f992f6f..991722a4c 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -3,6 +3,7 @@ :root { /* Colors */ + --color-brand: #155B4A; --color-primary: #155B4A; --color-primary-light: saturate(lighten(#155B4A, 50%), 20%); --color-light-alt: hsl(hue(#155B4A), 15, 85); diff --git a/ui/scss/component/_load-screen.scss b/ui/scss/component/_load-screen.scss index 43d84b116..24221c10d 100644 --- a/ui/scss/component/_load-screen.scss +++ b/ui/scss/component/_load-screen.scss @@ -2,7 +2,7 @@ .load-screen { color: white; - background: var(--color-primary); + background: var(--color-brand); background-size: cover; min-height: 100vh; min-width: 100vw; diff --git a/ui/scss/component/_snack-bar.scss b/ui/scss/component/_snack-bar.scss index 1d057b16f..5be3e1c6d 100644 --- a/ui/scss/component/_snack-bar.scss +++ b/ui/scss/component/_snack-bar.scss @@ -25,7 +25,7 @@ $padding-snack-horizontal: $spacing-vertical; border-radius: 2px; - transition: all var(--standard-transition); + transition: all var(--transition-duration) var(--transition-type); z-index: 10000; /*hack to get it over react modal */ } From 509ff192cd4bdd39314f60f85040cf5428739d9a Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 19:09:45 -0600 Subject: [PATCH 036/132] fix for card style --- ui/scss/_vars.scss | 2 +- ui/scss/component/_card.scss | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 991722a4c..c25920a21 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -64,7 +64,7 @@ --card-hover-translate: 10px; --card-margin: $spacing-vertical * 2/3; --card-max-width: $width-page-constrained; - --card-padding: var(--card-margin); + --card-padding: $spacing-vertical * 2/3; --card-radius: 2px; --card-link-scaling: 1.1; --card-shadow: var(--box-shadow-layer); diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 29869925b..5910bfd9c 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -30,7 +30,7 @@ .card__actions, .card__content, .card__subtext { - padding: 0 cacl(var(--card-padding) / 2); + padding: 0 calc(var(--card-padding) / 2); } } .card__title-primary { @@ -176,12 +176,12 @@ $font-size-subtext-multiple: 0.82; margin-left: auto; margin-right: auto; max-width: var(--card-max-width); - padding: calc(var(--vertical-spacing) / 2); + padding: $spacing-vertical / 2; } .card-row { + .card-row { - margin-top: calc(var(--vertical-spacing) * 1/3); + margin-top: $spacing-vertical * 1/3; } } @@ -213,7 +213,7 @@ $padding-right-card-hover-hack: 30px; padding-right: $padding-right-card-hover-hack; } .card-row__header { - margin-bottom: $spacing-vertical; + margin-bottom: $spacing-vertical / 3; } .card-row__scrollhouse { From 198d44af662ba921d675ed10359c8db16155bc44 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 19:18:07 -0600 Subject: [PATCH 037/132] minor fix for buttons style --- ui/scss/component/_button.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 8a2d945f0..3b5fdce8d 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -55,10 +55,12 @@ $button-focus-shift: 12%; color: var(--button-primary-color); background-color: var(--button-primary-bg); box-shadow: var(--box-shadow-layer); + opacity: 0.9; &:focus { color: var(--button-primary-color); //box-shadow: $box-shadow-focus; //background-color: mix(black, $color-primary, $button-focus-shift) + opacity: 1; } } .button-alt From dccd52c7dffc55805f91165380961db522cf4012 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 19:46:45 -0600 Subject: [PATCH 038/132] fix broken style from form-field --- ui/scss/_vars.scss | 2 ++ ui/scss/component/_button.scss | 7 +++---- ui/scss/component/_form-field.scss | 11 ++++------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index c25920a21..b8115d0ca 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -43,6 +43,8 @@ /* Input */ --input-width: 330px; + --input-border-size: 2px; + --input-border-color: rgba(0,0,0,.25); /* Button */ --button-primary-bg: var(--color-primary); diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 3b5fdce8d..0f4d851e5 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -55,12 +55,11 @@ $button-focus-shift: 12%; color: var(--button-primary-color); background-color: var(--button-primary-bg); box-shadow: var(--box-shadow-layer); - opacity: 0.9; + &:focus { - color: var(--button-primary-color); + //color: var(--button-primary-active-color); + //background-color:color: var(--button-primary-active-bg); //box-shadow: $box-shadow-focus; - //background-color: mix(black, $color-primary, $button-focus-shift) - opacity: 1; } } .button-alt diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index 050a4cd27..841d58d62 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -1,8 +1,5 @@ @import "../global"; -$width-input-border: 2px; -$color-form-border: #000; - .form-row-submit { margin-top: $spacing-vertical; @@ -24,7 +21,7 @@ $color-form-border: #000; } input[type="text"].input-copyable { - border: 1px solid var(--color-form-border); + border: 1px solid var(--input-border-color); line-height: 1; padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; @@ -50,7 +47,7 @@ input[type="text"].input-copyable { padding-right: 5px; height: $spacing-vertical; &:focus { - outline: $width-input-border solid var(--color-primary); + outline: var(--input-border-size) solid var(--color-primary); } } @@ -81,7 +78,7 @@ input[type="text"].input-copyable { input[type="number"], input[type="search"], input[type="date"] { - border-bottom: $width-input-border solid $color-form-border; + border-bottom: var(--input-border-size) solid var(--input-border-color); line-height: 1; padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; @@ -109,7 +106,7 @@ input[type="text"].input-copyable { textarea { padding: 2px; - border: $width-input-border solid $color-form-border; + border: var(--input-border-size) solid var(--input-border-color); } } .form-field--SimpleMDE { From 3f3372c96a8617a8fc2fd3b50ce70425f288aa68 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 18 Aug 2017 22:33:01 -0600 Subject: [PATCH 039/132] update overall scss structure make styles more flexible / customizable --- ui/scss/_gui.scss | 6 +++ ui/scss/_vars.scss | 57 ++++++++++++++++++++++------ ui/scss/component/_button.scss | 4 +- ui/scss/component/_card.scss | 2 +- ui/scss/component/_file-actions.scss | 6 +-- ui/scss/component/_header.scss | 30 +++++++-------- ui/scss/component/_menu.scss | 6 +-- ui/scss/component/_modal.scss | 10 ++--- ui/scss/component/_table.scss | 10 ++--- ui/scss/component/_tooltip.scss | 4 +- 10 files changed, 84 insertions(+), 51 deletions(-) diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index 7f9768f2c..1c484c68b 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -11,6 +11,12 @@ body line-height: var(--font-line-height); } +/* Custom text selection */ +*::selection { + background: var(--text-selection-bg); + color: var(--text-selection-color); +} + #window { min-height: 100vh; diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index b8115d0ca..bfa2264ab 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -12,12 +12,18 @@ --color-notice: #8a6d3b; --color-error: #a94442; --color-load-screen-text: #c3c3c3; - --color-money: #216C2A; --color-meta-light: #505050; + --color-money: #216C2A; + --color-download: #444; --color-canvas: #f5f5f5; --color-bg: #ffffff; --color-bg-alt: #D9D9D9; + /* Misc */ + --content-max-width: 1000px; + --nsfw-blur-intensity: 20px; + --height-video-embedded: $width-page-constrained * 9 / 16 ; + /* Font */ --font-size: 16px; --font-line-height: 1.3333; @@ -27,19 +33,20 @@ --box-shadow-layer: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); --box-shadow-focus: 2px 4px 4px 0 rgba(0,0,0,.14),2px 5px 3px -2px rgba(0,0,0,.2),2px 3px 7px 0 rgba(0,0,0,.12); - /* Misc */ - --content-max-width: 1000px; - --nsfw-blur-intensity: 20px; - --height-video-embedded: $width-page-constrained * 9 / 16 ; - - /* Transitions */ + /* Transition */ --transition-duration: .225s; --transition-type: ease; /* Text */ --text-color: #000; + --text-help-color: #EEE; --text-max-width: 660px; --text-link-padding: 4px; + --text-selection-bg: rgba(saturate(lighten(#155B4A, 20%), 20%), 1); // temp color + --text-selection-color: #FFF; + + /* Window */ + --window-bg: var(--color-canvas); /* Input */ --input-width: 330px; @@ -47,6 +54,8 @@ --input-border-color: rgba(0,0,0,.25); /* Button */ + --button-bg: var(--color-bg-alt); + --button-color: #FFF; --button-primary-bg: var(--color-primary); --button-primary-color: #FFF; --button-padding: 12px; @@ -55,11 +64,26 @@ /* Header */ --header-bg: var(--color-bg); --header-color: #666; + --header-active-color: rgba(0,0,0, 0.85); --header-height: $spacing-vertical * 2.5; - --header-shadow: var(--box-shadow-layer); - /* Window */ - --window-bg: var(--color-canvas); + /* Header -> search */ + --search-bg: rgba(255, 255, 255, 0.7); + --search-border:1px solid #ccc; + --search-color: #666; + --search-active-color: var(--header-active-color); + + /* Tabs */ + --tab-bg: transparent; + --tab-color: #666; + --tab-active-color: var(--header-active-color); + --tab-border-size: 2px; + --tab-border: var(--tab-border-size) solid var(--tab-active-color); + + /* Table */ + --table-border: 1px solid #e2e2e2; + --table-item-even: white; + --table-item-odd: #f4f4f4; /* Card */ --card-bg: var(--color-bg); @@ -69,12 +93,21 @@ --card-padding: $spacing-vertical * 2/3; --card-radius: 2px; --card-link-scaling: 1.1; - --card-shadow: var(--box-shadow-layer); --card-small-width: $spacing-vertical * 10; + /* Modal */ + --modal-bg: var(--color-bg); + --modal-overlay-bg: rgba(#F5F5F5, 0.75); // --color-canvas: #F5F5F5 + --modal-border: 1px solid rgb(204, 204, 204); + + /* Menu */ + --menu-bg: var(--color-bg); + --menu-radius: 2px; + --menu-item-hover-bg: var(--color-bg-alt); + /* Tooltip */ --tooltip-body-width: 300px; --tooltip-bg: var(--color-bg); --tooltip-color: var(--text-color); - --tooltip-shadow: var(--box-shadow-layer); + --tooltip-border: 1px solid #aaa; } diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 0f4d851e5..93662bd86 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -64,7 +64,7 @@ $button-focus-shift: 12%; } .button-alt { - background-color: var(--color-bg-alt); + background-color: var(--button-bg); box-shadow: var(--box-shadow-layer); } @@ -79,7 +79,7 @@ $button-focus-shift: 12%; } .button-text-help { - @include text-link(#aaa); + @include text-link(var(--text-help-color)); font-size: 0.8em; } .button--flat diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 5910bfd9c..c43cc3c2d 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -5,7 +5,7 @@ margin-right: auto; max-width: var(--card-max-width); background: var(--card-bg); - box-shadow: var(--card-shadow); + box-shadow: var(--box-shadow-layer); border-radius: var(--card-radius); margin-bottom: var(--card-margin); overflow: auto; diff --git a/ui/scss/component/_file-actions.scss b/ui/scss/component/_file-actions.scss index 84aef8471..88d67bf29 100644 --- a/ui/scss/component/_file-actions.scss +++ b/ui/scss/component/_file-actions.scss @@ -1,7 +1,5 @@ @import "../global"; -$color-download: #444; - .file-actions { line-height: var(--button-height); @@ -17,11 +15,11 @@ $color-download: #444; .file-actions__download-status-bar { position: relative; - color: $color-download; + color: var(--color-download); } .file-actions__download-status-bar-overlay { - background: $color-download; + background: var(--color-download); color: white; position: absolute; white-space: nowrap; diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index 9e6498c8e..0d01abe1c 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -1,15 +1,12 @@ @import "../global"; -$color-header: #666; -$color-header-active: darken($color-header, 20%); - #header { - color: $color-header; - background: #fff; + color: var(--header-color); + background: var(--header-bg); display: flex; position: fixed; - box-shadow: var(--header-shadow); + box-shadow: var(--box-shadow-layer); top: 0; left: 0; width: 100%; @@ -39,18 +36,18 @@ $color-header-active: darken($color-header, 20%); .wunderbar--active .icon-search { color: var(--color-primary); } .wunderbar__input { - background: rgba(255, 255, 255, 0.7); + background: var(--search-bg); width: 100%; - color: $color-header; + color: var(--search-color); height: $spacing-vertical * 1.5; line-height: $spacing-vertical * 1.5; padding-left: 38px; padding-right: 5px; - border: 1px solid var(--text-color); @include border-radius(2px); - border: 1px solid #ccc; + border: var(--search-border); + transition: all var(--transition-duration) var(--transition-type); &:focus { - color: $color-header-active; + color: var(--search-active-color); box-shadow: var(--box-shadow-focus); border-color: var(--color-primary); } @@ -65,12 +62,11 @@ nav.sub-header margin-right: auto; > a { - $sub-header-selected-underline-height: 2px; display: inline-block; margin: 0 15px; padding: 0 5px; - line-height:calc(var(--header-height) - $spacing-vertical - $sub-header-selected-underline-height); - color: var(--header-color); + line-height:calc(var(--header-height) - $spacing-vertical - var(--tab-border-size)); + color: var(--tab-color); &:first-child { margin-left: 0; @@ -81,12 +77,12 @@ nav.sub-header } &.sub-header-selected { - border-bottom: $sub-header-selected-underline-height solid $color-header-active; - color: $color-header-active; + border-bottom: var(--tab-border); + color: var(--tab-active-color); } &:hover { - color: $color-header-active; + color: var(--tab-active-color); } } } diff --git a/ui/scss/component/_menu.scss b/ui/scss/component/_menu.scss index 2b59c6079..52399bdfb 100644 --- a/ui/scss/component/_menu.scss +++ b/ui/scss/component/_menu.scss @@ -9,9 +9,9 @@ $border-radius-menu: 2px; .menu { position: absolute; white-space: nowrap; - background-color: white; + background-color: var(--menu-bg); box-shadow: var(--box-shadow-layer); - border-radius: $border-radius-menu; + border-radius: var(--menu-radius); padding-top: ($spacing-vertical / 5) 0px; z-index: 1; } @@ -20,6 +20,6 @@ $border-radius-menu: 2px; display: block; padding: ($spacing-vertical / 4) ($spacing-vertical / 2); &:hover { - background: var(--color-bg-alt); + background: var(--menu-item-hover-bg); } } diff --git a/ui/scss/component/_modal.scss b/ui/scss/component/_modal.scss index c320a6475..f367e45f3 100644 --- a/ui/scss/component/_modal.scss +++ b/ui/scss/component/_modal.scss @@ -10,7 +10,7 @@ left: 0px; right: 0px; bottom: 0px; - background-color: rgba(255, 255, 255, 0.74902); + background-color: var(--modal-overlay-bg); z-index: 9999; } @@ -24,12 +24,12 @@ justify-content: center; align-items: center; - border: 1px solid rgb(204, 204, 204); - background: rgb(255, 255, 255); + border: var(--modal-border); + background: var(--modal-bg); overflow: auto; border-radius: 4px; padding: $spacing-vertical; - box-shadow: var(--modal-shadow); + box-shadow: var(--box-shadow-layer); max-width: 400px; word-break: break-word; @@ -52,7 +52,7 @@ } .error-modal-overlay { - background: var(--color-dark-overlay); + background: var(--modal-overlay-bg); } .error-modal__content { diff --git a/ui/scss/component/_table.scss b/ui/scss/component/_table.scss index 9d60cf6e8..1535286c3 100644 --- a/ui/scss/component/_table.scss +++ b/ui/scss/component/_table.scss @@ -20,13 +20,13 @@ table.table-standard { font-size: 0.9em; padding: $spacing-vertical/4+1 8px $spacing-vertical/4-2; text-align: left; - border-bottom: 1px solid #e2e2e2; + border-bottom: var(--table-border); img { vertical-align: text-bottom; } } tr.thead:not(:first-child) th { - border-top: 1px solid #e2e2e2; + border-top: var(--table-border); } tfoot td { padding: $spacing-vertical / 2 8px; @@ -35,10 +35,10 @@ table.table-standard { tbody { tr { &:nth-child(even):not(.odd) { - background-color: #f4f4f4; + background-color: var(--table-item-odd); } &:nth-child(odd):not(.even) { - background-color: white; + background-color: var(--table-item-ever); } &.thead { background: none; @@ -52,4 +52,4 @@ table.table-standard { table.table-stretch { width: 100%; -} \ No newline at end of file +} diff --git a/ui/scss/component/_tooltip.scss b/ui/scss/component/_tooltip.scss index 12dc1ee89..18b3d92c3 100644 --- a/ui/scss/component/_tooltip.scss +++ b/ui/scss/component/_tooltip.scss @@ -17,12 +17,12 @@ box-sizing: border-box; padding: $spacing-vertical / 2; width: var(--tooltip-width); - border: 1px solid #aaa; + border: var(--tooltip-border); color: var(--tooltip-color); background-color: var(--tooltip-bg); font-size: calc(var(--font-size) * 7/8); line-height: var(--font-line-height); - box-shadow: var(--tooltip-shadow); + box-shadow: var(--box-shadow-layer); } .tooltip--header .tooltip__link { From 58496c1d3c24559a64afb5ceb280e289202268ed Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 19 Aug 2017 13:04:45 -0600 Subject: [PATCH 040/132] init fix for last review --- CHANGELOG.md | 5 ++--- ui/js/actions/settings.js | 2 ++ ui/js/constants/action_types.js | 3 --- ui/js/constants/settings.js | 1 + ui/js/main.js | 4 ---- ui/js/page/settings/index.js | 7 +------ ui/js/page/settings/view.jsx | 11 +++++------ ui/js/util/setTheme.js | 21 --------------------- ui/scss/_vars.scss | 2 +- ui/scss/component/_table.scss | 2 +- 10 files changed, 13 insertions(+), 45 deletions(-) delete mode 100644 ui/js/util/setTheme.js diff --git a/CHANGELOG.md b/CHANGELOG.md index aae0813e8..adcbd124c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,10 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * Added a new component, `FormFieldPrice` which is now used in Publish and Settings - * Added a theme system to select different themes in Settings. + * Added a new component, `FormFieldPrice` which is now used in Publish and Settings. + * Added a new theme system to select different themes in Settings. * Added a new dark theme. * 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 diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 9b450bb08..977151493 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -46,6 +46,7 @@ export function doSetClientSetting(key, value) { } export function getThemes() { + /* // Themes path const themesPath = `${remote.app.getAppPath()}/dist/themes`; @@ -63,4 +64,5 @@ export function getThemes() { type: types.GET_THEMES, data: { themes }, }; + */ } diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 0ba2af2fe..78d12d2cf 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -85,9 +85,6 @@ export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED"; -// Themes -export const GET_THEMES = "GET_THEMES"; - // User export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED"; export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS"; diff --git a/ui/js/constants/settings.js b/ui/js/constants/settings.js index 5187baea1..97ec0a23a 100644 --- a/ui/js/constants/settings.js +++ b/ui/js/constants/settings.js @@ -3,3 +3,4 @@ export const FIRST_RUN_ACKNOWLEDGED = "welcome_acknowledged"; export const LANGUAGE = "language"; export const SHOW_NSFW = "showNsfw"; export const SHOW_UNAVAILABLE = "showUnavailable"; +export const GET_THEMES = "theme"; diff --git a/ui/js/main.js b/ui/js/main.js index ba880004d..aed81f1c8 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -8,7 +8,6 @@ import store from "store.js"; import SplashScreen from "component/splash"; import { doChangePath, doNavigate, doDaemonReady } from "actions/app"; import { toQueryString } from "util/query_params"; -import setTheme from "util/setTheme"; import * as types from "constants/action_types"; const env = ENV; @@ -72,9 +71,6 @@ document.addEventListener("click", event => { } }); -// Load initial theme -setTheme(lbry.getClientSetting("theme")); - const application = remote.app; const dock = application.dock; const win = remote.getCurrentWindow(); diff --git a/ui/js/page/settings/index.js b/ui/js/page/settings/index.js index a202da461..c74b918af 100644 --- a/ui/js/page/settings/index.js +++ b/ui/js/page/settings/index.js @@ -1,11 +1,7 @@ import React from "react"; import { connect } from "react-redux"; import { doClearCache } from "actions/app"; -import { - doSetDaemonSetting, - doSetClientSetting, - getThemes, -} from "actions/settings"; +import { doSetDaemonSetting, doSetClientSetting } from "actions/settings"; import { selectDaemonSettings, selectShowNsfw } from "selectors/settings"; import SettingsPage from "./view"; @@ -17,7 +13,6 @@ const select = state => ({ const perform = dispatch => ({ setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)), clearCache: () => dispatch(doClearCache()), - getThemes: () => dispatch(getThemes()), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), }); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 423e6d248..f2f89b0a2 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -7,7 +7,6 @@ import lbry from "lbry.js"; import Link from "component/link"; import FormFieldPrice from "component/formFieldPrice"; import { remote } from "electron"; -import setTheme from "util/setTheme"; class SettingsPage extends React.PureComponent { constructor(props) { @@ -21,7 +20,7 @@ class SettingsPage extends React.PureComponent { showUnavailable: lbry.getClientSetting(settings.SHOW_UNAVAILABLE), language: lbry.getClientSetting(settings.LANGUAGE), clearingCache: false, - theme: lbry.getClientSetting("theme"), + theme: lbry.getClientSetting(settings.THEME), themes: [], }; } @@ -40,8 +39,8 @@ class SettingsPage extends React.PureComponent { } getThemes() { - const { themes } = this.props.getThemes().data; - this.setState({ themes }); + //const { themes } = this.props.getThemes().data; + //this.setState({ themes }); } setDaemonSetting(name, value) { @@ -54,8 +53,8 @@ class SettingsPage extends React.PureComponent { } setTheme(value) { - setTheme(value); - this.props.setClientSetting("theme", value); + //setTheme(value); + //this.props.setClientSetting("theme", value); } onRunOnStartChange(event) { diff --git a/ui/js/util/setTheme.js b/ui/js/util/setTheme.js deleted file mode 100644 index 9add03811..000000000 --- a/ui/js/util/setTheme.js +++ /dev/null @@ -1,21 +0,0 @@ -import lbry from "lbry"; -import { existsSync } from "fs"; -import { remote } from "electron"; - -function setTheme(name) { - /* - const link = document.getElementById("theme"); - const file = `${name}.css`; - const path = `${remote.app.getAppPath()}/dist/themes/${file}`; - - if (existsSync(path)) { - link.href = `./themes/${file}`; - lbry.setClientSetting("theme", name); - } else { - link.href = `./themes/light.css`; - lbry.setClientSetting("theme", "light"); - } - */ -} - -export default setTheme; diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index bfa2264ab..3148abd7e 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -106,7 +106,7 @@ --menu-item-hover-bg: var(--color-bg-alt); /* Tooltip */ - --tooltip-body-width: 300px; + --tooltip-width: 300px; --tooltip-bg: var(--color-bg); --tooltip-color: var(--text-color); --tooltip-border: 1px solid #aaa; diff --git a/ui/scss/component/_table.scss b/ui/scss/component/_table.scss index 1535286c3..c6d274296 100644 --- a/ui/scss/component/_table.scss +++ b/ui/scss/component/_table.scss @@ -38,7 +38,7 @@ table.table-standard { background-color: var(--table-item-odd); } &:nth-child(odd):not(.even) { - background-color: var(--table-item-ever); + background-color: var(--table-item-even); } &.thead { background: none; From c87bcb83831316a5e3249f938cebfec6dc7d913d Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 19 Aug 2017 15:34:45 -0600 Subject: [PATCH 041/132] rewrite themes-system -> action / reducer --- ui/dist/index.html | 1 + ui/js/actions/settings.js | 37 ++++++++++++++++++++------------- ui/js/constants/action_types.js | 3 +++ ui/js/constants/settings.js | 3 ++- ui/js/lbry.js | 3 ++- ui/js/page/settings/index.js | 16 ++++++++++++-- ui/js/page/settings/view.jsx | 15 +++++++------ ui/js/reducers/settings.js | 7 +++++++ ui/js/selectors/settings.js | 10 +++++++++ 9 files changed, 69 insertions(+), 26 deletions(-) diff --git a/ui/dist/index.html b/ui/dist/index.html index 4be7ceb5b..29c1e0550 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -6,6 +6,7 @@ + diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 977151493..a51ceb7b4 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -45,24 +45,33 @@ export function doSetClientSetting(key, value) { }; } -export function getThemes() { - /* - // Themes path - const themesPath = `${remote.app.getAppPath()}/dist/themes`; +export function doSetTheme(name) { + const link = document.getElementById("theme"); + + return function(dispatch, getState) { + const { themes } = getState().settings.clientSettings; + const theme = themes.find(theme => theme.name === name); + + link.href = theme.path; + + dispatch(doSetClientSetting("theme", theme)); + }; +} + +export function doGetThemes() { + const path = `${remote.app.getAppPath()}/dist/themes`; // Get all .css files - const files = readdirSync(themesPath).filter(function(file) { - return extname(file) === ".css"; - }); + const files = readdirSync(path).filter(file => extname(file) === ".css"); // Get theme name - const themes = files.map(function(file) { - return file.replace(".css", ""); - }); + const themes = files.map(file => ({ + name: file.replace(".css", ""), + path: `./themes/${file}`, + fullPath: `${path}/${file}`, + })); - return { - type: types.GET_THEMES, - data: { themes }, + return function(dispatch, getState) { + dispatch(doSetClientSetting("themes", themes)); }; - */ } diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 78d12d2cf..942ea11ee 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -85,6 +85,9 @@ export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED"; +// THEMES +export const GET_THEMES = "GET_THEMES"; + // User export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED"; export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS"; diff --git a/ui/js/constants/settings.js b/ui/js/constants/settings.js index 97ec0a23a..b5a2d30b9 100644 --- a/ui/js/constants/settings.js +++ b/ui/js/constants/settings.js @@ -3,4 +3,5 @@ export const FIRST_RUN_ACKNOWLEDGED = "welcome_acknowledged"; export const LANGUAGE = "language"; export const SHOW_NSFW = "showNsfw"; export const SHOW_UNAVAILABLE = "showUnavailable"; -export const GET_THEMES = "theme"; +export const THEME = "theme"; +export const THEMES = "themes"; diff --git a/ui/js/lbry.js b/ui/js/lbry.js index a2f48c064..9591038e3 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -19,7 +19,8 @@ let lbry = { customLighthouseServers: [], showDeveloperMenu: false, language: "en", - theme: "light", + theme: { name: "light", path: "" }, + themes: [], }, }; diff --git a/ui/js/page/settings/index.js b/ui/js/page/settings/index.js index c74b918af..798f31c4a 100644 --- a/ui/js/page/settings/index.js +++ b/ui/js/page/settings/index.js @@ -1,8 +1,18 @@ import React from "react"; import { connect } from "react-redux"; import { doClearCache } from "actions/app"; -import { doSetDaemonSetting, doSetClientSetting } from "actions/settings"; -import { selectDaemonSettings, selectShowNsfw } from "selectors/settings"; +import { + doSetDaemonSetting, + doSetClientSetting, + doSetTheme, + doGetThemes, +} from "actions/settings"; +import { + selectDaemonSettings, + selectShowNsfw, + selectThemes, + selectTheme, +} from "selectors/settings"; import SettingsPage from "./view"; const select = state => ({ @@ -14,6 +24,8 @@ const perform = dispatch => ({ setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)), clearCache: () => dispatch(doClearCache()), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), + setTheme: name => dispatch(doSetTheme(name)), + getThemes: () => dispatch(doGetThemes()), }); export default connect(select, perform)(SettingsPage); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index f2f89b0a2..02f64957d 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -21,7 +21,7 @@ class SettingsPage extends React.PureComponent { language: lbry.getClientSetting(settings.LANGUAGE), clearingCache: false, theme: lbry.getClientSetting(settings.THEME), - themes: [], + themes: lbry.getClientSetting(settings.THEMES), }; } @@ -39,8 +39,7 @@ class SettingsPage extends React.PureComponent { } getThemes() { - //const { themes } = this.props.getThemes().data; - //this.setState({ themes }); + this.props.getThemes(); } setDaemonSetting(name, value) { @@ -53,8 +52,7 @@ class SettingsPage extends React.PureComponent { } setTheme(value) { - //setTheme(value); - //this.props.setClientSetting("theme", value); + this.props.setTheme(value); } onRunOnStartChange(event) { @@ -121,7 +119,6 @@ class SettingsPage extends React.PureComponent { onShowUnavailableChange(event) {} componentDidMount() { - const { themes } = this.state; this.getThemes(); } @@ -252,8 +249,10 @@ class SettingsPage extends React.PureComponent { defaultValue={lbry.getClientSetting("theme")} className="form-field__input--inline" > - {this.state.themes.map((name, index) => - + {this.state.themes.map((theme, index) => + )} diff --git a/ui/js/reducers/settings.js b/ui/js/reducers/settings.js index 4b78284cc..1d5d4cd2a 100644 --- a/ui/js/reducers/settings.js +++ b/ui/js/reducers/settings.js @@ -5,6 +5,7 @@ const reducers = {}; const defaultState = { clientSettings: { showNsfw: lbry.getClientSetting("showNsfw"), + themes: [], }, }; @@ -25,6 +26,12 @@ reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) { }); }; +reducers[types.GET_THEMES] = function(state, action) { + return Object.assign({}, state, { + themes: action.data.themes, + }); +}; + export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/selectors/settings.js b/ui/js/selectors/settings.js index d875ef360..1979e8b17 100644 --- a/ui/js/selectors/settings.js +++ b/ui/js/selectors/settings.js @@ -21,3 +21,13 @@ export const selectShowNsfw = createSelector( selectClientSettings, clientSettings => !!clientSettings.showNsfw ); + +export const selectThemes = createSelector( + selectClientSettings, + clientSettings => clientSettings.themes +); + +export const selectTheme = createSelector( + selectClientSettings, + clientSettings => clientSettings.theme +); From 1233b2d4fde8c38e9bb98781d626c9c91bbdbf6c Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 19 Aug 2017 16:03:40 -0600 Subject: [PATCH 042/132] load initial theme --- ui/js/actions/settings.js | 23 ++++++++++++----------- ui/js/component/app/index.js | 4 +++- ui/js/component/app/view.jsx | 3 +++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index a51ceb7b4..4e360313c 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -45,16 +45,18 @@ export function doSetClientSetting(key, value) { }; } -export function doSetTheme(name) { +export function doSetTheme(themeName) { + const name = themeName || "light"; const link = document.getElementById("theme"); return function(dispatch, getState) { const { themes } = getState().settings.clientSettings; const theme = themes.find(theme => theme.name === name); - link.href = theme.path; - - dispatch(doSetClientSetting("theme", theme)); + if (theme) { + link.href = theme.path; + dispatch(doSetClientSetting("theme", theme)); + } }; } @@ -64,14 +66,13 @@ export function doGetThemes() { // Get all .css files const files = readdirSync(path).filter(file => extname(file) === ".css"); - // Get theme name - const themes = files.map(file => ({ - name: file.replace(".css", ""), - path: `./themes/${file}`, - fullPath: `${path}/${file}`, - })); - return function(dispatch, getState) { + // Find themes + const themes = files.map(file => ({ + name: file.replace(".css", ""), + path: `./themes/${file}`, + })); + dispatch(doSetClientSetting("themes", themes)); }; } diff --git a/ui/js/component/app/index.js b/ui/js/component/app/index.js index 252fdf783..6e3c9bbca 100644 --- a/ui/js/component/app/index.js +++ b/ui/js/component/app/index.js @@ -7,9 +7,10 @@ import { doAlertError, doRecordScroll, } from "actions/app"; -import { doFetchRewardedContent } from "actions/content"; +import { doFetchRewardedContent } from "actions/content"; import { doUpdateBalance } from "actions/wallet"; +import { doSetTheme } from "actions/settings"; import { selectWelcomeModalAcknowledged } from "selectors/app"; import { selectUser } from "selectors/user"; import App from "./view"; @@ -28,6 +29,7 @@ const perform = dispatch => ({ updateBalance: balance => dispatch(doUpdateBalance(balance)), fetchRewardedContent: () => dispatch(doFetchRewardedContent()), recordScroll: scrollPosition => dispatch(doRecordScroll(scrollPosition)), + setTheme: name => dispatch(doSetTheme(name)), }); export default connect(select, perform)(App); diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index 32cb74247..289162068 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -11,6 +11,7 @@ class App extends React.PureComponent { checkUpgradeAvailable, updateBalance, fetchRewardedContent, + setTheme, } = this.props; document.addEventListener("unhandledError", event => { @@ -30,6 +31,8 @@ class App extends React.PureComponent { this.scrollListener = () => this.props.recordScroll(window.scrollY); window.addEventListener("scroll", this.scrollListener); + + setTheme(); } componentWillUnmount() { From 2db24b059f37bc6202df56e51564150ffbe539cd Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 19 Aug 2017 17:59:48 -0600 Subject: [PATCH 043/132] rewrite action -> doSetTheme --- ui/dist/themes/light.css | 6 +++++ ui/js/actions/app.js | 21 +++++++++++++++++- ui/js/actions/settings.js | 43 +++++++++++++----------------------- ui/js/component/app/index.js | 2 ++ ui/js/component/app/view.jsx | 5 +++++ ui/js/lbry.js | 2 +- ui/js/page/settings/index.js | 9 +------- ui/js/page/settings/view.jsx | 8 +------ ui/js/reducers/settings.js | 10 +++------ ui/js/selectors/settings.js | 10 --------- 10 files changed, 54 insertions(+), 62 deletions(-) create mode 100644 ui/dist/themes/light.css diff --git a/ui/dist/themes/light.css b/ui/dist/themes/light.css new file mode 100644 index 000000000..c41b966f8 --- /dev/null +++ b/ui/dist/themes/light.css @@ -0,0 +1,6 @@ +:root { + --color-primary: #155B4A; + --color-canvas: #f5f5f5; + --color-bg: #ffffff; + --color-bg-alt: #D9D9D9; +} diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index e70e9767f..56d7eab7b 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -12,7 +12,7 @@ import { selectHistoryForward, } from "selectors/app"; import { doSearch } from "actions/search"; -import { doFetchDaemonSettings } from "actions/settings"; +import { doFetchDaemonSettings, doSetClientSetting } from "actions/settings"; import { doAuthenticate } from "actions/user"; import { doFileList } from "actions/file_info"; import { toQueryString } from "util/query_params"; @@ -351,3 +351,22 @@ export function doQuit() { remote.app.quit(); }; } + +export function doGetThemes() { + const dir = `${remote.app.getAppPath()}/dist/themes`; + + // Get all .css files + const files = fs + .readdirSync(dir) + .filter(file => path.extname(file) === ".css"); + + return function(dispatch, getState) { + // Find themes + const themes = files.map(file => ({ + name: file.replace(".css", ""), + path: `./themes/${file}`, + })); + + dispatch(doSetClientSetting("themes", themes)); + }; +} diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 4e360313c..313b9e1b8 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -1,8 +1,6 @@ import * as types from "constants/action_types"; +import * as settings from "constants/settings"; import lbry from "lbry"; -import { readdirSync } from "fs"; -import { extname } from "path"; -import { remote } from "electron"; export function doFetchDaemonSettings() { return function(dispatch, getState) { @@ -45,34 +43,23 @@ export function doSetClientSetting(key, value) { }; } -export function doSetTheme(themeName) { - const name = themeName || "light"; - const link = document.getElementById("theme"); - +export function doSetTheme(name) { return function(dispatch, getState) { - const { themes } = getState().settings.clientSettings; - const theme = themes.find(theme => theme.name === name); + const last = lbry.getClientSetting(settings.THEME); + const find = name => themes.find(theme => theme.name === name); - if (theme) { + // Get themes + const themes = lbry.getClientSetting(settings.THEMES); + + // Find theme + const theme = find(name) || find(last) || find("light"); + + if (theme.path) { + // update theme + const link = document.getElementById("theme"); link.href = theme.path; - dispatch(doSetClientSetting("theme", theme)); + + dispatch(doSetClientSetting(settings.THEME, theme.name)); } }; } - -export function doGetThemes() { - const path = `${remote.app.getAppPath()}/dist/themes`; - - // Get all .css files - const files = readdirSync(path).filter(file => extname(file) === ".css"); - - return function(dispatch, getState) { - // Find themes - const themes = files.map(file => ({ - name: file.replace(".css", ""), - path: `./themes/${file}`, - })); - - dispatch(doSetClientSetting("themes", themes)); - }; -} diff --git a/ui/js/component/app/index.js b/ui/js/component/app/index.js index 6e3c9bbca..cf6f89986 100644 --- a/ui/js/component/app/index.js +++ b/ui/js/component/app/index.js @@ -6,6 +6,7 @@ import { doOpenModal, doAlertError, doRecordScroll, + doGetThemes, } from "actions/app"; import { doFetchRewardedContent } from "actions/content"; @@ -29,6 +30,7 @@ const perform = dispatch => ({ updateBalance: balance => dispatch(doUpdateBalance(balance)), fetchRewardedContent: () => dispatch(doFetchRewardedContent()), recordScroll: scrollPosition => dispatch(doRecordScroll(scrollPosition)), + getThemes: () => dispatch(doGetThemes()), setTheme: name => dispatch(doSetTheme(name)), }); diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index 289162068..e28667c08 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -11,6 +11,7 @@ class App extends React.PureComponent { checkUpgradeAvailable, updateBalance, fetchRewardedContent, + getThemes, setTheme, } = this.props; @@ -32,6 +33,10 @@ class App extends React.PureComponent { window.addEventListener("scroll", this.scrollListener); + // Load themes + getThemes(); + + // Select theme setTheme(); } diff --git a/ui/js/lbry.js b/ui/js/lbry.js index 9591038e3..2524c738b 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -19,7 +19,7 @@ let lbry = { customLighthouseServers: [], showDeveloperMenu: false, language: "en", - theme: { name: "light", path: "" }, + theme: "light", themes: [], }, }; diff --git a/ui/js/page/settings/index.js b/ui/js/page/settings/index.js index 798f31c4a..5764e9dac 100644 --- a/ui/js/page/settings/index.js +++ b/ui/js/page/settings/index.js @@ -5,14 +5,8 @@ import { doSetDaemonSetting, doSetClientSetting, doSetTheme, - doGetThemes, } from "actions/settings"; -import { - selectDaemonSettings, - selectShowNsfw, - selectThemes, - selectTheme, -} from "selectors/settings"; +import { selectDaemonSettings, selectShowNsfw } from "selectors/settings"; import SettingsPage from "./view"; const select = state => ({ @@ -25,7 +19,6 @@ const perform = dispatch => ({ clearCache: () => dispatch(doClearCache()), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setTheme: name => dispatch(doSetTheme(name)), - getThemes: () => dispatch(doGetThemes()), }); export default connect(select, perform)(SettingsPage); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 02f64957d..be847a69a 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -38,10 +38,6 @@ class SettingsPage extends React.PureComponent { setTimeout(clear, 1000, { once: true }); } - getThemes() { - this.props.getThemes(); - } - setDaemonSetting(name, value) { this.props.setDaemonSetting(name, value); } @@ -118,9 +114,7 @@ class SettingsPage extends React.PureComponent { onShowUnavailableChange(event) {} - componentDidMount() { - this.getThemes(); - } + componentDidMount() {} render() { const { daemonSettings } = this.props; diff --git a/ui/js/reducers/settings.js b/ui/js/reducers/settings.js index 1d5d4cd2a..6dc59a068 100644 --- a/ui/js/reducers/settings.js +++ b/ui/js/reducers/settings.js @@ -1,11 +1,13 @@ import * as types from "constants/action_types"; +import * as settings from "constants/settings"; import lbry from "lbry"; const reducers = {}; const defaultState = { clientSettings: { showNsfw: lbry.getClientSetting("showNsfw"), - themes: [], + theme: lbry.getClientSetting(settings.THEME), + themes: lbry.getClientSetting(settings.THEMES), }, }; @@ -26,12 +28,6 @@ reducers[types.CLIENT_SETTING_CHANGED] = function(state, action) { }); }; -reducers[types.GET_THEMES] = function(state, action) { - return Object.assign({}, state, { - themes: action.data.themes, - }); -}; - export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/selectors/settings.js b/ui/js/selectors/settings.js index 1979e8b17..d875ef360 100644 --- a/ui/js/selectors/settings.js +++ b/ui/js/selectors/settings.js @@ -21,13 +21,3 @@ export const selectShowNsfw = createSelector( selectClientSettings, clientSettings => !!clientSettings.showNsfw ); - -export const selectThemes = createSelector( - selectClientSettings, - clientSettings => clientSettings.themes -); - -export const selectTheme = createSelector( - selectClientSettings, - clientSettings => clientSettings.theme -); From 4ddecf2aaa87b720d664c2f1ab3d9a8f2b07a929 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 19 Aug 2017 23:58:03 -0600 Subject: [PATCH 044/132] implement dark theme --- ui/dist/themes/dark.css | 33 ++++++++++++++++++++++++++++++ ui/js/component/app/view.jsx | 10 ++++----- ui/scss/_gui.scss | 1 + ui/scss/_vars.scss | 6 ++++++ ui/scss/component/_form-field.scss | 5 +++++ ui/scss/component/_header.scss | 3 ++- 6 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 ui/dist/themes/dark.css diff --git a/ui/dist/themes/dark.css b/ui/dist/themes/dark.css new file mode 100644 index 000000000..e83cab517 --- /dev/null +++ b/ui/dist/themes/dark.css @@ -0,0 +1,33 @@ +:root { + /* Colors */ + --color-primary: #009688; + --color-canvas: #0f1517; + --color-bg: #1a2327; + --color-bg-alt: #314048; + --color-help: #AAA; + --color-error: #a94442; + --color-load-screen-text: #FFF; + --color-money: var(--color-primary); + --color-meta-light: #757575; + --color-dark-overlay: rgb(15, 21, 23, 0.85); + + /* Text */ + --text-color: #FFF; + + /* Input */ + --input-bg: transparent; + --input-active-bg: rgba(0,0,0, 0.65); + --input-border-color: rgba(255,255,255, 0.25); + + /* Search */ + --search-bg: rgba(0,0,0, 0.45); + --search-active-bg: rgba(0,0,0, 0.75); + --search-border: 1px solid rgba(0,0,0, 0.5); + + /* Select */ + --select-bg: var(--color-bg-alt); + + /* Header */ + --header-color: #EEE; + --header-active-color: #FFF; +} diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index e28667c08..6efe7db7e 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -19,6 +19,10 @@ class App extends React.PureComponent { alertError(event.detail); }); + getThemes(); + + setTheme(); + if (!this.props.upgradeSkipped) { checkUpgradeAvailable(); } @@ -32,12 +36,6 @@ class App extends React.PureComponent { this.scrollListener = () => this.props.recordScroll(window.scrollY); window.addEventListener("scroll", this.scrollListener); - - // Load themes - getThemes(); - - // Select theme - setTheme(); } componentWillUnmount() { diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index 1c484c68b..7e4d93f1d 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -7,6 +7,7 @@ html } body { + color: var(--text-color); font-family: 'Source Sans Pro', sans-serif; line-height: var(--font-line-height); } diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 3148abd7e..95e394126 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -19,6 +19,7 @@ --color-bg: #ffffff; --color-bg-alt: #D9D9D9; + /* Misc */ --content-max-width: 1000px; --nsfw-blur-intensity: 20px; @@ -50,9 +51,14 @@ /* Input */ --input-width: 330px; + --input-color: var(--text-color); --input-border-size: 2px; --input-border-color: rgba(0,0,0,.25); + /* Select */ + --select-bg: var(--color-bg-alt); + --select-color: var(--text-color); + /* Button */ --button-bg: var(--color-bg-alt); --button-color: #FFF; diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index 841d58d62..8e2547c54 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -46,6 +46,8 @@ input[type="text"].input-copyable { padding-left: 5px; padding-right: 5px; height: $spacing-vertical; + background: var(--select-bg); + color: var(--select-color); &:focus { outline: var(--input-border-size) solid var(--color-primary); } @@ -67,6 +69,8 @@ input[type="text"].input-copyable { padding-right: 1px; box-sizing: border-box; -webkit-appearance: none; + background: var(--input-bg); + color: var(--input-color); &[readonly] { background-color: #bbb; } @@ -82,6 +86,7 @@ input[type="text"].input-copyable { line-height: 1; padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; + &.form-field__input--error { border-color: var(--color-error); } diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index 0d01abe1c..f27cb4e00 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -45,8 +45,9 @@ padding-right: 5px; @include border-radius(2px); border: var(--search-border); - transition: all var(--transition-duration) var(--transition-type); + transition: box-shadow var(--transition-duration) var(--transition-type); &:focus { + background: var(--search-active-bg); color: var(--search-active-color); box-shadow: var(--box-shadow-focus); border-color: var(--color-primary); From a2cc9afe0504b707b1eb476c10b1bab185f59968 Mon Sep 17 00:00:00 2001 From: hackrush Date: Sun, 20 Aug 2017 15:21:57 +0530 Subject: [PATCH 045/132] Displays additional fields in the transaction list --- ui/js/actions/claims.js | 2 +- ui/js/component/transactionList/index.js | 2 ++ ui/js/component/transactionList/view.jsx | 30 +++++++++++++++++++++++- ui/js/selectors/wallet.js | 4 ++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js index 46557da57..71f94852c 100644 --- a/ui/js/actions/claims.js +++ b/ui/js/actions/claims.js @@ -47,7 +47,7 @@ export function doSendSupport(amount, claim_id) { }; lbry - .claim_send_tip({ + .wallet_send({ claim_id: claim_id, amount: amount, }) diff --git a/ui/js/component/transactionList/index.js b/ui/js/component/transactionList/index.js index 7e15a67b4..c650e9eac 100644 --- a/ui/js/component/transactionList/index.js +++ b/ui/js/component/transactionList/index.js @@ -1,5 +1,6 @@ import React from "react"; import { connect } from "react-redux"; +import { doNavigate } from "actions/app"; import { doFetchTransactions } from "actions/wallet"; import { selectBalance, @@ -15,6 +16,7 @@ const select = state => ({ }); const perform = dispatch => ({ + navigate: (path, params) => dispatch(doNavigate(path, params)), fetchTransactions: () => dispatch(doFetchTransactions()), }); diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index db913eea6..6879e3349 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -7,13 +7,38 @@ class TransactionList extends React.PureComponent { } render() { - const { fetchingTransactions, transactionItems } = this.props; + const { fetchingTransactions, transactionItems, navigate } = this.props; + + function findTypeOfTx(type, is_tip) { + if (is_tip && type === "support") return "tip"; + else return type; + } + + function getClaimLink(claim_name, claim_id) { + if (claim_id !== "----" && claim_name !== "----") { + let uri = `lbry://${claim_name}#${claim_id}`; + + return ( + + navigate("/show", { uri })} + > + {claim_name} + + + ); + } + + return {__("N/A")}; + } const rows = []; if (transactionItems.length > 0) { transactionItems.forEach(function(item) { rows.push( + {findTypeOfTx(item.type, item.is_tip)} {(item.amount > 0 ? "+" : "") + item.amount} {item.date @@ -25,6 +50,7 @@ class TransactionList extends React.PureComponent { ? item.date.toLocaleTimeString() : {__("(Transaction pending)")}} + {getClaimLink(item.claim_name, item.claim_id)} + {__("Type")} {__("Amount")} {__("Date")} {__("Time")} + {__("Claim")} {__("Transaction")} diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index 1027bb6e7..f5aa533d2 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -29,6 +29,10 @@ export const selectTransactionItems = createSelector( id: txid, date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, amount: parseFloat(tx.value), + type: tx.type, + claim_id: tx.claim_id, + claim_name: tx.claim_name, + is_tip: tx.is_tip, }); }); return transactionItems.reverse(); From af46f8a73c4860969f9eac5da24287a566c132a7 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 20 Aug 2017 09:52:09 -0600 Subject: [PATCH 046/132] remove unused constant --- ui/js/constants/action_types.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 942ea11ee..78d12d2cf 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -85,9 +85,6 @@ export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; export const CLIENT_SETTING_CHANGED = "CLIENT_SETTING_CHANGED"; -// THEMES -export const GET_THEMES = "GET_THEMES"; - // User export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED"; export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS"; From d8f71eba6d84a534b0ef784a98d0b8b3610eebaa Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 20 Aug 2017 11:07:26 -0600 Subject: [PATCH 047/132] minor fix for dark theme --- ui/dist/themes/dark.css | 12 ++++++++++-- ui/scss/component/_form-field.scss | 10 +++++++--- ui/scss/component/_header.scss | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ui/dist/themes/dark.css b/ui/dist/themes/dark.css index e83cab517..088d667fc 100644 --- a/ui/dist/themes/dark.css +++ b/ui/dist/themes/dark.css @@ -16,18 +16,26 @@ /* Input */ --input-bg: transparent; - --input-active-bg: rgba(0,0,0, 0.65); + --input-active-bg: rgba(0,0,0, 0.5); --input-border-color: rgba(255,255,255, 0.25); /* Search */ --search-bg: rgba(0,0,0, 0.45); + --search-color: #757575; --search-active-bg: rgba(0,0,0, 0.75); - --search-border: 1px solid rgba(0,0,0, 0.5); + --search-border: 1px solid rgba(0,0,0, 0.25); /* Select */ --select-bg: var(--color-bg-alt); + --tab-color: #757575; + --tab-active-color: #CCC; /* Header */ --header-color: #EEE; --header-active-color: #FFF; + + /* Table */ + --table-border: 0; + --table-item-even: var(--color-bg-alt); + --table-item-odd: transparent; } diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index 8e2547c54..7fc276ddd 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -21,7 +21,9 @@ } input[type="text"].input-copyable { - border: 1px solid var(--input-border-color); + background: var(--input-bg); + border-bottom: var(--input-border-size) solid var(--input-border-color); + color: var(--input-color); line-height: 1; padding-top: $spacing-vertical * 1/3; padding-bottom: $spacing-vertical * 1/3; @@ -29,7 +31,7 @@ input[type="text"].input-copyable { padding-left: 5px; padding-right: 5px; width: 100%; - &:focus { border-color: black; } + &:focus { border-color: var(--color-primary); } } .form-field { @@ -72,7 +74,7 @@ input[type="text"].input-copyable { background: var(--input-bg); color: var(--input-color); &[readonly] { - background-color: #bbb; + background-color: var(--input-bg); } } @@ -107,6 +109,7 @@ input[type="text"].input-copyable { input[type="search"]:focus, input[type="date"]:focus { border-color: var(--color-primary); + background: var(--input-active-bg); } textarea { @@ -119,6 +122,7 @@ input[type="text"].input-copyable { } .form-field__label { + color: var(--color-help); &[for] { cursor: pointer; } > input[type="checkbox"], input[type="radio"] { margin-right: 6px; diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index f27cb4e00..e26c2aa9f 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -68,6 +68,7 @@ nav.sub-header padding: 0 5px; line-height:calc(var(--header-height) - $spacing-vertical - var(--tab-border-size)); color: var(--tab-color); + &:first-child { margin-left: 0; From 66af58940a415767e2534f7228116fb7d08f19e7 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 20 Aug 2017 12:13:17 -0600 Subject: [PATCH 048/132] tidy up dark theme --- ui/dist/themes/dark.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/dist/themes/dark.css b/ui/dist/themes/dark.css index 088d667fc..9c2f6d197 100644 --- a/ui/dist/themes/dark.css +++ b/ui/dist/themes/dark.css @@ -25,8 +25,7 @@ --search-active-bg: rgba(0,0,0, 0.75); --search-border: 1px solid rgba(0,0,0, 0.25); - /* Select */ - --select-bg: var(--color-bg-alt); + /* Tab */ --tab-color: #757575; --tab-active-color: #CCC; From 3c7f1761bbbdd034da0b86f17f16ab2c3b07d617 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 21 Aug 2017 20:23:38 -0600 Subject: [PATCH 049/132] minor fixes for overall scss / themes --- ui/dist/themes/dark.css | 7 ++++++- ui/scss/_gui.scss | 2 +- ui/scss/_vars.scss | 1 + ui/scss/component/_header.scss | 4 ++++ ui/scss/component/_modal.scss | 2 +- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ui/dist/themes/dark.css b/ui/dist/themes/dark.css index 9c2f6d197..d6daa1d38 100644 --- a/ui/dist/themes/dark.css +++ b/ui/dist/themes/dark.css @@ -9,7 +9,7 @@ --color-load-screen-text: #FFF; --color-money: var(--color-primary); --color-meta-light: #757575; - --color-dark-overlay: rgb(15, 21, 23, 0.85); + --color-dark-overlay: rgba(15, 21, 23, 0.85); /* Text */ --text-color: #FFF; @@ -32,9 +32,14 @@ /* Header */ --header-color: #EEE; --header-active-color: #FFF; + --header-button-bg: transparent; /* Table */ --table-border: 0; --table-item-even: var(--color-bg-alt); --table-item-odd: transparent; + + /* Modla */ + --modal-overlay-bg: var(--color-dark-overlay); + --modal-border: 1px solid rgba(0, 0, 0, 0.25); } diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index 7e4d93f1d..59646f480 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -94,7 +94,7 @@ sub { top: 0.4em; } code { font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace; - background-color: #eee; + background-color: var(--color-bg-alt); } p diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 95e394126..75783d391 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -72,6 +72,7 @@ --header-color: #666; --header-active-color: rgba(0,0,0, 0.85); --header-height: $spacing-vertical * 2.5; + --header-button-bg: var(--button-bg); /* Header -> search */ --search-bg: rgba(255, 255, 255, 0.7); diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index e26c2aa9f..4f7eac1e3 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -18,7 +18,11 @@ flex: 0 0 content; padding-left: $spacing-vertical / 4; padding-right: $spacing-vertical / 4; + .button-alt { + background: var(--header-button-bg) !important; + } } + .header__item--wunderbar { flex-grow: 1; } diff --git a/ui/scss/component/_modal.scss b/ui/scss/component/_modal.scss index f367e45f3..7140e6cf8 100644 --- a/ui/scss/component/_modal.scss +++ b/ui/scss/component/_modal.scss @@ -74,7 +74,7 @@ width: 400px; } .error-modal__error-list { /*shitty hack/temp fix for long errors making modal unusable*/ - border: 1px solid #eee; + border: 1px solid var(--input-border-color); padding: 8px; list-style: none; max-height: 400px; From a77a6495b06c96630fdee45d1a919aae9b165a2e Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 21 Aug 2017 20:43:14 -0600 Subject: [PATCH 050/132] tidy up themes --- ui/dist/themes/dark.css | 1 + ui/dist/themes/light.css | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/dist/themes/dark.css b/ui/dist/themes/dark.css index d6daa1d38..45b297835 100644 --- a/ui/dist/themes/dark.css +++ b/ui/dist/themes/dark.css @@ -13,6 +13,7 @@ /* Text */ --text-color: #FFF; + --text-selection-bg: rgba(0,150,136, 0.95); /* Input */ --input-bg: transparent; diff --git a/ui/dist/themes/light.css b/ui/dist/themes/light.css index c41b966f8..c95f61136 100644 --- a/ui/dist/themes/light.css +++ b/ui/dist/themes/light.css @@ -1,6 +1,4 @@ :root { + /* Colors */ --color-primary: #155B4A; - --color-canvas: #f5f5f5; - --color-bg: #ffffff; - --color-bg-alt: #D9D9D9; } From 191b95cc2ea9f969f59c10a3249d7d5fea67fd76 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 24 Aug 2017 10:11:39 -0600 Subject: [PATCH 051/132] load theme on /doDaemonReady --- ui/js/actions/app.js | 22 ++-------------------- ui/js/actions/settings.js | 22 ++++++++++++++++++++++ ui/js/component/app/index.js | 4 ---- ui/js/component/app/view.jsx | 6 ------ 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 56d7eab7b..ac757496a 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -12,7 +12,7 @@ import { selectHistoryForward, } from "selectors/app"; import { doSearch } from "actions/search"; -import { doFetchDaemonSettings, doSetClientSetting } from "actions/settings"; +import { doFetchDaemonSettings, doSetTheme } from "actions/settings"; import { doAuthenticate } from "actions/user"; import { doFileList } from "actions/file_info"; import { toQueryString } from "util/query_params"; @@ -320,6 +320,7 @@ export function doDaemonReady() { type: types.DAEMON_READY, data: { page }, }); + dispatch(doSetTheme()); dispatch(doFetchDaemonSettings()); dispatch(doFileList()); }; @@ -351,22 +352,3 @@ export function doQuit() { remote.app.quit(); }; } - -export function doGetThemes() { - const dir = `${remote.app.getAppPath()}/dist/themes`; - - // Get all .css files - const files = fs - .readdirSync(dir) - .filter(file => path.extname(file) === ".css"); - - return function(dispatch, getState) { - // Find themes - const themes = files.map(file => ({ - name: file.replace(".css", ""), - path: `./themes/${file}`, - })); - - dispatch(doSetClientSetting("themes", themes)); - }; -} diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 313b9e1b8..064651725 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -2,6 +2,11 @@ import * as types from "constants/action_types"; import * as settings from "constants/settings"; import lbry from "lbry"; +const { remote } = require("electron"); +const { extname } = require("path"); +const { download } = remote.require("electron-dl"); +const { readdirSync } = remote.require("fs"); + export function doFetchDaemonSettings() { return function(dispatch, getState) { lbry.settings_get().then(settings => { @@ -43,6 +48,23 @@ export function doSetClientSetting(key, value) { }; } +export function doGetThemes() { + const dir = `${remote.app.getAppPath()}/dist/themes`; + + // Get all .css files + const files = readdirSync(dir).filter(file => extname(file) === ".css"); + + return function(dispatch, getState) { + // Find themes + const themes = files.map(file => ({ + name: file.replace(".css", ""), + path: `./themes/${file}`, + })); + + dispatch(doSetClientSetting("themes", themes)); + }; +} + export function doSetTheme(name) { return function(dispatch, getState) { const last = lbry.getClientSetting(settings.THEME); diff --git a/ui/js/component/app/index.js b/ui/js/component/app/index.js index cf6f89986..9f13465c7 100644 --- a/ui/js/component/app/index.js +++ b/ui/js/component/app/index.js @@ -6,12 +6,10 @@ import { doOpenModal, doAlertError, doRecordScroll, - doGetThemes, } from "actions/app"; import { doFetchRewardedContent } from "actions/content"; import { doUpdateBalance } from "actions/wallet"; -import { doSetTheme } from "actions/settings"; import { selectWelcomeModalAcknowledged } from "selectors/app"; import { selectUser } from "selectors/user"; import App from "./view"; @@ -30,8 +28,6 @@ const perform = dispatch => ({ updateBalance: balance => dispatch(doUpdateBalance(balance)), fetchRewardedContent: () => dispatch(doFetchRewardedContent()), recordScroll: scrollPosition => dispatch(doRecordScroll(scrollPosition)), - getThemes: () => dispatch(doGetThemes()), - setTheme: name => dispatch(doSetTheme(name)), }); export default connect(select, perform)(App); diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index 6efe7db7e..32cb74247 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -11,18 +11,12 @@ class App extends React.PureComponent { checkUpgradeAvailable, updateBalance, fetchRewardedContent, - getThemes, - setTheme, } = this.props; document.addEventListener("unhandledError", event => { alertError(event.detail); }); - getThemes(); - - setTheme(); - if (!this.props.upgradeSkipped) { checkUpgradeAvailable(); } From 8b8c9c9da935fd47052fc8d6b3635d48dd3a4fa7 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 24 Aug 2017 10:14:30 -0600 Subject: [PATCH 052/132] fix settings constant --- ui/js/actions/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 064651725..52a1fee9d 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -61,7 +61,7 @@ export function doGetThemes() { path: `./themes/${file}`, })); - dispatch(doSetClientSetting("themes", themes)); + dispatch(doSetClientSetting(settings.THEMES, themes)); }; } From c257691b57a39feef2b089995f9f0c90332d1a2c Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 24 Aug 2017 10:29:54 -0600 Subject: [PATCH 053/132] move getThemes -> settings -> componentWillMount --- ui/js/page/settings/index.js | 2 ++ ui/js/page/settings/view.jsx | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/ui/js/page/settings/index.js b/ui/js/page/settings/index.js index 5764e9dac..8516f55f4 100644 --- a/ui/js/page/settings/index.js +++ b/ui/js/page/settings/index.js @@ -4,6 +4,7 @@ import { doClearCache } from "actions/app"; import { doSetDaemonSetting, doSetClientSetting, + doGetThemes, doSetTheme, } from "actions/settings"; import { selectDaemonSettings, selectShowNsfw } from "selectors/settings"; @@ -19,6 +20,7 @@ const perform = dispatch => ({ clearCache: () => dispatch(doClearCache()), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setTheme: name => dispatch(doSetTheme(name)), + getThemes: () => dispatch(doGetThemes), }); export default connect(select, perform)(SettingsPage); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index be847a69a..54dc969a0 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -51,6 +51,10 @@ class SettingsPage extends React.PureComponent { this.props.setTheme(value); } + getThemes() { + this.props.getThemes(); + } + onRunOnStartChange(event) { this.setDaemonSetting("run_on_startup", event.target.checked); } @@ -114,6 +118,10 @@ class SettingsPage extends React.PureComponent { onShowUnavailableChange(event) {} + componentWillMount() { + this.getThemes(); + } + componentDidMount() {} render() { From 8e7c783750523a9b60f722b526ffeab2d63c6c8b Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 24 Aug 2017 10:55:24 -0600 Subject: [PATCH 054/132] rewrite fallback for themes --- ui/js/actions/app.js | 4 +++- ui/js/actions/settings.js | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index ac757496a..a3b63578c 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -1,4 +1,5 @@ import * as types from "constants/action_types"; +import * as settings from "constants/settings"; import lbry from "lbry"; import { selectUpdateUrl, @@ -320,7 +321,8 @@ export function doDaemonReady() { type: types.DAEMON_READY, data: { page }, }); - dispatch(doSetTheme()); + // Load last theme selected + dispatch(doSetTheme(lbry.getClientSetting(settings.THEME))); dispatch(doFetchDaemonSettings()); dispatch(doFileList()); }; diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 52a1fee9d..be614c7f5 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -67,20 +67,21 @@ export function doGetThemes() { export function doSetTheme(name) { return function(dispatch, getState) { - const last = lbry.getClientSetting(settings.THEME); - const find = name => themes.find(theme => theme.name === name); + // Find a theme from themes list + const find = themeName => themes.find(theme => theme.name === themeName); // Get themes const themes = lbry.getClientSetting(settings.THEMES); - // Find theme - const theme = find(name) || find(last) || find("light"); + // Find theme and set fallback + const theme = find(name) || find("light"); if (theme.path) { - // update theme + // load css const link = document.getElementById("theme"); link.href = theme.path; + // update theme dispatch(doSetClientSetting(settings.THEME, theme.name)); } }; From 4185f22cb22fe60e82aeab40e210e321d49a703d Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 24 Aug 2017 11:06:21 -0600 Subject: [PATCH 055/132] update dark theme -> header color -> #ccc --- ui/dist/themes/dark.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/dist/themes/dark.css b/ui/dist/themes/dark.css index 45b297835..c32108393 100644 --- a/ui/dist/themes/dark.css +++ b/ui/dist/themes/dark.css @@ -31,7 +31,7 @@ --tab-active-color: #CCC; /* Header */ - --header-color: #EEE; + --header-color: #CCC; --header-active-color: #FFF; --header-button-bg: transparent; From 0054723ed6ac72aa9f821c05fd30ee0e02970d34 Mon Sep 17 00:00:00 2001 From: hackrush Date: Fri, 25 Aug 2017 18:56:43 +0530 Subject: [PATCH 056/132] Added Fee column --- ui/js/component/transactionList/view.jsx | 6 ++++-- ui/js/selectors/wallet.js | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index 6879e3349..5b06f5f8f 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -10,12 +10,12 @@ class TransactionList extends React.PureComponent { const { fetchingTransactions, transactionItems, navigate } = this.props; function findTypeOfTx(type, is_tip) { - if (is_tip && type === "support") return "tip"; + if (is_tip && type === "Support") return "Tip"; else return type; } function getClaimLink(claim_name, claim_id) { - if (claim_id !== "----" && claim_name !== "----") { + if (claim_id !== "" && claim_name !== "") { let uri = `lbry://${claim_name}#${claim_id}`; return ( @@ -40,6 +40,7 @@ class TransactionList extends React.PureComponent { {findTypeOfTx(item.type, item.is_tip)} {(item.amount > 0 ? "+" : "") + item.amount} + {item.fee} {item.date ? item.date.toLocaleDateString() @@ -81,6 +82,7 @@ class TransactionList extends React.PureComponent { {__("Type")} {__("Amount")} + {__("Fee")} {__("Date")} {__("Time")} {__("Claim")} diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index f5aa533d2..6637c8bff 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -30,6 +30,7 @@ export const selectTransactionItems = createSelector( date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, amount: parseFloat(tx.value), type: tx.type, + fee: tx.fee, claim_id: tx.claim_id, claim_name: tx.claim_name, is_tip: tx.is_tip, From e8c5ba5536f445b99e221ff4828e4d03eec62a1d Mon Sep 17 00:00:00 2001 From: hackrush Date: Fri, 25 Aug 2017 23:33:33 +0530 Subject: [PATCH 057/132] Tipping UI is rendered in FilePage --- ui/js/component/fileActions/view.jsx | 26 +++----- ui/js/component/tipLink/view.jsx | 92 ++++++++++------------------ ui/js/page/filePage/view.jsx | 38 +++++++++++- 3 files changed, 74 insertions(+), 82 deletions(-) diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 1b0c2670a..cd5700e86 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,7 +1,6 @@ import React from "react"; import { Icon, BusyMessage } from "component/common"; import FilePrice from "component/filePrice"; -import TipLink from "component/tipLink"; import { Modal } from "component/modal"; import Link from "component/link"; import { ToolTip } from "component/tooltip"; @@ -14,7 +13,6 @@ class FileActions extends React.PureComponent { super(props); this.state = { forceShowActions: false, - showTipBox: false, }; } @@ -59,16 +57,8 @@ class FileActions extends React.PureComponent { this.props.loadVideo(this.props.uri); } - handleTipShow() { - this.setState({ - showTipBox: true, - }); - } - - handleTipHide() { - this.setState({ - showTipBox: false, - }); + handleSupportButtonClicked() { + this.props.onTipShow(); } render() { @@ -90,8 +80,6 @@ class FileActions extends React.PureComponent { claimInfo, } = this.props; - const { showTipBox } = this.state; - const metadata = fileInfo ? fileInfo.metadata : null, openInFolderMessage = platform.startsWith("Mac") ? __("Open in Finder") @@ -183,11 +171,11 @@ class FileActions extends React.PureComponent { return (
{showTipBox ? "" : content} - {showMenu && !showTipBox ? diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 432e24004..4fbd111c3 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -1,28 +1,20 @@ import React from "react"; import Link from "component/link"; -import FormFieldPrice from "component/formFieldPrice"; +import { FormRow } from "component/form"; class TipLink extends React.PureComponent { constructor(props) { super(props); this.state = { - feeAmount: "1.00", - currency: "LBC", + tipAmount: "1.00", }; } - handleSupportButtonClicked() { - this.resetDefaults(); - this.props.onTipShow(); - } - handleSendButtonClicked() { let claim_id = this.props.claim_id; - let amount = this.state.feeAmount; - + let amount = this.state.tipAmount; this.props.sendSupport(amount, claim_id); - this.props.onTipHide(); } @@ -30,61 +22,41 @@ class TipLink extends React.PureComponent { this.props.onTipHide(); } - handleSupportPriceChange(newValue) { + handleSupportPriceChange(event) { this.setState({ - feeAmount: newValue.amount, - feeCurrency: newValue.currency, - }); - } - - resetDefaults() { - this.setState({ - feeAmount: "1.00", - currency: "LBC", + tipAmount: event.target.value, }); } render() { - const { showTipBox } = this.props; - const { feeAmount, currency } = this.state; - - let tipLink = ( - - ); - - let tipBox = ( - - this.handleSupportPriceChange(value)} - defaultValue={{ amount: feeAmount, currency: currency }} - /> - - -
- {__("This sends the entered amount of LBCs to the publisher.")} -
-
- ); - return ( -
- {showTipBox ? tipBox : tipLink} +
+
+

{__("Support Claim")}

+
+
+ this.handleSupportPriceChange(event)} + /> +
+
+ + +
); } diff --git a/ui/js/page/filePage/view.jsx b/ui/js/page/filePage/view.jsx index 3ca23aadc..d3c633015 100644 --- a/ui/js/page/filePage/view.jsx +++ b/ui/js/page/filePage/view.jsx @@ -3,6 +3,7 @@ import ReactMarkdown from "react-markdown"; import lbry from "lbry.js"; import lbryuri from "lbryuri.js"; import Video from "component/video"; +import TipLink from "component/tipLink"; import { Thumbnail } from "component/common"; import FilePrice from "component/filePrice"; import FileActions from "component/fileActions"; @@ -33,6 +34,13 @@ const FormatItem = props => { }; class FilePage extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + showTipBox: false, + }; + } + componentDidMount() { this.fetchFileInfo(this.props); this.fetchCostInfo(this.props); @@ -54,6 +62,18 @@ class FilePage extends React.PureComponent { } } + handleTipShow() { + this.setState({ + showTipBox: true, + }); + } + + handleTipHide() { + this.setState({ + showTipBox: false, + }); + } + render() { const { claim, @@ -64,6 +84,8 @@ class FilePage extends React.PureComponent { rewardedContentClaimIds, } = this.props; + const { showTipBox } = this.state; + if (!claim || !metadata) { return ( {__("Empty claim or metadata info.")} @@ -111,7 +133,7 @@ class FilePage extends React.PureComponent { {!fileInfo || fileInfo.written_bytes <= 0 ? - {isRewardContent && {" "} } + {isRewardContent && {" "}} : null}

{title}

@@ -126,7 +148,10 @@ class FilePage extends React.PureComponent { : uriIndicator}
- +
@@ -137,11 +162,18 @@ class FilePage extends React.PureComponent { />
- {metadata + {metadata && !showTipBox ?
: ""} + {showTipBox + ? + : ""}
Date: Sat, 26 Aug 2017 00:11:31 +0530 Subject: [PATCH 058/132] Fix the Mega Breaking change --- ui/js/component/fileActions/view.jsx | 4 ++-- ui/js/component/tipLink/view.jsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index cd5700e86..cd2df769c 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -170,14 +170,14 @@ class FileActions extends React.PureComponent { return (
- {showTipBox ? "" : content} + {content} - {showMenu && !showTipBox + {showMenu ? Date: Sat, 26 Aug 2017 00:55:53 +0530 Subject: [PATCH 059/132] Removed useless css --- ui/scss/component/_form-field.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index a6631c0f5..9dee7240b 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -165,8 +165,4 @@ input[type="text"].input-copyable { .form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll { height: auto; -} - -.form-field--tip { - padding-right: 15px; } \ No newline at end of file From 55cd9123f2f2e6d5ed32f335a572728d35b16f27 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 26 Aug 2017 13:04:44 -0600 Subject: [PATCH 060/132] fix export / import error --- ui/js/actions/settings.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 25731e135..6253b1ad7 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -88,8 +88,9 @@ export function doSetTheme(name) { // update theme dispatch(doSetClientSetting(settings.THEME, theme.name)); } + }; } - + export function doDownloadLanguage(langFile) { return function(dispatch, getState) { const destinationPath = `app/locales/${langFile}`; From f6857313ad29869b203244d90d2190c7aed0a3dd Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 26 Aug 2017 14:47:37 -0600 Subject: [PATCH 061/132] fix markdown-editor styles --- ui/scss/_vars.scss | 2 + ui/scss/all.scss | 1 + ui/scss/component/_markdown-editor.scss | 125 ++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 ui/scss/component/_markdown-editor.scss diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 75783d391..6af7932b1 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -50,6 +50,8 @@ --window-bg: var(--color-canvas); /* Input */ + --input-bg: transparent; + --input-active-bg: transparent; --input-width: 330px; --input-color: var(--text-color); --input-border-size: 2px; diff --git a/ui/scss/all.scss b/ui/scss/all.scss index a63c6ec13..7dfd15d34 100644 --- a/ui/scss/all.scss +++ b/ui/scss/all.scss @@ -19,6 +19,7 @@ @import "component/_snack-bar.scss"; @import "component/_video.scss"; @import "component/_pagination.scss"; +@import "component/_markdown-editor.scss"; @import "page/_developer.scss"; @import "page/_reward.scss"; @import "page/_show.scss"; diff --git a/ui/scss/component/_markdown-editor.scss b/ui/scss/component/_markdown-editor.scss new file mode 100644 index 000000000..9691ce7ce --- /dev/null +++ b/ui/scss/component/_markdown-editor.scss @@ -0,0 +1,125 @@ +.CodeMirror { + background: var(--input-active-bg) !important; + border: 1px solid var(--input-border-color) !important; + color: var(--text-color) !important; +} + +.CodeMirror-scroll { + min-height: 300px +} + +.CodeMirror-fullscreen { + background: var(--input-bg); +} + +.CodeMirror .CodeMirror-code .cm-strikethrough { + text-decoration: line-through; +} + +.editor-toolbar { + border: 1px solid var(--input-border-color) !important; + border-bottom: 0 !important; +} + +.editor-toolbar i.separator { + border-color: var(--input-border-color) !important; +} + + +.editor-toolbar.fullscreen { + background: var(--color-bg) !important; +} + + +/* +.editor-toolbar.fullscreen::before { + background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%); +} + +.editor-toolbar.fullscreen::after { + + background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); +} +*/ + +div.editor-toolbar a { + color: var(--text-color) !important; +} + +.editor-toolbar a.active, +.editor-toolbar a:hover { + background: var(--button-bg) !important; + border-color: transparent !important; +} + + + +.editor-toolbar.disabled-for-preview a:not(.no-disable) { + background: transparent !important; + border-color: transparent !important; +} + + +.editor-statusbar { + color: #959694; +} + +.editor-preview { + background: var(--card-bg) !important; +} + +.editor-preview-side { + background: var(--color-bg-alt) !important; + border: 1px solid var(--input-border-color) !important; +} + + + +.editor-preview pre, +.editor-preview-side pre { + background: #eee; +} + +.editor-preview table td, +.editor-preview table th, +.editor-preview-side table td, +.editor-preview-side table th { + border: 1px solid var(--input-border-color) !important; +} + +.CodeMirror .CodeMirror-code .cm-tag { + color: #63a35c; +} + +.CodeMirror .CodeMirror-code .cm-attribute { + color: #795da3; +} + +.CodeMirror .CodeMirror-code .cm-string { + color: #183691; +} + +.CodeMirror .CodeMirror-selected { + background: var(--text-selection-bg) !important; + color: var(--text-selection-color) !important; +} + +.CodeMirror .CodeMirror-cursor{ + border-color: var(--text-color) !important; +} + +.CodeMirror .CodeMirror-code .cm-comment { + background: rgba(0, 0, 0, .05); +} + +.CodeMirror .CodeMirror-code .cm-link { + color: #7f8c8d; +} + +.CodeMirror .CodeMirror-code .cm-url { + color: #aab2b3; +} + +.CodeMirror .CodeMirror-placeholder { + opacity: .5; +} From 463d09256f38068f20f62f2dcd982ceee9afb91f Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 26 Aug 2017 14:50:02 -0600 Subject: [PATCH 062/132] tidy up _markdown-styles.scss --- ui/scss/component/_markdown-editor.scss | 26 ------------------------- 1 file changed, 26 deletions(-) diff --git a/ui/scss/component/_markdown-editor.scss b/ui/scss/component/_markdown-editor.scss index 9691ce7ce..a2b311f5b 100644 --- a/ui/scss/component/_markdown-editor.scss +++ b/ui/scss/component/_markdown-editor.scss @@ -4,18 +4,10 @@ color: var(--text-color) !important; } -.CodeMirror-scroll { - min-height: 300px -} - .CodeMirror-fullscreen { background: var(--input-bg); } -.CodeMirror .CodeMirror-code .cm-strikethrough { - text-decoration: line-through; -} - .editor-toolbar { border: 1px solid var(--input-border-color) !important; border-bottom: 0 !important; @@ -25,23 +17,10 @@ border-color: var(--input-border-color) !important; } - .editor-toolbar.fullscreen { background: var(--color-bg) !important; } - -/* -.editor-toolbar.fullscreen::before { - background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%); -} - -.editor-toolbar.fullscreen::after { - - background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); -} -*/ - div.editor-toolbar a { color: var(--text-color) !important; } @@ -52,14 +31,11 @@ div.editor-toolbar a { border-color: transparent !important; } - - .editor-toolbar.disabled-for-preview a:not(.no-disable) { background: transparent !important; border-color: transparent !important; } - .editor-statusbar { color: #959694; } @@ -73,8 +49,6 @@ div.editor-toolbar a { border: 1px solid var(--input-border-color) !important; } - - .editor-preview pre, .editor-preview-side pre { background: #eee; From b9735249015c0a09745b059a9aeea94754b38616 Mon Sep 17 00:00:00 2001 From: hackrush Date: Thu, 31 Aug 2017 09:45:13 +0530 Subject: [PATCH 063/132] Fixed modals --- ui/js/modal/modalInsufficientBalance/index.js | 16 ++++++++++++ ui/js/modal/modalInsufficientBalance/view.jsx | 26 +++++++++++++++++++ ui/js/modal/modalRouter/view.jsx | 8 +++++- ui/js/modal/modalTransactionFailed/index.js | 12 +++++++++ ui/js/modal/modalTransactionFailed/view.jsx | 20 ++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 ui/js/modal/modalInsufficientBalance/index.js create mode 100644 ui/js/modal/modalInsufficientBalance/view.jsx create mode 100644 ui/js/modal/modalTransactionFailed/index.js create mode 100644 ui/js/modal/modalTransactionFailed/view.jsx diff --git a/ui/js/modal/modalInsufficientBalance/index.js b/ui/js/modal/modalInsufficientBalance/index.js new file mode 100644 index 000000000..c56232caf --- /dev/null +++ b/ui/js/modal/modalInsufficientBalance/index.js @@ -0,0 +1,16 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal, doNavigate } from "actions/app"; +import ModalInsufficientBalance from "./view"; + +const select = state => ({}); + +const perform = dispatch => ({ + addBalance: () => { + dispatch(doNavigate("/wallet")); + dispatch(doCloseModal()); + }, + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalInsufficientBalance); diff --git a/ui/js/modal/modalInsufficientBalance/view.jsx b/ui/js/modal/modalInsufficientBalance/view.jsx new file mode 100644 index 000000000..d1287d9c5 --- /dev/null +++ b/ui/js/modal/modalInsufficientBalance/view.jsx @@ -0,0 +1,26 @@ +import React from "react"; +import { Modal } from "modal/modal"; + +class ModalInsufficientBalance extends React.PureComponent { + render() { + const { addBalance, closeModal } = this.props; + + return ( + + {__( + "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." + )} + + ); + } +} + +export default ModalInsufficientBalance; diff --git a/ui/js/modal/modalRouter/view.jsx b/ui/js/modal/modalRouter/view.jsx index d2280821e..6d8ca4017 100644 --- a/ui/js/modal/modalRouter/view.jsx +++ b/ui/js/modal/modalRouter/view.jsx @@ -6,8 +6,10 @@ import ModalInsufficientCredits from "modal/modalInsufficientCredits"; import ModalUpgrade from "modal/modalUpgrade"; import ModalWelcome from "modal/modalWelcome"; import ModalFirstReward from "modal/modalFirstReward"; -import * as modals from "constants/modal_types"; import ModalCreditIntro from "modal/modalCreditIntro"; +import ModalTransactionFailed from "modal/modalTransactionFailed"; +import ModalInsufficientBalance from "modal/modalInsufficientBalance"; +import * as modals from "constants/modal_types"; class ModalRouter extends React.PureComponent { componentWillMount() { @@ -51,6 +53,10 @@ class ModalRouter extends React.PureComponent { return ; case modals.CREDIT_INTRO: return ; + case modals.TRANSACTION_FAILED: + return ; + case modals.INSUFFICIENT_BALANCE: + return ; default: return null; } diff --git a/ui/js/modal/modalTransactionFailed/index.js b/ui/js/modal/modalTransactionFailed/index.js new file mode 100644 index 000000000..4b370a7c8 --- /dev/null +++ b/ui/js/modal/modalTransactionFailed/index.js @@ -0,0 +1,12 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal } from "actions/app"; +import ModalTransactionFailed from "./view"; + +const select = state => ({}); + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalTransactionFailed); diff --git a/ui/js/modal/modalTransactionFailed/view.jsx b/ui/js/modal/modalTransactionFailed/view.jsx new file mode 100644 index 000000000..b2d4a3558 --- /dev/null +++ b/ui/js/modal/modalTransactionFailed/view.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { Modal } from "modal/modal"; + +class ModalTransactionFailed extends React.PureComponent { + render() { + const { closeModal } = this.props; + + return ( + + {__("Something went wrong")}: + + ); + } +} + +export default ModalTransactionFailed; From 997c8930c1a7662fb6babf95fe015496639abc7b Mon Sep 17 00:00:00 2001 From: hackrush Date: Fri, 1 Sep 2017 21:37:06 +0530 Subject: [PATCH 064/132] Fixed the feature breaking change, I don't how I could have skipped this --- ui/js/page/file/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index d3c633015..a77042ff3 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -171,7 +171,7 @@ class FilePage extends React.PureComponent { ? : ""}
From 5b96039b99489fc8b567a665a3f18710f4cf545a Mon Sep 17 00:00:00 2001 From: hackrush Date: Sat, 2 Sep 2017 21:06:27 +0530 Subject: [PATCH 065/132] Transaction list now displays additional information Removed older modal files --- ui/js/actions/wallet.js | 2 +- ui/js/component/bodyTransactionList/index.js | 5 + ui/js/component/bodyTransactionList/view.jsx | 97 +++++++++++++++++++ .../component/headerTransactionList/index.js | 5 + .../component/headerTransactionList/view.jsx | 20 ++++ .../modalInsufficientBalance/index.js | 16 --- .../modalInsufficientBalance/view.jsx | 26 ----- .../component/modalTransactionFailed/index.js | 12 --- .../component/modalTransactionFailed/view.jsx | 20 ---- ui/js/component/transactionList/view.jsx | 95 +++++++++--------- ui/js/selectors/wallet.js | 7 +- 11 files changed, 178 insertions(+), 127 deletions(-) create mode 100644 ui/js/component/bodyTransactionList/index.js create mode 100644 ui/js/component/bodyTransactionList/view.jsx create mode 100644 ui/js/component/headerTransactionList/index.js create mode 100644 ui/js/component/headerTransactionList/view.jsx delete mode 100644 ui/js/component/modalInsufficientBalance/index.js delete mode 100644 ui/js/component/modalInsufficientBalance/view.jsx delete mode 100644 ui/js/component/modalTransactionFailed/index.js delete mode 100644 ui/js/component/modalTransactionFailed/view.jsx diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 364c7e9d5..2575c5285 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -23,7 +23,7 @@ export function doFetchTransactions() { type: types.FETCH_TRANSACTIONS_STARTED, }); - lbry.transaction_list().then(results => { + lbry.transaction_list({ include_tip_info: true }).then(results => { dispatch({ type: types.FETCH_TRANSACTIONS_COMPLETED, data: { diff --git a/ui/js/component/bodyTransactionList/index.js b/ui/js/component/bodyTransactionList/index.js new file mode 100644 index 000000000..48db597ed --- /dev/null +++ b/ui/js/component/bodyTransactionList/index.js @@ -0,0 +1,5 @@ +import React from "react"; +import { connect } from "react-redux"; +import TransactionTableBody from "./view"; + +export default connect(null, null)(TransactionTableBody); diff --git a/ui/js/component/bodyTransactionList/view.jsx b/ui/js/component/bodyTransactionList/view.jsx new file mode 100644 index 000000000..dcabf00ec --- /dev/null +++ b/ui/js/component/bodyTransactionList/view.jsx @@ -0,0 +1,97 @@ +import React from "react"; +import LinkTransaction from "component/linkTransaction"; +import { CreditAmount } from "component/common"; + +class TransactionTableBody extends React.PureComponent { + constructor(props) { + super(props); + } + + filterList(transaction) { + if (this.filter == "claim") { + return transaction.claim_info.length > 0; + } else if (this.filter == "support") { + return transaction.support_info.length > 0; + } else if (this.filter == "update") { + return transaction.update_info.length > 0; + } else { + return transaction; + } + } + + renderBody(transaction, index) { + const txid = transaction.id; + const date = transaction.date; + const fee = transaction.fee; + const filter = this.filter; + + return filter != "unfiltered" + ? transaction[`${filter}_info`].map(item => { + return ( + + + {date + ? date.toLocaleDateString() + " " + date.toLocaleTimeString() + : + {__("(Transaction pending)")} + } + + + {" "} + + + {" "} + + + {item.claim_name} + + + + + + ); + }) + : + + {date + ? date.toLocaleDateString() + " " + date.toLocaleTimeString() + : + {__("(Transaction pending)")} + } + + + {" "} + + + {" "} + + + + + ; + } + + render() { + const { transactions, filter } = this.props; + + return ( + + {transactions + .filter(this.filterList, this.props) + .map(this.renderBody, this.props)} + + ); + } +} + +export default TransactionTableBody; diff --git a/ui/js/component/headerTransactionList/index.js b/ui/js/component/headerTransactionList/index.js new file mode 100644 index 000000000..60ae880d7 --- /dev/null +++ b/ui/js/component/headerTransactionList/index.js @@ -0,0 +1,5 @@ +import React from "react"; +import { connect } from "react-redux"; +import TransactionTableHeader from "./view"; + +export default connect(null, null)(TransactionTableHeader); diff --git a/ui/js/component/headerTransactionList/view.jsx b/ui/js/component/headerTransactionList/view.jsx new file mode 100644 index 000000000..23fd61965 --- /dev/null +++ b/ui/js/component/headerTransactionList/view.jsx @@ -0,0 +1,20 @@ +import React from "react"; + +class TransactionTableHeader extends React.PureComponent { + render() { + const { filter } = this.props; + return ( + + + {__("Date")} + {__("Amount")} + {__("Fee")} + {filter != "unfiltered" && {__("Claim Name")} } + {__("Transaction")} + + + ); + } +} + +export default TransactionTableHeader; diff --git a/ui/js/component/modalInsufficientBalance/index.js b/ui/js/component/modalInsufficientBalance/index.js deleted file mode 100644 index c56232caf..000000000 --- a/ui/js/component/modalInsufficientBalance/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { doCloseModal, doNavigate } from "actions/app"; -import ModalInsufficientBalance from "./view"; - -const select = state => ({}); - -const perform = dispatch => ({ - addBalance: () => { - dispatch(doNavigate("/wallet")); - dispatch(doCloseModal()); - }, - closeModal: () => dispatch(doCloseModal()), -}); - -export default connect(select, perform)(ModalInsufficientBalance); diff --git a/ui/js/component/modalInsufficientBalance/view.jsx b/ui/js/component/modalInsufficientBalance/view.jsx deleted file mode 100644 index f9ac56138..000000000 --- a/ui/js/component/modalInsufficientBalance/view.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; -import { Modal } from "component/modal"; - -class ModalInsufficientBalance extends React.PureComponent { - render() { - const { addBalance, closeModal } = this.props; - - return ( - - {__( - "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." - )} - - ); - } -} - -export default ModalInsufficientBalance; diff --git a/ui/js/component/modalTransactionFailed/index.js b/ui/js/component/modalTransactionFailed/index.js deleted file mode 100644 index 4b370a7c8..000000000 --- a/ui/js/component/modalTransactionFailed/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { doCloseModal } from "actions/app"; -import ModalTransactionFailed from "./view"; - -const select = state => ({}); - -const perform = dispatch => ({ - closeModal: () => dispatch(doCloseModal()), -}); - -export default connect(select, perform)(ModalTransactionFailed); diff --git a/ui/js/component/modalTransactionFailed/view.jsx b/ui/js/component/modalTransactionFailed/view.jsx deleted file mode 100644 index f22038e78..000000000 --- a/ui/js/component/modalTransactionFailed/view.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react"; -import { Modal } from "component/modal"; - -class ModalTransactionFailed extends React.PureComponent { - render() { - const { closeModal } = this.props; - - return ( - - {__("Something went wrong")}: - - ); - } -} - -export default ModalTransactionFailed; diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index 0ad7f4eeb..374c6887d 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -1,57 +1,56 @@ import React from "react"; -import LinkTransaction from "component/linkTransaction"; -import { CreditAmount } from "component/common"; +import TransactionTableHeader from "component/headerTransactionList"; +import TransactionTableBody from "component/bodyTransactionList"; +import FormField from "component/formField"; -const TransactionList = props => { - const { emptyMessage, transactions } = props; +class TransactionList extends React.PureComponent { + constructor(props) { + super(props); + + this.state = { + filter: "unfiltered", + }; + } + + handleFilterChanged(event) { + this.setState({ + filter: event.target.value, + }); + } + + render() { + const { emptyMessage, transactions } = this.props; + const { filter } = this.state; + + if (!transactions || !transactions.length) { + return ( +
+ {emptyMessage || __("No transactions to list.")} +
+ ); + } - if (!transactions || !transactions.length) { return ( -
- {emptyMessage || __("No transactions to list.")} +
+ + {__("Filter")} {" "} + + + + + + + + + + +
); } - - return ( - - - - - - - - - - {transactions.map(item => { - return ( - - - - - - ); - })} - -
{__("Date")}{__("Amount")}{__("Transaction")}
- {item.date - ? item.date.toLocaleDateString() + - " " + - item.date.toLocaleTimeString() - : - {__("(Transaction pending)")} - } - - {" "} - - -
- ); -}; +} export default TransactionList; diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index dbf32639f..60e0dd1aa 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -28,11 +28,10 @@ export const selectTransactionItems = createSelector( id: txid, date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, amount: parseFloat(tx.value), - type: tx.type, + claim_info: tx.claim_info, + support_info: tx.support_info, + update_info: tx.update_info, fee: tx.fee, - claim_id: tx.claim_id, - claim_name: tx.claim_name, - is_tip: tx.is_tip, }); }); return transactionItems.reverse(); From 7a328f185a856fafb0ea5f77dac854bc11aadd0f Mon Sep 17 00:00:00 2001 From: hackrush Date: Sat, 2 Sep 2017 23:20:40 +0530 Subject: [PATCH 066/132] Clickable claims and filter for tips --- ui/js/component/bodyTransactionList/index.js | 7 +++- ui/js/component/bodyTransactionList/view.jsx | 41 ++++++++++++++++---- ui/js/component/transactionList/view.jsx | 7 ++-- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/ui/js/component/bodyTransactionList/index.js b/ui/js/component/bodyTransactionList/index.js index 48db597ed..95fcdaf11 100644 --- a/ui/js/component/bodyTransactionList/index.js +++ b/ui/js/component/bodyTransactionList/index.js @@ -1,5 +1,10 @@ import React from "react"; import { connect } from "react-redux"; +import { doNavigate } from "actions/navigation"; import TransactionTableBody from "./view"; -export default connect(null, null)(TransactionTableBody); +const perform = dispatch => ({ + navigate: (path, params) => dispatch(doNavigate(path, params)), +}); + +export default connect(null, perform)(TransactionTableBody); diff --git a/ui/js/component/bodyTransactionList/view.jsx b/ui/js/component/bodyTransactionList/view.jsx index dcabf00ec..fa15d1619 100644 --- a/ui/js/component/bodyTransactionList/view.jsx +++ b/ui/js/component/bodyTransactionList/view.jsx @@ -7,23 +7,41 @@ class TransactionTableBody extends React.PureComponent { super(props); } + getClaimLink(claim_name, claim_id) { + let uri = `lbry://${claim_name}#${claim_id}`; + + return ( +
this.props.navigate("/show", { uri })} + > + {claim_name} + + ); + } + filterList(transaction) { - if (this.filter == "claim") { + if (this.props.filter == "claim") { return transaction.claim_info.length > 0; - } else if (this.filter == "support") { + } else if (this.props.filter == "support") { return transaction.support_info.length > 0; - } else if (this.filter == "update") { + } else if (this.props.filter == "update") { return transaction.update_info.length > 0; } else { return transaction; } } - renderBody(transaction, index) { + renderBody(transaction) { const txid = transaction.id; const date = transaction.date; const fee = transaction.fee; - const filter = this.filter; + const filter = this.props.filter; + + if (filter == "tipSupport") + transaction["tipSupport_info"] = transaction["support_info"].filter( + tx => tx.is_tip + ); return filter != "unfiltered" ? transaction[`${filter}_info`].map(item => { @@ -48,7 +66,7 @@ class TransactionTableBody extends React.PureComponent { {" "} - {item.claim_name} + {this.getClaimLink(item.claim_name, item.claim_id)} @@ -81,14 +99,21 @@ class TransactionTableBody extends React.PureComponent { ; } + removeFeeTx(transaction) { + if (this.props.filter == "unfiltered") + return Math.abs(transaction.amount) != Math.abs(transaction.fee); + else return true; + } + render() { const { transactions, filter } = this.props; return ( {transactions - .filter(this.filterList, this.props) - .map(this.renderBody, this.props)} + .filter(this.filterList, this) + .filter(this.removeFeeTx, this) + .map(this.renderBody, this)} ); } diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index 374c6887d..361b54395 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -39,9 +39,10 @@ class TransactionList extends React.PureComponent { onChange={this.handleFilterChanged.bind(this)} > - - - + + + + From f1bdb5e20d63d653398d9653409baf18c58366e7 Mon Sep 17 00:00:00 2001 From: hackrush Date: Sat, 2 Sep 2017 23:32:13 +0530 Subject: [PATCH 067/132] Removes inconsistencies in wallet.js and Insuff. Balance Modal --- ui/js/actions/wallet.js | 2 +- ui/js/modal/modalInsufficientBalance/view.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 2575c5285..368247d16 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -73,7 +73,7 @@ export function doSendDraftTransaction() { const balance = selectBalance(state); const amount = selectDraftTransactionAmount(state); - if (balance - amount < 1) { + if (balance - amount <= 0) { return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); } diff --git a/ui/js/modal/modalInsufficientBalance/view.jsx b/ui/js/modal/modalInsufficientBalance/view.jsx index d1287d9c5..5b43583cd 100644 --- a/ui/js/modal/modalInsufficientBalance/view.jsx +++ b/ui/js/modal/modalInsufficientBalance/view.jsx @@ -16,7 +16,7 @@ class ModalInsufficientBalance extends React.PureComponent { onConfirmed={addBalance} > {__( - "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." + "Insufficient balance: after this transaction you would have less than 0 LBCs in your wallet." )} ); From 065d699a2df10e355b225644eb2685b7291fd9d6 Mon Sep 17 00:00:00 2001 From: hackrush Date: Mon, 4 Sep 2017 23:05:41 +0530 Subject: [PATCH 068/132] Small changes Clicking support hides everything below fileActions Title of form is Support now One line helper sentence Moved Tx related component to internal Unfiltered -> Show All -> All Claims -> Publishes Fee below Amount(class meta) Dropped Credits everywhere. --- ui/js/component/bodyTransactionList/index.js | 10 ---- ui/js/component/common.js | 7 ++- .../component/headerTransactionList/index.js | 5 -- ui/js/component/tipLink/view.jsx | 8 +++- ui/js/component/transactionList/index.js | 7 ++- .../internal/TransactionListBody.jsx} | 46 +++++++++++++------ .../internal/TransactionListHeader.jsx} | 3 +- ui/js/component/transactionList/view.jsx | 18 ++++++-- ui/js/page/file/view.jsx | 30 ++++++------ 9 files changed, 81 insertions(+), 53 deletions(-) delete mode 100644 ui/js/component/bodyTransactionList/index.js delete mode 100644 ui/js/component/headerTransactionList/index.js rename ui/js/component/{bodyTransactionList/view.jsx => transactionList/internal/TransactionListBody.jsx} (75%) rename ui/js/component/{headerTransactionList/view.jsx => transactionList/internal/TransactionListHeader.jsx} (85%) diff --git a/ui/js/component/bodyTransactionList/index.js b/ui/js/component/bodyTransactionList/index.js deleted file mode 100644 index 95fcdaf11..000000000 --- a/ui/js/component/bodyTransactionList/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { doNavigate } from "actions/navigation"; -import TransactionTableBody from "./view"; - -const perform = dispatch => ({ - navigate: (path, params) => dispatch(doNavigate(path, params)), -}); - -export default connect(null, perform)(TransactionTableBody); diff --git a/ui/js/component/common.js b/ui/js/component/common.js index d92669262..8af8733c2 100644 --- a/ui/js/component/common.js +++ b/ui/js/component/common.js @@ -71,6 +71,7 @@ export class CreditAmount extends React.PureComponent { showFullPrice: React.PropTypes.bool, showPlus: React.PropTypes.bool, look: React.PropTypes.oneOf(["indicator", "plain"]), + fee: React.PropTypes.bool, }; static defaultProps = { @@ -81,6 +82,7 @@ export class CreditAmount extends React.PureComponent { showFree: false, showFullPrice: false, showPlus: false, + fee: false, }; render() { @@ -117,7 +119,10 @@ export class CreditAmount extends React.PureComponent { return ( diff --git a/ui/js/component/headerTransactionList/index.js b/ui/js/component/headerTransactionList/index.js deleted file mode 100644 index 60ae880d7..000000000 --- a/ui/js/component/headerTransactionList/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import TransactionTableHeader from "./view"; - -export default connect(null, null)(TransactionTableHeader); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 03f7685ec..831806d48 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -32,7 +32,13 @@ class TipLink extends React.PureComponent { return (
-

{__("Support Claim")}

+

{__("Support")}

+
+
+ {__( + "Support the creator and the success of their content by sending a tip. " + )} +
({ + navigate: (path, params) => dispatch(doNavigate(path, params)), +}); + +export default connect(null, perform)(TransactionList); diff --git a/ui/js/component/bodyTransactionList/view.jsx b/ui/js/component/transactionList/internal/TransactionListBody.jsx similarity index 75% rename from ui/js/component/bodyTransactionList/view.jsx rename to ui/js/component/transactionList/internal/TransactionListBody.jsx index fa15d1619..12beb2e8d 100644 --- a/ui/js/component/bodyTransactionList/view.jsx +++ b/ui/js/component/transactionList/internal/TransactionListBody.jsx @@ -11,10 +11,7 @@ class TransactionTableBody extends React.PureComponent { let uri = `lbry://${claim_name}#${claim_id}`; return ( - this.props.navigate("/show", { uri })} - > + this.props.navigate(uri)}> {claim_name} ); @@ -37,6 +34,15 @@ class TransactionTableBody extends React.PureComponent { const date = transaction.date; const fee = transaction.fee; const filter = this.props.filter; + const options = { + weekday: "short", + year: "2-digit", + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }; if (filter == "tipSupport") transaction["tipSupport_info"] = transaction["support_info"].filter( @@ -49,7 +55,7 @@ class TransactionTableBody extends React.PureComponent {
- - - - + {filter != "unfiltered" && } diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index 361b54395..ee78e2acc 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -1,6 +1,6 @@ import React from "react"; -import TransactionTableHeader from "component/headerTransactionList"; -import TransactionTableBody from "component/bodyTransactionList"; +import TransactionTableHeader from "./internal/TransactionListHeader"; +import TransactionTableBody from "./internal/TransactionListBody"; import FormField from "component/formField"; class TransactionList extends React.PureComponent { @@ -18,6 +18,10 @@ class TransactionList extends React.PureComponent { }); } + handleClaimNameClicked(uri) { + this.props.navigate("/show", { uri }); + } + render() { const { emptyMessage, transactions } = this.props; const { filter } = this.state; @@ -38,8 +42,8 @@ class TransactionList extends React.PureComponent { type="select" onChange={this.handleFilterChanged.bind(this)} > - - + + @@ -47,7 +51,11 @@ class TransactionList extends React.PureComponent {
{date - ? date.toLocaleDateString() + " " + date.toLocaleTimeString() + ? date.toLocaleDateString("en-US", options) : {__("(Transaction pending)")} } @@ -58,12 +64,18 @@ class TransactionTableBody extends React.PureComponent { {" "} - - {" "} + /> +
+
{this.getClaimLink(item.claim_name, item.claim_id)} @@ -77,7 +89,7 @@ class TransactionTableBody extends React.PureComponent { :
{date - ? date.toLocaleDateString() + " " + date.toLocaleTimeString() + ? date.toLocaleDateString("en-US", options) : {__("(Transaction pending)")} } @@ -86,12 +98,18 @@ class TransactionTableBody extends React.PureComponent { {" "} - - {" "} + /> +
+
diff --git a/ui/js/component/headerTransactionList/view.jsx b/ui/js/component/transactionList/internal/TransactionListHeader.jsx similarity index 85% rename from ui/js/component/headerTransactionList/view.jsx rename to ui/js/component/transactionList/internal/TransactionListHeader.jsx index 23fd61965..52f735fb9 100644 --- a/ui/js/component/headerTransactionList/view.jsx +++ b/ui/js/component/transactionList/internal/TransactionListHeader.jsx @@ -7,8 +7,7 @@ class TransactionTableHeader extends React.PureComponent {
{__("Date")}{__("Amount")}{__("Fee")}{__("Amount(Fee)")} {__("Claim Name")} {__("Transaction")}
- +
); diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index a77042ff3..08568c5b5 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -154,13 +154,14 @@ class FilePage extends React.PureComponent { />
-
- -
+ {!showTipBox && +
+ +
} {metadata && !showTipBox ?
@@ -174,13 +175,14 @@ class FilePage extends React.PureComponent { claim_id={claim.claim_id} /> : ""} -
- -
+ {!showTipBox && +
+ +
}
); From de69a7c76b7564a9d2c8d8fa0454fb08c4d0d77d Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 6 Sep 2017 18:34:11 -0400 Subject: [PATCH 069/132] further css cleanup, no dependency on themes folder existing --- ui/js/actions/settings.js | 4 ++ ui/js/component/link/view.jsx | 2 - ui/scss/_global.scss | 54 ----------------------- ui/scss/_gui.scss | 10 ----- ui/scss/_icons.scss | 2 - ui/scss/_vars.scss | 9 +++- ui/scss/all.scss | 2 +- ui/scss/component/_button.scss | 2 +- ui/scss/component/_card.scss | 2 - ui/scss/component/_channel-indicator.scss | 1 - ui/scss/component/_file-actions.scss | 1 - ui/scss/component/_file-tile.scss | 1 - ui/scss/component/_form-field.scss | 9 +++- ui/scss/component/_header.scss | 1 - ui/scss/component/_load-screen.scss | 1 - ui/scss/component/_menu.scss | 1 - ui/scss/component/_modal.scss | 1 - ui/scss/component/_notice.scss | 1 - ui/scss/component/_pagination.scss | 1 - ui/scss/component/_snack-bar.scss | 1 - ui/scss/component/_table.scss | 1 - ui/scss/component/_tooltip.scss | 2 +- ui/scss/component/_video.scss | 1 - ui/scss/mixin/link.scss | 30 +++++++++++++ ui/scss/page/_reward.scss | 5 --- ui/scss/page/_show.scss | 2 - 26 files changed, 51 insertions(+), 96 deletions(-) delete mode 100644 ui/scss/_global.scss create mode 100644 ui/scss/mixin/link.scss delete mode 100644 ui/scss/page/_reward.scss diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 38d489157..3aaf6ad4a 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -55,6 +55,10 @@ export function doSetClientSetting(key, value) { export function doGetThemes() { const dir = `${remote.app.getAppPath()}/dist/themes`; + if (!fs.existsSync(dir)) { + return; + } + // Get all .css files const files = readdirSync(dir).filter(file => extname(file) === ".css"); diff --git a/ui/js/component/link/view.jsx b/ui/js/component/link/view.jsx index 6760c6cd3..a30d1a981 100644 --- a/ui/js/component/link/view.jsx +++ b/ui/js/component/link/view.jsx @@ -8,7 +8,6 @@ const Link = props => { style, label, icon, - badge, button, disabled, children, @@ -36,7 +35,6 @@ const Link = props => { {"icon" in props ? : null} {label ? {label} : null} - {"badge" in props ? {badge} : null} ); } diff --git a/ui/scss/_global.scss b/ui/scss/_global.scss deleted file mode 100644 index 34681e5b6..000000000 --- a/ui/scss/_global.scss +++ /dev/null @@ -1,54 +0,0 @@ -@charset "UTF-8"; - -$spacing-vertical: 24px; -$width-page-constrained: 800px; - -@mixin absolute-center() -{ - -} - -@mixin linear-gradient($from-color, $to-color) { - background-color: $to-color; /* Fallback Color */ - background-image: -webkit-linear-gradient(top, $from-color, $to-color); /* Chrome 10+, Saf5.1+, iOS 5+ */ - background-image: -moz-linear-gradient(top, $from-color, $to-color); /* FF3.6 */ - background-image: -ms-linear-gradient(top, $from-color, $to-color); /* IE10 */ - background-image: linear-gradient(top, $from-color, $to-color); -} - -@mixin placeholder { - &::-webkit-input-placeholder {@content} - &:-moz-placeholder {@content} - &:-ms-input-placeholder {@content} -} - -@mixin text-link($color: var(--color-primary), $hover-opacity: 0.70) { - .icon - { - &:first-child { - padding-right: 5px; - } - &:last-child:not(:only-child) { - padding-left: 5px; - } - } - - &:not(.no-underline) { - text-decoration: underline; - .icon { - text-decoration: none; - } - } - &:hover - { - opacity: $hover-opacity; - transition: opacity var(--transition-duration) var(--transition-type); - text-decoration: underline; - .icon { - text-decoration: none; - } - } - - color: $color; - cursor: pointer; -} diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index 6d746f0f2..0f4b13be5 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -1,5 +1,3 @@ -@import "global"; - html { height: 100%; @@ -24,14 +22,6 @@ body background: var(--window-bg); } -.badge -{ - background: var(--color-money); - display: inline-block; - padding: 2px; - color: white; - border-radius: 2px; -} .credit-amount--indicator { font-weight: bold; diff --git a/ui/scss/_icons.scss b/ui/scss/_icons.scss index cb487975b..329b65566 100644 --- a/ui/scss/_icons.scss +++ b/ui/scss/_icons.scss @@ -1,5 +1,3 @@ -@import "global"; - @font-face { font-family: 'FontAwesome'; src: url('../font/fontawesome-webfont.eot?v=4.7.0'); diff --git a/ui/scss/_vars.scss b/ui/scss/_vars.scss index 16ac4b569..0a86d1d76 100644 --- a/ui/scss/_vars.scss +++ b/ui/scss/_vars.scss @@ -1,4 +1,9 @@ -@import "global"; +/* +Both of these should probably die and become variables as well + */ +$spacing-vertical: 24px; +$width-page-constrained: 800px; +$text-color: #000; :root { @@ -39,7 +44,7 @@ --transition-type: ease; /* Text */ - --text-color: #000; + --text-color: $text-color; --text-help-color: #EEE; --text-max-width: 660px; --text-link-padding: 4px; diff --git a/ui/scss/all.scss b/ui/scss/all.scss index 7dfd15d34..61f636b77 100644 --- a/ui/scss/all.scss +++ b/ui/scss/all.scss @@ -1,3 +1,4 @@ +@charset "UTF-8"; @import "_reset"; @import "_vars"; @import "_icons"; @@ -21,5 +22,4 @@ @import "component/_pagination.scss"; @import "component/_markdown-editor.scss"; @import "page/_developer.scss"; -@import "page/_reward.scss"; @import "page/_show.scss"; diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 5e2c338db..28075c123 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -1,4 +1,4 @@ -@import "../global"; +@import "../mixin/link.scss"; $button-focus-shift: 12%; diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 5ec826048..d81f408ac 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -1,5 +1,3 @@ -@import "../global"; - .card { margin-left: auto; margin-right: auto; diff --git a/ui/scss/component/_channel-indicator.scss b/ui/scss/component/_channel-indicator.scss index 8b72bd36d..2e80c096e 100644 --- a/ui/scss/component/_channel-indicator.scss +++ b/ui/scss/component/_channel-indicator.scss @@ -1,4 +1,3 @@ -@import "../global"; .channel-indicator__icon--invalid { color: var(--color-error); diff --git a/ui/scss/component/_file-actions.scss b/ui/scss/component/_file-actions.scss index 88d67bf29..0350dad90 100644 --- a/ui/scss/component/_file-actions.scss +++ b/ui/scss/component/_file-actions.scss @@ -1,4 +1,3 @@ -@import "../global"; .file-actions { diff --git a/ui/scss/component/_file-tile.scss b/ui/scss/component/_file-tile.scss index 7630f5517..7341cc606 100644 --- a/ui/scss/component/_file-tile.scss +++ b/ui/scss/component/_file-tile.scss @@ -1,4 +1,3 @@ -@import "../global"; $height-file-tile: $spacing-vertical * 6; .file-tile__row { diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index 7fc276ddd..f3d46befd 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -1,4 +1,9 @@ -@import "../global"; + +@mixin placeholder { + &::-webkit-input-placeholder {@content} + &:-moz-placeholder {@content} + &:-ms-input-placeholder {@content} +} .form-row-submit { @@ -63,7 +68,7 @@ input[type="text"].input-copyable { input[type="search"], input[type="date"] { @include placeholder { - //color: lighten($color-text-dark, 60%); + color: lighten($text-color, 60%); } transition: all var(--transition-duration) var(--transition-type); cursor: pointer; diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index ea114dc5d..9428298e2 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -1,4 +1,3 @@ -@import "../global"; #header { diff --git a/ui/scss/component/_load-screen.scss b/ui/scss/component/_load-screen.scss index 24221c10d..cfd369c95 100644 --- a/ui/scss/component/_load-screen.scss +++ b/ui/scss/component/_load-screen.scss @@ -1,4 +1,3 @@ -@import "../global"; .load-screen { color: white; diff --git a/ui/scss/component/_menu.scss b/ui/scss/component/_menu.scss index 52399bdfb..19af2af66 100644 --- a/ui/scss/component/_menu.scss +++ b/ui/scss/component/_menu.scss @@ -1,4 +1,3 @@ -@import "../global"; $border-radius-menu: 2px; diff --git a/ui/scss/component/_modal.scss b/ui/scss/component/_modal.scss index 7140e6cf8..cb664e4c1 100644 --- a/ui/scss/component/_modal.scss +++ b/ui/scss/component/_modal.scss @@ -1,4 +1,3 @@ -@import "../global"; .modal-overlay, .error-modal-overlay { position: fixed; diff --git a/ui/scss/component/_notice.scss b/ui/scss/component/_notice.scss index b77ba2a5a..112658987 100644 --- a/ui/scss/component/_notice.scss +++ b/ui/scss/component/_notice.scss @@ -1,4 +1,3 @@ -@import "../global"; .notice { padding: 10px 20px; diff --git a/ui/scss/component/_pagination.scss b/ui/scss/component/_pagination.scss index 6ea2a14c6..4851f366a 100644 --- a/ui/scss/component/_pagination.scss +++ b/ui/scss/component/_pagination.scss @@ -1,4 +1,3 @@ -@import "../global"; .pagination { display: block; diff --git a/ui/scss/component/_snack-bar.scss b/ui/scss/component/_snack-bar.scss index 5be3e1c6d..acc9f98a6 100644 --- a/ui/scss/component/_snack-bar.scss +++ b/ui/scss/component/_snack-bar.scss @@ -1,4 +1,3 @@ -@import "../global"; $padding-snack-horizontal: $spacing-vertical; diff --git a/ui/scss/component/_table.scss b/ui/scss/component/_table.scss index 98cb50664..2e2b664a1 100644 --- a/ui/scss/component/_table.scss +++ b/ui/scss/component/_table.scss @@ -1,4 +1,3 @@ -@import "../global"; table.table-standard { word-wrap: break-word; diff --git a/ui/scss/component/_tooltip.scss b/ui/scss/component/_tooltip.scss index 18b3d92c3..58889f657 100644 --- a/ui/scss/component/_tooltip.scss +++ b/ui/scss/component/_tooltip.scss @@ -1,4 +1,4 @@ -@import "../global"; +@import "../mixin/link.scss"; .tooltip { position: relative; diff --git a/ui/scss/component/_video.scss b/ui/scss/component/_video.scss index 20d5b7572..46cd07eee 100644 --- a/ui/scss/component/_video.scss +++ b/ui/scss/component/_video.scss @@ -1,4 +1,3 @@ -@import "../global"; $height-video-embedded: $width-page-constrained * 9 / 16; diff --git a/ui/scss/mixin/link.scss b/ui/scss/mixin/link.scss new file mode 100644 index 000000000..ae6e752da --- /dev/null +++ b/ui/scss/mixin/link.scss @@ -0,0 +1,30 @@ +@mixin text-link($color: var(--color-primary), $hover-opacity: 0.70) { + .icon + { + &:first-child { + padding-right: 5px; + } + &:last-child:not(:only-child) { + padding-left: 5px; + } + } + + &:not(.no-underline) { + text-decoration: underline; + .icon { + text-decoration: none; + } + } + &:hover + { + opacity: $hover-opacity; + transition: opacity var(--transition-duration) var(--transition-type); + text-decoration: underline; + .icon { + text-decoration: none; + } + } + + color: $color; + cursor: pointer; +} diff --git a/ui/scss/page/_reward.scss b/ui/scss/page/_reward.scss deleted file mode 100644 index 5e6180dc5..000000000 --- a/ui/scss/page/_reward.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import "../global"; - -.reward-page__details { - //background-color: lighten($color-canvas, 1.5%); -} diff --git a/ui/scss/page/_show.scss b/ui/scss/page/_show.scss index 0dbfea2e0..d52f28381 100644 --- a/ui/scss/page/_show.scss +++ b/ui/scss/page/_show.scss @@ -1,5 +1,3 @@ -@import "../global"; - .show-page-media { text-align: center; margin-bottom: $spacing-vertical; From 4d85f4c5f9f6217cf40a5e266d705ada73a2e518 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 6 Sep 2017 19:16:21 -0400 Subject: [PATCH 070/132] update daemon, fix icon path --- app/package.json | 2 +- build/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/package.json b/app/package.json index e1293e5ac..2e4e70bd5 100644 --- a/app/package.json +++ b/app/package.json @@ -20,7 +20,7 @@ "electron-rebuild": "^1.5.11" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.15.1", + "lbrynetDaemonVersion": "0.16.0rc5", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip" }, "license": "MIT" diff --git a/build/build.sh b/build/build.sh index 92c2c5e8f..1f910d0d1 100755 --- a/build/build.sh +++ b/build/build.sh @@ -21,7 +21,7 @@ fi if $OSX; then ICON="$BUILD_DIR/icon.icns" else - ICON="$BUILD_DIR/icons/lbry48.png" + ICON="$BUILD_DIR/icons/48x48.png" fi FULL_BUILD="${FULL_BUILD:-false}" From 1019a942216ac0c878132e61d59a75a1d7543f9b Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 6 Sep 2017 20:52:34 -0400 Subject: [PATCH 071/132] theme refactor and bug fix --- ui/dist/index.html | 1 - ui/dist/quit.html | 1 - ui/js/actions/app.js | 1 - ui/js/actions/settings.js | 56 +++++++++++----------------------- ui/js/component/app/view.jsx | 2 ++ ui/js/component/theme/index.js | 10 ++++++ ui/js/component/theme/view.jsx | 21 +++++++++++++ ui/js/page/settings/index.js | 6 ++-- ui/js/page/settings/view.jsx | 25 ++++----------- ui/js/selectors/settings.js | 6 ++++ 10 files changed, 66 insertions(+), 63 deletions(-) create mode 100644 ui/js/component/theme/index.js create mode 100644 ui/js/component/theme/view.jsx diff --git a/ui/dist/index.html b/ui/dist/index.html index 29c1e0550..4be7ceb5b 100644 --- a/ui/dist/index.html +++ b/ui/dist/index.html @@ -6,7 +6,6 @@ - diff --git a/ui/dist/quit.html b/ui/dist/quit.html index 161d7ab4c..eff68e049 100644 --- a/ui/dist/quit.html +++ b/ui/dist/quit.html @@ -6,7 +6,6 @@ - diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 0b20c7bde..0f8a3bcf3 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -176,7 +176,6 @@ export function doDaemonReady() { return function(dispatch, getState) { dispatch(doAuthenticate()); dispatch({ type: types.DAEMON_READY }); - //dispatch(doSetTheme(lbry.getClientSetting(settings.THEME))); dispatch(doFetchDaemonSettings()); dispatch(doFileList()); }; diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 3aaf6ad4a..313b7c606 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -1,5 +1,6 @@ import * as types from "constants/action_types"; import * as settings from "constants/settings"; +import { doAlertError } from "actions/app"; import batchActions from "util/batchActions"; import lbry from "lbry"; @@ -8,8 +9,7 @@ import http from "http"; const { remote } = require("electron"); const { extname } = require("path"); -const { download } = remote.require("electron-dl"); -const { readdirSync } = remote.require("fs"); +const { readdir } = remote.require("fs"); export function doFetchDaemonSettings() { return function(dispatch, getState) { @@ -53,45 +53,23 @@ export function doSetClientSetting(key, value) { } export function doGetThemes() { - const dir = `${remote.app.getAppPath()}/dist/themes`; - - if (!fs.existsSync(dir)) { - return; - } - - // Get all .css files - const files = readdirSync(dir).filter(file => extname(file) === ".css"); - return function(dispatch, getState) { - // Find themes - const themes = files.map(file => ({ - name: file.replace(".css", ""), - path: `./themes/${file}`, - })); + const dir = `${remote.app.getAppPath()}/dist/themes`; - dispatch(doSetClientSetting(settings.THEMES, themes)); - }; -} - -export function doSetTheme(name) { - return function(dispatch, getState) { - // Find a theme from themes list - const find = themeName => themes.find(theme => theme.name === themeName); - - // Get themes - const themes = lbry.getClientSetting(settings.THEMES); - - // Find theme and set fallback - const theme = find(name) || find("light"); - - if (theme.path) { - // load css - const link = document.getElementById("theme"); - link.href = theme.path; - - // update theme - dispatch(doSetClientSetting(settings.THEME, theme.name)); - } + readdir(dir, (error, files) => { + if (!error) { + dispatch( + doSetClientSetting( + settings.THEMES, + files + .filter(file => extname(file) === ".css") + .map(file => file.replace(".css", "")) + ) + ); + } else { + dispatch(doAlertError(error)); + } + }); }; } diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index e3c2465de..37bd05c72 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -1,6 +1,7 @@ import React from "react"; import Router from "component/router/index"; import Header from "component/header"; +import Theme from "component/theme"; import ModalRouter from "modal/modalRouter"; import lbry from "lbry"; @@ -49,6 +50,7 @@ class App extends React.PureComponent { render() { return (
+
diff --git a/ui/js/component/theme/index.js b/ui/js/component/theme/index.js new file mode 100644 index 000000000..ad95b5297 --- /dev/null +++ b/ui/js/component/theme/index.js @@ -0,0 +1,10 @@ +import React from "react"; +import { connect } from "react-redux"; +import { selectThemePath } from "selectors/settings.js"; +import Theme from "./view"; + +const select = state => ({ + themePath: selectThemePath(state), +}); + +export default connect(select, null)(Theme); diff --git a/ui/js/component/theme/view.jsx b/ui/js/component/theme/view.jsx new file mode 100644 index 000000000..ad0b21ebc --- /dev/null +++ b/ui/js/component/theme/view.jsx @@ -0,0 +1,21 @@ +import React from "react"; + +const Theme = props => { + const { themePath } = props; + + if (!themePath) { + return null; + } + + return ( + + ); +}; + +export default Theme; diff --git a/ui/js/page/settings/index.js b/ui/js/page/settings/index.js index 5fe86a7a2..93f89f1d1 100644 --- a/ui/js/page/settings/index.js +++ b/ui/js/page/settings/index.js @@ -1,5 +1,6 @@ import React from "react"; import { connect } from "react-redux"; +import * as settings from "constants/settings"; import { doClearCache } from "actions/app"; import { doSetDaemonSetting, @@ -9,6 +10,7 @@ import { doChangeLanguage, } from "actions/settings"; import { + makeSelectClientSetting, selectDaemonSettings, selectShowNsfw, selectLanguages, @@ -21,14 +23,14 @@ const select = state => ({ showNsfw: selectShowNsfw(state), language: selectCurrentLanguage(state), languages: selectLanguages(state), + theme: makeSelectClientSetting(settings.THEME)(state), }); const perform = dispatch => ({ setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)), clearCache: () => dispatch(doClearCache()), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), - setTheme: name => dispatch(doSetTheme(name)), - getThemes: () => dispatch(doGetThemes), + getThemes: () => dispatch(doGetThemes()), changeLanguage: newLanguage => dispatch(doChangeLanguage(newLanguage)), }); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 45ad6efea..2eb32d260 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -42,19 +42,6 @@ class SettingsPage extends React.PureComponent { this.props.setDaemonSetting(name, value); } - setClientSetting(name, value) { - lbry.setClientSetting(name, value); - this._onSettingSaveSuccess(); - } - - setTheme(value) { - this.props.setTheme(value); - } - - getThemes() { - this.props.getThemes(); - } - onRunOnStartChange(event) { this.setDaemonSetting("run_on_startup", event.target.checked); } @@ -77,7 +64,7 @@ class SettingsPage extends React.PureComponent { onThemeChange(event) { const { value } = event.target; - this.setTheme(value); + this.props.setClientSetting(settings.THEME, value); } // onMaxUploadPrefChange(isLimited) { @@ -118,13 +105,13 @@ class SettingsPage extends React.PureComponent { onShowUnavailableChange(event) {} componentWillMount() { - this.getThemes(); + this.props.getThemes(); } componentDidMount() {} render() { - const { daemonSettings, language, languages } = this.props; + const { daemonSettings, language, languages, theme } = this.props; if (!daemonSettings || Object.keys(daemonSettings).length === 0) { return ( @@ -270,12 +257,12 @@ class SettingsPage extends React.PureComponent { {this.state.themes.map((theme, index) => - )} diff --git a/ui/js/selectors/settings.js b/ui/js/selectors/settings.js index 10b9191df..c4642e39f 100644 --- a/ui/js/selectors/settings.js +++ b/ui/js/selectors/settings.js @@ -1,3 +1,4 @@ +import * as settings from "constants/settings"; import { createSelector } from "reselect"; const _selectState = state => state.settings || {}; @@ -33,3 +34,8 @@ export const selectLanguages = createSelector( _selectState, state => state.languages || {} ); + +export const selectThemePath = createSelector( + makeSelectClientSetting(settings.THEME), + theme => "themes/" + (theme || "light") + ".css" +); From 4cc9f4693472d172e7005d10d6d702315a948301 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 6 Sep 2017 21:53:42 -0400 Subject: [PATCH 072/132] more settings progress --- ui/js/actions/settings.js | 2 +- ui/js/app.js | 7 +------ ui/js/component/theme/view.jsx | 1 - ui/js/lbry.js | 17 ----------------- ui/js/page/settings/index.js | 7 ++++--- ui/js/page/settings/view.jsx | 34 ++++++++++++++++++++-------------- ui/js/reducers/settings.js | 3 ++- ui/js/selectors/settings.js | 6 ++---- 8 files changed, 30 insertions(+), 47 deletions(-) diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index 313b7c606..28e21f5c7 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -164,7 +164,7 @@ export function doDownloadLanguages() { export function doChangeLanguage(language) { return function(dispatch, getState) { - lbry.setClientSetting(settings.LANGUAGE, language); + dispatch(doSetClientSetting(settings.LANGUAGE, language)); app.i18n.setLocale(language); }; } diff --git a/ui/js/app.js b/ui/js/app.js index ecbb5f83c..a2e8fcbbd 100644 --- a/ui/js/app.js +++ b/ui/js/app.js @@ -1,18 +1,13 @@ import store from "store.js"; -import lbry from "./lbry.js"; -import * as settings from "constants/settings"; const env = ENV; const config = { ...require(`./config/${env}`), }; -const language = lbry.getClientSetting(settings.LANGUAGE) - ? lbry.getClientSetting(settings.LANGUAGE) - : "en"; const i18n = require("y18n")({ directory: "app/locales", updateFiles: false, - locale: language, + locale: "en", }); const logs = []; const app = { diff --git a/ui/js/component/theme/view.jsx b/ui/js/component/theme/view.jsx index ad0b21ebc..1ff7c8480 100644 --- a/ui/js/component/theme/view.jsx +++ b/ui/js/component/theme/view.jsx @@ -9,7 +9,6 @@ const Theme = props => { return ( ({ daemonSettings: selectDaemonSettings(state), - showNsfw: selectShowNsfw(state), + showNsfw: makeSelectClientSetting(settings.SHOW_NSFW)(state), + showUnavailable: makeSelectClientSetting(settings.SHOW_UNAVAILABLE)(state), + theme: makeSelectClientSetting(settings.THEME)(state), + themes: makeSelectClientSetting(settings.THEMES)(state), language: selectCurrentLanguage(state), languages: selectLanguages(state), - theme: makeSelectClientSetting(settings.THEME)(state), }); const perform = dispatch => ({ diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 2eb32d260..8835b0236 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -12,16 +12,8 @@ class SettingsPage extends React.PureComponent { constructor(props) { super(props); - const { daemonSettings } = this.props || {}; - this.state = { - // isMaxUpload: daemonSettings && daemonSettings.max_upload != 0, - // isMaxDownload: daemonSettings && daemonSettings.max_download != 0, - showUnavailable: lbry.getClientSetting(settings.SHOW_UNAVAILABLE), - language: lbry.getClientSetting(settings.LANGUAGE), clearingCache: false, - theme: lbry.getClientSetting(settings.THEME), - themes: lbry.getClientSetting(settings.THEMES), }; } @@ -102,7 +94,12 @@ class SettingsPage extends React.PureComponent { this.forceUpdate(); } - onShowUnavailableChange(event) {} + onShowUnavailableChange(event) { + this.props.setClientSetting( + settings.SHOW_UNAVAILABLE, + event.target.checked + ); + } componentWillMount() { this.props.getThemes(); @@ -111,7 +108,15 @@ class SettingsPage extends React.PureComponent { componentDidMount() {} render() { - const { daemonSettings, language, languages, theme } = this.props; + const { + daemonSettings, + language, + languages, + showNsfw, + showUnavailable, + theme, + themes, + } = this.props; if (!daemonSettings || Object.keys(daemonSettings).length === 0) { return ( @@ -216,7 +221,7 @@ class SettingsPage extends React.PureComponent {
@@ -225,7 +230,7 @@ class SettingsPage extends React.PureComponent { label={__("Show NSFW content")} type="checkbox" onChange={this.onShowNsfwChange.bind(this)} - defaultChecked={this.props.showNsfw} + defaultChecked={showNsfw} helper={__( "NSFW content may include nudity, intense sexuality, profanity, or other adult content. By displaying NSFW content, you are affirming you are of legal age to view mature content in your country or jurisdiction. " )} @@ -254,13 +259,14 @@ class SettingsPage extends React.PureComponent {

{__("Theme")}

+ {console.log(theme)} - {this.state.themes.map((theme, index) => + {themes.map((theme, index) => diff --git a/ui/js/reducers/settings.js b/ui/js/reducers/settings.js index dd50c2ad7..2656c03fd 100644 --- a/ui/js/reducers/settings.js +++ b/ui/js/reducers/settings.js @@ -6,7 +6,8 @@ import lbry from "lbry"; const reducers = {}; const defaultState = { clientSettings: { - showNsfw: lbry.getClientSetting("showNsfw"), + showNsfw: lbry.getClientSetting(settings.SHOW_NSFW), + showUnavailable: lbry.getClientSetting(settings.SHOW_UNAVAILABLE), welcome_acknowledged: lbry.getClientSetting(settings.NEW_USER_ACKNOWLEDGED), credit_intro_acknowledged: lbry.getClientSetting( settings.CREDIT_INTRO_ACKNOWLEDGED diff --git a/ui/js/selectors/settings.js b/ui/js/selectors/settings.js index c4642e39f..5bf7f7f74 100644 --- a/ui/js/selectors/settings.js +++ b/ui/js/selectors/settings.js @@ -25,10 +25,8 @@ export const selectSettingsIsGenerous = createSelector( settings => settings && settings.is_generous_host ); -export const selectShowNsfw = createSelector( - selectClientSettings, - clientSettings => !!clientSettings.showNsfw -); +//refactor me +export const selectShowNsfw = makeSelectClientSetting(settings.SHOW_NSFW); export const selectLanguages = createSelector( _selectState, From 24e21271a7423a26ab450b0b14bfae0da80e5b52 Mon Sep 17 00:00:00 2001 From: Baltazar Gomez Date: Fri, 25 Aug 2017 18:10:57 -0600 Subject: [PATCH 073/132] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c03d0bf8a..1ff9ee49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added * Added a tipping button to send LBRY Credits to the publisher + * Added edit button on published content / improved UX for editing claims. * File pages now show the time of a publish. * The "auth token" displayable on Help offers security warning * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. From 73d4f24a5f97cc4b9eb83f7c3c2f9b3cd470e372 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 25 Aug 2017 20:09:56 -0600 Subject: [PATCH 074/132] add edit-claim button --- ui/js/component/fileActions/index.js | 3 ++- ui/js/component/fileActions/view.jsx | 7 +++++++ ui/js/component/publishForm/view.jsx | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 02fb213da..fa86c3e54 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -8,7 +8,7 @@ import { } from "selectors/file_info"; import { makeSelectIsAvailableForUri } from "selectors/availability"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; -import { doCloseModal, doOpenModal } from "actions/app"; +import { doCloseModal, doOpenModal, doNavigate } from "actions/app"; import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; import { @@ -52,6 +52,7 @@ const perform = dispatch => ({ startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), loadVideo: uri => dispatch(doLoadVideo(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), + navigate: (path, params) => dispatch(doNavigate(path, params)), }); export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 2642ea7e4..b437341d5 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -78,6 +78,7 @@ class FileActions extends React.PureComponent { loading, claimIsMine, claimInfo, + navigate, } = this.props; const metadata = fileInfo ? fileInfo.metadata : null, @@ -185,6 +186,12 @@ class FileActions extends React.PureComponent { onClick={() => openInFolder(fileInfo)} label={openInFolderMessage} /> + {claimIsMine && + navigate("/publish", { name: fileInfo.name })} + label={__("Edit claim")} + />} openModal(modals.CONFIRM_FILE_REMOVE)} diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index f770ae38e..b01438edf 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -187,6 +187,14 @@ class PublishForm extends React.PureComponent { return !!myClaims.find(claim => claim.name === name); } + handleEditClaim() { + const isMine = this.myClaimExists(); + + if (isMine) { + this.handlePrefillClicked(); + } + } + topClaimIsMine() { const myClaimInfo = this.myClaimInfo(); const { claimsByUri } = this.props; @@ -410,8 +418,16 @@ class PublishForm extends React.PureComponent { } componentWillMount() { + const { name } = this.props.params; + this.props.fetchClaimListMine(); this._updateChannelList(); + + if (name) this.setState({ name }); + } + + componentDidMount() { + this.handleEditClaim(); } onFileChange() { From b8cadad26b870d088a99e539c4d45dc60e6065d4 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 25 Aug 2017 20:18:07 -0600 Subject: [PATCH 075/132] update message for use existing claim -> Edit existing claim --- ui/js/component/publishForm/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index b01438edf..5ada5c29e 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -471,7 +471,7 @@ class PublishForm extends React.PureComponent { {__("You already have a claim with this name.")}{" "} this.handlePrefillClicked()} /> From 2a09110d53b673d95fae16bc1421488e03439b07 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Fri, 25 Aug 2017 21:32:21 -0600 Subject: [PATCH 076/132] update rawName and channel on edit claim --- ui/js/component/fileActions/view.jsx | 5 ++++- ui/js/component/publishForm/view.jsx | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index b437341d5..cf6db5680 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -81,6 +81,9 @@ class FileActions extends React.PureComponent { navigate, } = this.props; + const name = fileInfo ? fileInfo.name : null; + const channel = fileInfo ? fileInfo.channel_name : null; + const metadata = fileInfo ? fileInfo.metadata : null, openInFolderMessage = platform.startsWith("Mac") ? __("Open in Finder") @@ -189,7 +192,7 @@ class FileActions extends React.PureComponent { {claimIsMine && navigate("/publish", { name: fileInfo.name })} + onClick={() => navigate("/publish", { name, channel })} label={__("Edit claim")} />} Date: Fri, 25 Aug 2017 23:33:04 -0600 Subject: [PATCH 077/132] simple fix for #467 --- ui/js/component/fileActions/view.jsx | 3 ++- ui/js/component/publishForm/view.jsx | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index cf6db5680..85dfbc1b4 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -82,6 +82,7 @@ class FileActions extends React.PureComponent { } = this.props; const name = fileInfo ? fileInfo.name : null; + const path = fileInfo ? fileInfo.download_path : null; const channel = fileInfo ? fileInfo.channel_name : null; const metadata = fileInfo ? fileInfo.metadata : null, @@ -192,7 +193,7 @@ class FileActions extends React.PureComponent { {claimIsMine && navigate("/publish", { name, channel })} + onClick={() => navigate("/publish", { name, channel, path })} label={__("Edit claim")} />} { this.onFileChange(event); }} From 9f154ac6b7f53f653fab70f73f1c36301ec9b393 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 26 Aug 2017 10:46:20 -0600 Subject: [PATCH 078/132] revert last commit fa531e9 --- ui/js/component/fileActions/view.jsx | 3 +-- ui/js/component/publishForm/view.jsx | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 85dfbc1b4..cf6db5680 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -82,7 +82,6 @@ class FileActions extends React.PureComponent { } = this.props; const name = fileInfo ? fileInfo.name : null; - const path = fileInfo ? fileInfo.download_path : null; const channel = fileInfo ? fileInfo.channel_name : null; const metadata = fileInfo ? fileInfo.metadata : null, @@ -193,7 +192,7 @@ class FileActions extends React.PureComponent { {claimIsMine && navigate("/publish", { name, channel, path })} + onClick={() => navigate("/publish", { name, channel })} label={__("Edit claim")} />} { this.onFileChange(event); }} From cde7008853becd750b77e3947494f1bf29a2385c Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 28 Aug 2017 21:17:13 -0600 Subject: [PATCH 079/132] use source when no file_path is provided - fix #467 --- ui/js/component/publishForm/view.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 28868e8a1..46c7b55c4 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -282,6 +282,8 @@ class PublishForm extends React.PureComponent { nsfw, } = claimInfo.value.stream.metadata; + const { source } = claimInfo.value.stream; + console.log(claimInfo); let newState = { meta_title: title, meta_thumbnail: thumbnail, From 61a83614ea4f2525ef7c0c7074e7c4152d3bb6c4 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 28 Aug 2017 21:18:21 -0600 Subject: [PATCH 080/132] remove debug for claimInfo --- ui/js/component/publishForm/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 46c7b55c4..305ca6e55 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -283,7 +283,7 @@ class PublishForm extends React.PureComponent { } = claimInfo.value.stream.metadata; const { source } = claimInfo.value.stream; - console.log(claimInfo); + let newState = { meta_title: title, meta_thumbnail: thumbnail, From 86c7bda9c86a69fea7bd11a5bcd4dd2e11d52c78 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 3 Sep 2017 13:06:44 -0400 Subject: [PATCH 081/132] fix merge --- ui/js/component/publishForm/view.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 305ca6e55..28868e8a1 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -282,8 +282,6 @@ class PublishForm extends React.PureComponent { nsfw, } = claimInfo.value.stream.metadata; - const { source } = claimInfo.value.stream; - let newState = { meta_title: title, meta_thumbnail: thumbnail, From 7a5f3c606df487c70677a28366b2c008bba810a7 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 3 Sep 2017 13:21:23 -0400 Subject: [PATCH 082/132] minor fixes --- ui/js/component/fileActions/index.js | 3 ++- ui/js/selectors/claims.js | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index fa86c3e54..75e884cc2 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -8,7 +8,8 @@ import { } from "selectors/file_info"; import { makeSelectIsAvailableForUri } from "selectors/availability"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; -import { doCloseModal, doOpenModal, doNavigate } from "actions/app"; +import { doCloseModal, doOpenModal } from "actions/app"; +import { doNavigate } from "actions/navigation"; import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; import { diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 630e72c3e..f4b6344b5 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -53,8 +53,7 @@ const selectClaimForUriIsMine = (state, props) => { const uri = lbryuri.normalize(props.uri); const claim = selectClaimsByUri(state)[uri]; const myClaims = selectMyClaimsRaw(state); - - return myClaims.has(claim.claim_id); + return myClaims && myClaims.has(claim.claim_id); }; export const makeSelectClaimForUriIsMine = () => { From dd5aada7ec26f419f5ee0cf5e0baccd9430a7d83 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 4 Sep 2017 00:31:47 -0600 Subject: [PATCH 083/132] fix for anonymous edit --- ui/js/component/publishForm/view.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 28868e8a1..2e68ac924 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -418,14 +418,15 @@ class PublishForm extends React.PureComponent { } componentWillMount() { - const { name, channel } = this.props.params; - const rawName = name; + let { name, channel } = this.props.params; + + channel = channel || this.state.channel; this.props.fetchClaimListMine(); this._updateChannelList(); - if (name && channel) { - this.setState({ name, rawName, channel }); + if (name) { + this.setState({ name, rawName: name, channel }); } } From a28b4b0c87ec30c8a0342ae3f227e96162706ae9 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 4 Sep 2017 19:03:48 -0600 Subject: [PATCH 084/132] better label for submit button --- ui/js/component/publishForm/view.jsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 2e68ac924..2cc10c3a0 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -48,6 +48,7 @@ class PublishForm extends React.PureComponent { isFee: false, customUrl: false, source: null, + mode: "publish", }; } @@ -283,6 +284,7 @@ class PublishForm extends React.PureComponent { } = claimInfo.value.stream.metadata; let newState = { + mode: "edit", meta_title: title, meta_thumbnail: thumbnail, meta_description: description, @@ -513,10 +515,18 @@ class PublishForm extends React.PureComponent { } render() { + const { mode, submitting } = this.state; + const lbcInputHelp = __( "This LBC remains yours and the deposit can be undone at any time." ); + let submitLabel = !submitting ? __("Publish") : __("Publishing..."); + + if (mode === "edit") { + submitLabel = !submitting ? __("Update") : __("Updating..."); + } + return (
{ this.handleSubmit(event); }} From 7766b6db2894aa9cd3e61aa5284315bc66e05813 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 4 Sep 2017 20:11:59 -0600 Subject: [PATCH 085/132] improve submit label logic --- ui/js/component/publishForm/view.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 2cc10c3a0..aa05e4e43 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -235,6 +235,7 @@ class PublishForm extends React.PureComponent { name: "", uri: "", prefillDone: false, + mode: "publish", }); return; @@ -256,6 +257,7 @@ class PublishForm extends React.PureComponent { rawName: rawName, name: name, prefillDone: false, + mode: "publish", uri, }); @@ -385,6 +387,7 @@ class PublishForm extends React.PureComponent { handleChannelChange(channelName) { this.setState({ + mode: "publish", channel: channelName, }); const nameChanged = () => this.nameChanged(this.state.rawName); From 72d98767c6322f6ee82774f4048803a42b5e13ac Mon Sep 17 00:00:00 2001 From: btzr-io Date: Mon, 4 Sep 2017 21:03:28 -0600 Subject: [PATCH 086/132] add and use editClaim action --- ui/js/actions/file_info.js | 8 +++++++- ui/js/component/fileActions/index.js | 10 +++------- ui/js/component/fileActions/view.jsx | 3 ++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js index 7d9d102c6..7f4f103a0 100644 --- a/ui/js/actions/file_info.js +++ b/ui/js/actions/file_info.js @@ -13,7 +13,7 @@ import { selectTotalDownloadProgress, } from "selectors/file_info"; import { doCloseModal } from "actions/app"; -import { doHistoryBack } from "actions/navigation"; +import { doNavigate, doHistoryBack } from "actions/navigation"; import setProgressBar from "util/setProgressBar"; import batchActions from "util/batchActions"; @@ -155,3 +155,9 @@ export function doFetchFileInfosAndPublishedClaims() { if (!isFetchingFileInfo) dispatch(doFileList()); }; } + +export function doEditClaim(fileInfo) { + return function(dispatch, getState) { + dispatch(doNavigate("/publish", fileInfo)); + }; +} diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 75e884cc2..179493408 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -9,13 +9,9 @@ import { import { makeSelectIsAvailableForUri } from "selectors/availability"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doCloseModal, doOpenModal } from "actions/app"; -import { doNavigate } from "actions/navigation"; import { doFetchAvailability } from "actions/availability"; -import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; -import { - makeSelectClaimForUriIsMine, - makeSelectClaimForUri, -} from "selectors/claims"; +import { doOpenFileInShell, doOpenFileInFolder, doEditClaim, } from "actions/file_info"; +import { makeSelectClaimForUri,makeSelectClaimForUriIsMine } from "selectors/claims"; import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; import FileActions from "./view"; @@ -53,7 +49,7 @@ const perform = dispatch => ({ startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), loadVideo: uri => dispatch(doLoadVideo(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), - navigate: (path, params) => dispatch(doNavigate(path, params)), + editClaim: fileInfo => dispatch(doEditClaim(fileInfo)), }); export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index cf6db5680..2012ec409 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -79,6 +79,7 @@ class FileActions extends React.PureComponent { claimIsMine, claimInfo, navigate, + editClaim, } = this.props; const name = fileInfo ? fileInfo.name : null; @@ -192,7 +193,7 @@ class FileActions extends React.PureComponent { {claimIsMine && navigate("/publish", { name, channel })} + onClick={() => editClaim({ name, channel })} label={__("Edit claim")} />} Date: Thu, 7 Sep 2017 09:38:44 -0400 Subject: [PATCH 087/132] merge cleanup --- ui/js/actions/app.js | 4 ++-- ui/js/actions/file_info.js | 6 ------ ui/js/component/fileActions/index.js | 10 +++++++--- ui/js/component/fileActions/view.jsx | 12 ++++++------ ui/js/component/form.js | 5 ----- ui/js/modal/modalInsufficientBalance/index.js | 3 ++- ui/js/page/settings/view.jsx | 1 - ui/scss/component/_form-field.scss | 3 ++- 8 files changed, 19 insertions(+), 25 deletions(-) diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 0f8a3bcf3..4a3722caf 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -9,7 +9,7 @@ import { } from "selectors/app"; import { doFetchDaemonSettings } from "actions/settings"; import { doAuthenticate } from "actions/user"; -import { doFileList } from "actions/file_info"; +import { doFetchFileInfosAndPublishedClaims } from "actions/file_info"; const { remote, ipcRenderer, shell } = require("electron"); const path = require("path"); @@ -177,7 +177,7 @@ export function doDaemonReady() { dispatch(doAuthenticate()); dispatch({ type: types.DAEMON_READY }); dispatch(doFetchDaemonSettings()); - dispatch(doFileList()); + dispatch(doFetchFileInfosAndPublishedClaims()); }; } diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js index 7f4f103a0..eb317e484 100644 --- a/ui/js/actions/file_info.js +++ b/ui/js/actions/file_info.js @@ -155,9 +155,3 @@ export function doFetchFileInfosAndPublishedClaims() { if (!isFetchingFileInfo) dispatch(doFileList()); }; } - -export function doEditClaim(fileInfo) { - return function(dispatch, getState) { - dispatch(doNavigate("/publish", fileInfo)); - }; -} diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 179493408..461e7a14a 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -10,9 +10,13 @@ import { makeSelectIsAvailableForUri } from "selectors/availability"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doCloseModal, doOpenModal } from "actions/app"; import { doFetchAvailability } from "actions/availability"; -import { doOpenFileInShell, doOpenFileInFolder, doEditClaim, } from "actions/file_info"; -import { makeSelectClaimForUri,makeSelectClaimForUriIsMine } from "selectors/claims"; +import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; +import { + makeSelectClaimForUri, + makeSelectClaimForUriIsMine, +} from "selectors/claims"; import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; +import { doNavigate } from "actions/navigation"; import FileActions from "./view"; const makeSelect = () => { @@ -49,7 +53,7 @@ const perform = dispatch => ({ startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), loadVideo: uri => dispatch(doLoadVideo(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), - editClaim: fileInfo => dispatch(doEditClaim(fileInfo)), + editClaim: fileInfo => dispatch(doNavigate("/publish", fileInfo)), }); export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 2012ec409..f7f8a3842 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -191,13 +191,13 @@ class FileActions extends React.PureComponent { label={openInFolderMessage} /> {claimIsMine && + editClaim({ name, channel })} + label={__("Edit claim")} + />} editClaim({ name, channel })} - label={__("Edit claim")} - />} - openModal(modals.CONFIRM_FILE_REMOVE)} label={__("Remove...")} /> diff --git a/ui/js/component/form.js b/ui/js/component/form.js index d47d7445a..4b353eb94 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -74,11 +74,6 @@ export class FormRow extends React.PureComponent { } getOptions() { - if (!this._field || !this._field.getOptions) { - console.log(this); - console.log(this._field); - console.log(this._field.getOptions); - } return this._field.getOptions(); } diff --git a/ui/js/modal/modalInsufficientBalance/index.js b/ui/js/modal/modalInsufficientBalance/index.js index c56232caf..5e94a9f9e 100644 --- a/ui/js/modal/modalInsufficientBalance/index.js +++ b/ui/js/modal/modalInsufficientBalance/index.js @@ -1,6 +1,7 @@ import React from "react"; import { connect } from "react-redux"; -import { doCloseModal, doNavigate } from "actions/app"; +import { doCloseModal } from "actions/app"; +import { doNavigate } from "actions/navigation"; import ModalInsufficientBalance from "./view"; const select = state => ({}); diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 8835b0236..c09c1be13 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -259,7 +259,6 @@ class SettingsPage extends React.PureComponent {

{__("Theme")}

- {console.log(theme)} Date: Thu, 7 Sep 2017 17:18:33 -0400 Subject: [PATCH 088/132] pausing during partial refactor --- ui/js/actions/content.js | 2 +- ui/js/component/fileActions/index.js | 13 ++----- ui/js/component/fileActions/view.jsx | 35 +------------------ .../component/video/internal/play-button.jsx | 7 ---- ui/js/constants/modal_types.js | 2 ++ ui/js/modal/modalAffirmPurchase/index.js | 15 ++++++++ ui/js/modal/modalAffirmPurchase/view.jsx | 27 ++++++++++++++ ui/js/modal/modalFileTimeout/index.js | 15 ++++++++ ui/js/modal/modalFileTimeout/view.jsx | 21 +++++++++++ ui/js/modal/modalRemoveFile/index.js | 18 +++++----- ui/js/modal/modalRouter/view.jsx | 8 +++++ ui/js/selectors/navigation.js | 7 ++++ 12 files changed, 108 insertions(+), 62 deletions(-) create mode 100644 ui/js/modal/modalAffirmPurchase/index.js create mode 100644 ui/js/modal/modalAffirmPurchase/view.jsx create mode 100644 ui/js/modal/modalFileTimeout/index.js create mode 100644 ui/js/modal/modalFileTimeout/view.jsx diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index 69c717e88..60961ad10 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -299,7 +299,7 @@ export function doLoadVideo(uri) { data: { uri }, }); - dispatch(doOpenModal("timedOut")); + dispatch(doOpenModal(modals.FILE_TIMEOUT)); } else { dispatch(doDownloadFile(uri, streamInfo)); } diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 461e7a14a..0afa74839 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -1,6 +1,6 @@ import React from "react"; import { connect } from "react-redux"; -import { selectPlatform, selectCurrentModal } from "selectors/app"; +import { selectPlatform } from "selectors/app"; import { makeSelectFileInfoForUri, makeSelectDownloadingForUri, @@ -8,13 +8,10 @@ import { } from "selectors/file_info"; import { makeSelectIsAvailableForUri } from "selectors/availability"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; -import { doCloseModal, doOpenModal } from "actions/app"; +import { doOpenModal } from "actions/app"; import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; -import { - makeSelectClaimForUri, - makeSelectClaimForUriIsMine, -} from "selectors/claims"; +import { makeSelectClaimForUriIsMine } from "selectors/claims"; import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; import { doNavigate } from "actions/navigation"; import FileActions from "./view"; @@ -26,19 +23,16 @@ const makeSelect = () => { const selectCostInfoForUri = makeSelectCostInfoForUri(); const selectLoadingForUri = makeSelectLoadingForUri(); const selectClaimForUriIsMine = makeSelectClaimForUriIsMine(); - const selectClaimForUri = makeSelectClaimForUri(); const select = (state, props) => ({ fileInfo: selectFileInfoForUri(state, props), /*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ isAvailable: true, //selectIsAvailableForUri(state, props), platform: selectPlatform(state), - modal: selectCurrentModal(state), downloading: selectDownloadingForUri(state, props), costInfo: selectCostInfoForUri(state, props), loading: selectLoadingForUri(state, props), claimIsMine: selectClaimForUriIsMine(state, props), - claimInfo: selectClaimForUri(state, props), }); return select; @@ -46,7 +40,6 @@ const makeSelect = () => { const perform = dispatch => ({ checkAvailability: uri => dispatch(doFetchAvailability(uri)), - closeModal: () => dispatch(doCloseModal()), openInFolder: fileInfo => dispatch(doOpenFileInFolder(fileInfo)), openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), openModal: modal => dispatch(doOpenModal(modal)), diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index f7f8a3842..51ef4bd84 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,11 +1,8 @@ import React from "react"; import { Icon, BusyMessage } from "component/common"; -import FilePrice from "component/filePrice"; -import { Modal } from "modal/modal"; import Link from "component/link"; import { ToolTip } from "component/tooltip"; import { DropDownMenu, DropDownMenuItem } from "component/menu"; -import ModalRemoveFile from "modal/modalRemoveFile"; import * as modals from "constants/modal_types"; class FileActions extends React.PureComponent { @@ -70,15 +67,11 @@ class FileActions extends React.PureComponent { uri, openInFolder, openInShell, - modal, openModal, - closeModal, startDownload, costInfo, loading, claimIsMine, - claimInfo, - navigate, editClaim, } = this.props; @@ -204,33 +197,7 @@ class FileActions extends React.PureComponent {
: ""} - - {__("This will purchase")} {title} {__("for")}{" "} - - - {" "} - {__("credits")}. - - - {__("LBRY was unable to download the stream")}{" "}{" "} - {title}. - - {modal == modals.CONFIRM_FILE_REMOVE && - } + ); } diff --git a/ui/js/component/video/internal/play-button.jsx b/ui/js/component/video/internal/play-button.jsx index 2ae39fe7c..17d2817db 100644 --- a/ui/js/component/video/internal/play-button.jsx +++ b/ui/js/component/video/internal/play-button.jsx @@ -87,13 +87,6 @@ class VideoPlayButton extends React.PureComponent { {" "} {__("credits")}. - - {__("Sorry, your download timed out :(")} - ); } diff --git a/ui/js/constants/modal_types.js b/ui/js/constants/modal_types.js index 09ddb8451..9e82be50a 100644 --- a/ui/js/constants/modal_types.js +++ b/ui/js/constants/modal_types.js @@ -1,5 +1,6 @@ export const CONFIRM_FILE_REMOVE = "confirmFileRemove"; export const INCOMPATIBLE_DAEMON = "incompatibleDaemon"; +export const FILE_TIMEOUT = "file_timeout"; export const DOWNLOADING = "downloading"; export const ERROR = "error"; export const INSUFFICIENT_CREDITS = "insufficient_credits"; @@ -10,4 +11,5 @@ export const AUTHENTICATION_FAILURE = "auth_failure"; export const TRANSACTION_FAILED = "transaction_failed"; export const INSUFFICIENT_BALANCE = "insufficient_balance"; export const REWARD_APPROVAL_REQUIRED = "reward_approval_required"; +export const AFFIRM_PURCHASE = "affirm_purchase"; export const CREDIT_INTRO = "credit_intro"; diff --git a/ui/js/modal/modalAffirmPurchase/index.js b/ui/js/modal/modalAffirmPurchase/index.js new file mode 100644 index 000000000..f76921431 --- /dev/null +++ b/ui/js/modal/modalAffirmPurchase/index.js @@ -0,0 +1,15 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal } from "actions/app"; +import { makeSelectMetadataForUri } from "selectors/claims"; +import ModalAffirmPurchase from "./view"; + +const select = state => ({ + metadata: makeSelectMetadataForUri()(state), +}); + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalAffirmPurchase); diff --git a/ui/js/modal/modalAffirmPurchase/view.jsx b/ui/js/modal/modalAffirmPurchase/view.jsx new file mode 100644 index 000000000..3f886322e --- /dev/null +++ b/ui/js/modal/modalAffirmPurchase/view.jsx @@ -0,0 +1,27 @@ +import React from "react"; +import FilePrice from "component/filePrice"; +import { Modal } from "modal/modal"; + +class ModalAffirmPurchase extends React.PureComponent { + render() { + const { metadata: { title } } = this.props; + + return ( + + {__("This will purchase")} {title} {__("for")}{" "} + + + {" "} + {__("credits")}. + + ); + } +} + +export default ModalAffirmPurchase; diff --git a/ui/js/modal/modalFileTimeout/index.js b/ui/js/modal/modalFileTimeout/index.js new file mode 100644 index 000000000..44dd592e7 --- /dev/null +++ b/ui/js/modal/modalFileTimeout/index.js @@ -0,0 +1,15 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal } from "actions/app"; +import { makeSelectMetadataForUri } from "selectors/claims"; +import ModalFileTimeout from "./view"; + +const select = state => ({ + metadata: makeSelectMetadataForUri()(state), +}); + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(ModalFileTimeout); diff --git a/ui/js/modal/modalFileTimeout/view.jsx b/ui/js/modal/modalFileTimeout/view.jsx new file mode 100644 index 000000000..9a0916c66 --- /dev/null +++ b/ui/js/modal/modalFileTimeout/view.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import { Modal } from "modal/modal"; + +class ModalFileTimeout extends React.PureComponent { + render() { + const { metadata: { title } } = this.props; + + return ( + + {__("LBRY was unable to download the stream")}{" "} + {title}. + + ); + } +} + +export default ModalFileTimeout; diff --git a/ui/js/modal/modalRemoveFile/index.js b/ui/js/modal/modalRemoveFile/index.js index f64c1987e..c3ae80968 100644 --- a/ui/js/modal/modalRemoveFile/index.js +++ b/ui/js/modal/modalRemoveFile/index.js @@ -5,16 +5,14 @@ import { doDeleteFileAndGoBack } from "actions/file_info"; import { makeSelectClaimForUriIsMine } from "selectors/claims"; import ModalRemoveFile from "./view"; +import { makeSelectFileInfoForUri } from "../../selectors/file_info"; -const makeSelect = () => { - const selectClaimForUriIsMine = makeSelectClaimForUriIsMine(); - - const select = (state, props) => ({ - claimIsMine: selectClaimForUriIsMine(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + claimIsMine: makeSelectClaimForUriIsMine()(state, props), + uri: makeSelectCurrentParam("uri")(state, props), + metadata: makeSelectMetadataForUri()(state, props), + outpoint: makeSelectFileInfoForUri()(state, props), +}); const perform = dispatch => ({ closeModal: () => dispatch(doCloseModal()), @@ -23,4 +21,4 @@ const perform = dispatch => ({ }, }); -export default connect(makeSelect, perform)(ModalRemoveFile); +export default connect(select, perform)(ModalRemoveFile); diff --git a/ui/js/modal/modalRouter/view.jsx b/ui/js/modal/modalRouter/view.jsx index 47ff2d80c..d74cddc44 100644 --- a/ui/js/modal/modalRouter/view.jsx +++ b/ui/js/modal/modalRouter/view.jsx @@ -10,6 +10,8 @@ import ModalRewardApprovalRequired from "modal/modalRewardApprovalRequired"; import ModalCreditIntro from "modal/modalCreditIntro"; import ModalTransactionFailed from "modal/modalTransactionFailed"; import ModalInsufficientBalance from "modal/modalInsufficientBalance"; +import ModalFileTimeout from "modal/modalFileTimeout"; +import ModalAffirmPurchase from "modal/modalAffirmPurchase"; import * as modals from "constants/modal_types"; class ModalRouter extends React.PureComponent { @@ -107,6 +109,8 @@ class ModalRouter extends React.PureComponent { return ; case modals.ERROR: return ; + case modals.FILE_TIMEOUT: + return ; case modals.INSUFFICIENT_CREDITS: return ; case modals.WELCOME: @@ -123,6 +127,10 @@ class ModalRouter extends React.PureComponent { return ; case modals.REWARD_APPROVAL_REQUIRED: return ; + case modals.CONFIRM_FILE_REMOVE: + return ; + case modals.AFFIRM_PURCHASE: + return ; default: return null; } diff --git a/ui/js/selectors/navigation.js b/ui/js/selectors/navigation.js index ca95e259f..08ae51774 100644 --- a/ui/js/selectors/navigation.js +++ b/ui/js/selectors/navigation.js @@ -21,6 +21,13 @@ export const selectCurrentParams = createSelector(selectCurrentPath, path => { return parseQueryParams(path.split("?")[1]); }); +export const makeSelectCurrentParam = param => { + return createSelector( + selectCurrentParams, + params => (params ? params[param] : undefined) + ); +}; + export const selectHeaderLinks = createSelector(selectCurrentPage, page => { // This contains intentional fall throughs switch (page) { From 680bb1df9da1c0dc76a96e0e69515234ef606feb Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 7 Sep 2017 23:15:05 -0400 Subject: [PATCH 089/132] make select and file actions refactor --- ui/js/actions/app.js | 5 +- ui/js/actions/content.js | 15 +- ui/js/component/fileActions/index.js | 44 ++---- ui/js/component/fileActions/view.jsx | 142 +---------------- ui/js/component/fileCard/index.js | 29 ++-- ui/js/component/fileDownloadLink/index.js | 31 ++++ ui/js/component/fileDownloadLink/view.jsx | 104 +++++++++++++ ui/js/component/filePrice/index.js | 20 +-- ui/js/component/fileTile/index.js | 29 ++-- ui/js/component/router/view.jsx | 2 +- ui/js/component/uriIndicator/index.js | 22 +-- ui/js/component/video/index.js | 37 ++--- .../component/video/internal/play-button.jsx | 57 ++----- ui/js/modal/modalAffirmPurchase/index.js | 6 +- ui/js/modal/modalAffirmPurchase/view.jsx | 9 +- ui/js/modal/modalAuthFailure/index.js | 2 +- ui/js/modal/modalError/index.js | 8 +- ui/js/modal/modalError/view.jsx | 4 +- ui/js/modal/modalFileTimeout/index.js | 2 +- ui/js/modal/modalRemoveFile/index.js | 15 +- ui/js/modal/modalRemoveFile/view.jsx | 8 +- ui/js/modal/modalRouter/index.js | 3 +- ui/js/modal/modalRouter/view.jsx | 33 ++-- ui/js/page/channel/index.js | 28 ++-- ui/js/page/channel/view.jsx | 16 +- ui/js/page/file/index.js | 30 ++-- ui/js/page/show/index.js | 19 +-- ui/js/page/show/view.jsx | 9 +- ui/js/reducers/app.js | 6 +- ui/js/selectors/app.js | 4 +- ui/js/selectors/availability.js | 21 +-- ui/js/selectors/claims.js | 146 +++++++----------- ui/js/selectors/content.js | 19 +-- ui/js/selectors/cost_info.js | 22 ++- ui/js/selectors/file_info.js | 48 +++--- 35 files changed, 409 insertions(+), 586 deletions(-) create mode 100644 ui/js/component/fileDownloadLink/index.js create mode 100644 ui/js/component/fileDownloadLink/view.jsx diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 4a3722caf..67fb76071 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -17,11 +17,12 @@ const { download } = remote.require("electron-dl"); const fs = remote.require("fs"); const { lbrySettings: config } = require("../../../app/package.json"); -export function doOpenModal(modal) { +export function doOpenModal(modal, modalProps = {}) { return { type: types.OPEN_MODAL, data: { modal, + modalProps, }, }; } @@ -166,7 +167,7 @@ export function doAlertError(errorList) { type: types.OPEN_MODAL, data: { modal: "error", - extraContent: errorList, + modalProps: { error: errorList }, }, }); }; diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index 60961ad10..ed9324f77 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -4,11 +4,11 @@ import lbryio from "lbryio"; import lbryuri from "lbryuri"; import { selectBalance } from "selectors/wallet"; import { - selectFileInfoForUri, + makeSelectFileInfoForUri, selectDownloadingByOutpoint, } from "selectors/file_info"; import { selectResolvingUris } from "selectors/content"; -import { selectCostInfoForUri } from "selectors/cost_info"; +import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doAlertError, doOpenModal } from "actions/app"; import { doClaimEligiblePurchaseRewards } from "actions/rewards"; import { selectBadgeNumber } from "selectors/app"; @@ -299,13 +299,12 @@ export function doLoadVideo(uri) { data: { uri }, }); - dispatch(doOpenModal(modals.FILE_TIMEOUT)); + dispatch(doOpenModal(modals.FILE_TIMEOUT, { uri })); } else { dispatch(doDownloadFile(uri, streamInfo)); } }) .catch(error => { - console.log(error); dispatch({ type: types.LOADING_VIDEO_FAILED, data: { uri }, @@ -315,11 +314,11 @@ export function doLoadVideo(uri) { }; } -export function doPurchaseUri(uri, purchaseModalName) { +export function doPurchaseUri(uri) { return function(dispatch, getState) { const state = getState(); const balance = selectBalance(state); - const fileInfo = selectFileInfoForUri(state, { uri }); + const fileInfo = makeSelectFileInfoForUri(uri)(state); const downloadingByOutpoint = selectDownloadingByOutpoint(state); const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint]; @@ -339,7 +338,7 @@ export function doPurchaseUri(uri, purchaseModalName) { return Promise.resolve(); } - const costInfo = selectCostInfoForUri(state, { uri }); + const costInfo = makeSelectCostInfoForUri(uri)(state); const { cost } = costInfo; // the file is free or we have partially downloaded it @@ -351,7 +350,7 @@ export function doPurchaseUri(uri, purchaseModalName) { if (cost > balance) { dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS)); } else { - dispatch(doOpenModal(purchaseModalName)); + dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri })); } return Promise.resolve(); diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 0afa74839..f8a5d8424 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -1,52 +1,32 @@ import React from "react"; import { connect } from "react-redux"; import { selectPlatform } from "selectors/app"; -import { - makeSelectFileInfoForUri, - makeSelectDownloadingForUri, - makeSelectLoadingForUri, -} from "selectors/file_info"; -import { makeSelectIsAvailableForUri } from "selectors/availability"; +import { makeSelectFileInfoForUri } from "selectors/file_info"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doOpenModal } from "actions/app"; import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; -import { makeSelectClaimForUriIsMine } from "selectors/claims"; +import { makeSelectClaimIsMine } from "selectors/claims"; import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; import { doNavigate } from "actions/navigation"; import FileActions from "./view"; -const makeSelect = () => { - const selectFileInfoForUri = makeSelectFileInfoForUri(); - const selectIsAvailableForUri = makeSelectIsAvailableForUri(); - const selectDownloadingForUri = makeSelectDownloadingForUri(); - const selectCostInfoForUri = makeSelectCostInfoForUri(); - const selectLoadingForUri = makeSelectLoadingForUri(); - const selectClaimForUriIsMine = makeSelectClaimForUriIsMine(); - - const select = (state, props) => ({ - fileInfo: selectFileInfoForUri(state, props), - /*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ - isAvailable: true, //selectIsAvailableForUri(state, props), - platform: selectPlatform(state), - downloading: selectDownloadingForUri(state, props), - costInfo: selectCostInfoForUri(state, props), - loading: selectLoadingForUri(state, props), - claimIsMine: selectClaimForUriIsMine(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + /*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ + platform: selectPlatform(state), + costInfo: makeSelectCostInfoForUri(props.uri)(state), + claimIsMine: makeSelectClaimIsMine(props.uri)(state), +}); const perform = dispatch => ({ checkAvailability: uri => dispatch(doFetchAvailability(uri)), openInFolder: fileInfo => dispatch(doOpenFileInFolder(fileInfo)), openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), - openModal: modal => dispatch(doOpenModal(modal)), - startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")), - loadVideo: uri => dispatch(doLoadVideo(uri)), + openModal: (modal, props) => dispatch(doOpenModal(modal, props)), + startDownload: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), editClaim: fileInfo => dispatch(doNavigate("/publish", fileInfo)), }); -export default connect(makeSelect, perform)(FileActions); +export default connect(select, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 51ef4bd84..d530f4ea7 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,59 +1,10 @@ import React from "react"; -import { Icon, BusyMessage } from "component/common"; import Link from "component/link"; -import { ToolTip } from "component/tooltip"; +import FileDownloadLink from "component/fileDownloadLink"; import { DropDownMenu, DropDownMenuItem } from "component/menu"; import * as modals from "constants/modal_types"; class FileActions extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - forceShowActions: false, - }; - } - - componentWillMount() { - this.checkAvailability(this.props.uri); - } - - componentWillReceiveProps(nextProps) { - this.checkAvailability(nextProps.uri); - this.restartDownload(nextProps); - } - - restartDownload(props) { - const { downloading, fileInfo, uri, restartDownload } = props; - - if ( - !downloading && - fileInfo && - !fileInfo.completed && - fileInfo.written_bytes !== false && - fileInfo.written_bytes < fileInfo.total_bytes - ) { - restartDownload(uri, fileInfo.outpoint); - } - } - - checkAvailability(uri) { - if (!this._uri || uri !== this._uri) { - this._uri = uri; - this.props.checkAvailability(uri); - } - } - - onShowFileActionsRowClicked() { - this.setState({ - forceShowActions: true, - }); - } - - onAffirmPurchase() { - this.props.closeModal(); - this.props.loadVideo(this.props.uri); - } - handleSupportButtonClicked() { this.props.onTipShow(); } @@ -61,16 +12,10 @@ class FileActions extends React.PureComponent { render() { const { fileInfo, - isAvailable, platform, - downloading, uri, openInFolder, - openInShell, openModal, - startDownload, - costInfo, - loading, claimIsMine, editClaim, } = this.props; @@ -85,90 +30,9 @@ class FileActions extends React.PureComponent { showMenu = fileInfo && Object.keys(fileInfo).length > 0, title = metadata ? metadata.title : uri; - let content; - - if (loading || downloading) { - const progress = fileInfo && fileInfo.written_bytes - ? fileInfo.written_bytes / fileInfo.total_bytes * 100 - : 0, - label = fileInfo - ? progress.toFixed(0) + __("% complete") - : __("Connecting..."), - labelWithIcon = ( - - - - {label} - - - ); - - content = ( -
-
- {labelWithIcon} -
- {labelWithIcon} -
- ); - } else if (!fileInfo && isAvailable === undefined) { - content = ; - } else if (!fileInfo && !isAvailable && !this.state.forceShowActions) { - content = ( -
-
- {__("Content unavailable.")} -
- - -
- ); - } else if (fileInfo === null && !downloading) { - if (!costInfo) { - content = ; - } else { - content = ( - { - startDownload(uri); - }} - /> - ); - } - } else if (fileInfo && fileInfo.download_path) { - content = ( - openInShell(fileInfo)} - /> - ); - } else if (!fileInfo) { - content = ; - } else { - console.log("handle this case of file action props?"); - } - return (
- {content} + } openModal(modals.CONFIRM_FILE_REMOVE)} + onClick={() => openModal(modals.CONFIRM_FILE_REMOVE, { uri })} label={__("Remove...")} /> diff --git a/ui/js/component/fileCard/index.js b/ui/js/component/fileCard/index.js index d933736e8..a0de51640 100644 --- a/ui/js/component/fileCard/index.js +++ b/ui/js/component/fileCard/index.js @@ -9,32 +9,23 @@ import { } from "selectors/claims"; import { makeSelectFileInfoForUri } from "selectors/file_info"; import { - makeSelectIsResolvingForUri, + makeSelectIsUriResolving, selectRewardContentClaimIds, } from "selectors/content"; import FileCard from "./view"; -const makeSelect = () => { - const selectClaimForUri = makeSelectClaimForUri(); - const selectFileInfoForUri = makeSelectFileInfoForUri(); - const selectMetadataForUri = makeSelectMetadataForUri(); - const selectResolvingUri = makeSelectIsResolvingForUri(); - - const select = (state, props) => ({ - claim: selectClaimForUri(state, props), - fileInfo: selectFileInfoForUri(state, props), - obscureNsfw: !selectShowNsfw(state), - metadata: selectMetadataForUri(state, props), - rewardedContentClaimIds: selectRewardContentClaimIds(state, props), - isResolvingUri: selectResolvingUri(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + obscureNsfw: !selectShowNsfw(state), + metadata: makeSelectMetadataForUri(props.uri)(state), + rewardedContentClaimIds: selectRewardContentClaimIds(state, props), + isResolvingUri: makeSelectIsUriResolving(props.uri)(state), +}); const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), resolveUri: uri => dispatch(doResolveUri(uri)), }); -export default connect(makeSelect, perform)(FileCard); +export default connect(select, perform)(FileCard); diff --git a/ui/js/component/fileDownloadLink/index.js b/ui/js/component/fileDownloadLink/index.js new file mode 100644 index 000000000..f9657f17b --- /dev/null +++ b/ui/js/component/fileDownloadLink/index.js @@ -0,0 +1,31 @@ +import React from "react"; +import { connect } from "react-redux"; +import { + makeSelectFileInfoForUri, + makeSelectDownloadingForUri, + makeSelectLoadingForUri, +} from "selectors/file_info"; +import { makeSelectCostInfoForUri } from "selectors/cost_info"; +import { doFetchAvailability } from "actions/availability"; +import { doOpenFileInShell } from "actions/file_info"; +import { doPurchaseUri, doStartDownload } from "actions/content"; +import FileDownloadLink from "./view"; +import * as modals from "constants/modal_types"; + +const select = (state, props) => ({ + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + /*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ + downloading: makeSelectDownloadingForUri(props.uri)(state), + costInfo: makeSelectCostInfoForUri(props.uri)(state), + loading: makeSelectLoadingForUri(props.uri)(state), +}); + +const perform = dispatch => ({ + checkAvailability: uri => dispatch(doFetchAvailability(uri)), + openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), + startDownload: uri => + dispatch(doPurchaseUri(uri, modals.CONFIRM_FILE_PURCHASE)), + restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), +}); + +export default connect(select, perform)(FileDownloadLink); diff --git a/ui/js/component/fileDownloadLink/view.jsx b/ui/js/component/fileDownloadLink/view.jsx new file mode 100644 index 000000000..fd1818ed7 --- /dev/null +++ b/ui/js/component/fileDownloadLink/view.jsx @@ -0,0 +1,104 @@ +import React from "react"; +import { Icon, BusyMessage } from "component/common"; +import Link from "component/link"; + +class FileDownloadLink extends React.PureComponent { + componentWillMount() { + this.checkAvailability(this.props.uri); + } + + componentWillReceiveProps(nextProps) { + this.checkAvailability(nextProps.uri); + this.restartDownload(nextProps); + } + + restartDownload(props) { + const { downloading, fileInfo, uri, restartDownload } = props; + + if ( + !downloading && + fileInfo && + !fileInfo.completed && + fileInfo.written_bytes !== false && + fileInfo.written_bytes < fileInfo.total_bytes + ) { + restartDownload(uri, fileInfo.outpoint); + } + } + + checkAvailability(uri) { + if (!this._uri || uri !== this._uri) { + this._uri = uri; + this.props.checkAvailability(uri); + } + } + + render() { + const { + fileInfo, + downloading, + uri, + openInShell, + startDownload, + costInfo, + loading, + } = this.props; + + if (loading || downloading) { + const progress = fileInfo && fileInfo.written_bytes + ? fileInfo.written_bytes / fileInfo.total_bytes * 100 + : 0, + label = fileInfo + ? progress.toFixed(0) + __("% complete") + : __("Connecting..."), + labelWithIcon = ( + + + + {label} + + + ); + + return ( +
+
+ {labelWithIcon} +
+ {labelWithIcon} +
+ ); + } else if (fileInfo === null && !downloading) { + if (!costInfo) { + return ; + } else { + return ( + { + startDownload(uri); + }} + /> + ); + } + } else if (fileInfo && fileInfo.download_path) { + return ( + openInShell(fileInfo)} + /> + ); + } + + return null; + } +} + +export default FileDownloadLink; diff --git a/ui/js/component/filePrice/index.js b/ui/js/component/filePrice/index.js index be675d924..bac5cafe2 100644 --- a/ui/js/component/filePrice/index.js +++ b/ui/js/component/filePrice/index.js @@ -8,23 +8,15 @@ import { import { makeSelectClaimForUri } from "selectors/claims"; import FilePrice from "./view"; -const makeSelect = () => { - const selectCostInfoForUri = makeSelectCostInfoForUri(); - const selectFetchingCostInfoForUri = makeSelectFetchingCostInfoForUri(); - const selectClaim = makeSelectClaimForUri(); - - const select = (state, props) => ({ - costInfo: selectCostInfoForUri(state, props), - fetching: selectFetchingCostInfoForUri(state, props), - claim: selectClaim(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + costInfo: makeSelectCostInfoForUri(props.uri)(state), + fetching: makeSelectFetchingCostInfoForUri(props.uri)(state), + claim: makeSelectClaimForUri(props.uri)(state), +}); const perform = dispatch => ({ fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)), // cancelFetchCostInfo: (uri) => dispatch(doCancelFetchCostInfoForUri(uri)) }); -export default connect(makeSelect, perform)(FilePrice); +export default connect(select, perform)(FilePrice); diff --git a/ui/js/component/fileTile/index.js b/ui/js/component/fileTile/index.js index 2df504226..75b6ce62b 100644 --- a/ui/js/component/fileTile/index.js +++ b/ui/js/component/fileTile/index.js @@ -9,32 +9,23 @@ import { import { makeSelectFileInfoForUri } from "selectors/file_info"; import { selectShowNsfw } from "selectors/settings"; import { - makeSelectIsResolvingForUri, + makeSelectIsUriResolving, selectRewardContentClaimIds, } from "selectors/content"; import FileTile from "./view"; -const makeSelect = () => { - const selectClaimForUri = makeSelectClaimForUri(); - const selectFileInfoForUri = makeSelectFileInfoForUri(); - const selectMetadataForUri = makeSelectMetadataForUri(); - const selectResolvingUri = makeSelectIsResolvingForUri(); - - const select = (state, props) => ({ - claim: selectClaimForUri(state, props), - fileInfo: selectFileInfoForUri(state, props), - obscureNsfw: !selectShowNsfw(state), - metadata: selectMetadataForUri(state, props), - isResolvingUri: selectResolvingUri(state, props), - rewardedContentClaimIds: selectRewardContentClaimIds(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + obscureNsfw: !selectShowNsfw(state), + metadata: makeSelectMetadataForUri(props.uri)(state), + isResolvingUri: makeSelectIsUriResolving(props.uri)(state), + rewardedContentClaimIds: selectRewardContentClaimIds(state, props), +}); const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), resolveUri: uri => dispatch(doResolveUri(uri)), }); -export default connect(makeSelect, perform)(FileTile); +export default connect(select, perform)(FileTile); diff --git a/ui/js/component/router/view.jsx b/ui/js/component/router/view.jsx index d5ff60a81..57f9630c2 100644 --- a/ui/js/component/router/view.jsx +++ b/ui/js/component/router/view.jsx @@ -46,7 +46,7 @@ const Router = props => { search: , send: , settings: , - show: , + show: , wallet: , }); }; diff --git a/ui/js/component/uriIndicator/index.js b/ui/js/component/uriIndicator/index.js index 839f54575..a57c33b15 100644 --- a/ui/js/component/uriIndicator/index.js +++ b/ui/js/component/uriIndicator/index.js @@ -1,25 +1,19 @@ import React from "react"; import lbryuri from "lbryuri"; import { connect } from "react-redux"; -import { makeSelectIsResolvingForUri } from "selectors/content"; +import { doResolveUri } from "actions/content"; +import { makeSelectIsUriResolving } from "selectors/content"; import { makeSelectClaimForUri } from "selectors/claims"; import UriIndicator from "./view"; -const makeSelect = () => { - const selectClaim = makeSelectClaimForUri(), - selectIsResolving = makeSelectIsResolvingForUri(); - - const select = (state, props) => ({ - claim: selectClaim(state, props), - isResolvingUri: selectIsResolving(state, props), - uri: lbryuri.normalize(props.uri), - }); - - return select; -}; +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + isResolvingUri: makeSelectIsUriResolving(props.uri)(state), + uri: lbryuri.normalize(props.uri), +}); const perform = dispatch => ({ resolveUri: uri => dispatch(doResolveUri(uri)), }); -export default connect(makeSelect, perform)(UriIndicator); +export default connect(select, perform)(UriIndicator); diff --git a/ui/js/component/video/index.js b/ui/js/component/video/index.js index f28fb94b8..36eeb3168 100644 --- a/ui/js/component/video/index.js +++ b/ui/js/component/video/index.js @@ -17,34 +17,21 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { selectShowNsfw } from "selectors/settings"; import Video from "./view"; -const makeSelect = () => { - const selectCostInfo = makeSelectCostInfoForUri(); - const selectFileInfo = makeSelectFileInfoForUri(); - const selectIsLoading = makeSelectLoadingForUri(); - const selectIsDownloading = makeSelectDownloadingForUri(); - const selectMetadata = makeSelectMetadataForUri(); - const selectContentType = makeSelectContentTypeForUri(); - - const select = (state, props) => ({ - costInfo: selectCostInfo(state, props), - fileInfo: selectFileInfo(state, props), - metadata: selectMetadata(state, props), - obscureNsfw: !selectShowNsfw(state), - modal: selectCurrentModal(state), - isLoading: selectIsLoading(state, props), - isDownloading: selectIsDownloading(state, props), - contentType: selectContentType(state, props), - volume: selectVolume(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + costInfo: makeSelectCostInfoForUri(props.uri)(state), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + metadata: makeSelectMetadataForUri(props.uri)(state), + obscureNsfw: !selectShowNsfw(state), + isLoading: makeSelectLoadingForUri(props.uri)(state), + isDownloading: makeSelectDownloadingForUri(props.uri)(state), + contentType: makeSelectContentTypeForUri(props.uri)(state), + volume: selectVolume(state), +}); const perform = dispatch => ({ loadVideo: uri => dispatch(doLoadVideo(uri)), - purchaseUri: uri => dispatch(doPurchaseUri(uri, "affirmPurchaseAndPlay")), - closeModal: () => dispatch(doCloseModal()), + purchaseUri: uri => dispatch(doPurchaseUri(uri)), changeVolume: volume => dispatch(doChangeVolume(volume)), }); -export default connect(makeSelect, perform)(Video); +export default connect(select, perform)(Video); diff --git a/ui/js/component/video/internal/play-button.jsx b/ui/js/component/video/internal/play-button.jsx index 17d2817db..2df2b2ea4 100644 --- a/ui/js/component/video/internal/play-button.jsx +++ b/ui/js/component/video/internal/play-button.jsx @@ -1,7 +1,5 @@ import React from "react"; -import FilePrice from "component/filePrice"; import Link from "component/link"; -import Modal from "modal/modal"; class VideoPlayButton extends React.PureComponent { componentDidMount() { @@ -13,12 +11,6 @@ class VideoPlayButton extends React.PureComponent { document.removeEventListener("keydown", this.keyDownListener); } - onPurchaseConfirmed() { - this.props.closeModal(); - this.props.startPlaying(); - this.props.loadVideo(this.props.uri); - } - onKeyDown(event) { if ( "input" !== event.target.tagName.toLowerCase() && @@ -33,23 +25,14 @@ class VideoPlayButton extends React.PureComponent { this.props.purchaseUri(this.props.uri).then(() => { if (!this.props.modal) { this.props.startPlaying(); + } else { + alert("fix me set pending play"); } }); } render() { - const { - button, - label, - metadata, - metadata: { title }, - uri, - modal, - closeModal, - isLoading, - fileInfo, - mediaType, - } = this.props; + const { button, label, isLoading, fileInfo, mediaType } = this.props; /* title={ @@ -64,31 +47,15 @@ class VideoPlayButton extends React.PureComponent { ? "icon-play" : "icon-folder-o"; - return ( -
- - - {__("This will purchase")} {title} {__("for")}{" "} - - - {" "} - {__("credits")}. - -
- ); + return; + ; } } diff --git a/ui/js/modal/modalAffirmPurchase/index.js b/ui/js/modal/modalAffirmPurchase/index.js index f76921431..c42afc373 100644 --- a/ui/js/modal/modalAffirmPurchase/index.js +++ b/ui/js/modal/modalAffirmPurchase/index.js @@ -1,15 +1,17 @@ import React from "react"; import { connect } from "react-redux"; import { doCloseModal } from "actions/app"; +import { doLoadVideo } from "actions/content"; import { makeSelectMetadataForUri } from "selectors/claims"; import ModalAffirmPurchase from "./view"; -const select = state => ({ - metadata: makeSelectMetadataForUri()(state), +const select = (state, props) => ({ + metadata: makeSelectMetadataForUri(props.uri)(state), }); const perform = dispatch => ({ closeModal: () => dispatch(doCloseModal()), + loadVideo: uri => dispatch(doLoadVideo(uri)), }); export default connect(select, perform)(ModalAffirmPurchase); diff --git a/ui/js/modal/modalAffirmPurchase/view.jsx b/ui/js/modal/modalAffirmPurchase/view.jsx index 3f886322e..a38e82f1c 100644 --- a/ui/js/modal/modalAffirmPurchase/view.jsx +++ b/ui/js/modal/modalAffirmPurchase/view.jsx @@ -3,13 +3,18 @@ import FilePrice from "component/filePrice"; import { Modal } from "modal/modal"; class ModalAffirmPurchase extends React.PureComponent { + onAffirmPurchase() { + this.props.closeModal(); + this.props.loadVideo(this.props.uri); + } + render() { - const { metadata: { title } } = this.props; + const { closeModal, metadata: { title }, uri } = this.props; return ( ({ close: () => dispatch(doCloseModal()), }); -export default connect(select, perform)(ModalAuthFailure); +export default connect(null, null)(ModalAuthFailure); diff --git a/ui/js/modal/modalError/index.js b/ui/js/modal/modalError/index.js index 47680ecc9..b1cb30f1b 100644 --- a/ui/js/modal/modalError/index.js +++ b/ui/js/modal/modalError/index.js @@ -1,16 +1,10 @@ import React from "react"; import { connect } from "react-redux"; -import { selectCurrentModal, selectModalExtraContent } from "selectors/app"; import { doCloseModal } from "actions/app"; import ModalError from "./view"; -const select = state => ({ - modal: selectCurrentModal(state), - error: selectModalExtraContent(state), -}); - const perform = dispatch => ({ closeModal: () => dispatch(doCloseModal()), }); -export default connect(select, perform)(ModalError); +export default connect(null, perform)(ModalError); diff --git a/ui/js/modal/modalError/view.jsx b/ui/js/modal/modalError/view.jsx index ceb998dee..bbae36a15 100644 --- a/ui/js/modal/modalError/view.jsx +++ b/ui/js/modal/modalError/view.jsx @@ -4,7 +4,7 @@ import { ExpandableModal } from "modal/modal"; class ModalError extends React.PureComponent { render() { - const { modal, closeModal, error } = this.props; + const { closeModal, error } = this.props; const errorObj = typeof error === "string" ? { message: error } : error; @@ -33,7 +33,7 @@ class ModalError extends React.PureComponent { return ( ({ - metadata: makeSelectMetadataForUri()(state), + metadata: makeSelectMetadataForUri(props.uri)(state), }); const perform = dispatch => ({ diff --git a/ui/js/modal/modalRemoveFile/index.js b/ui/js/modal/modalRemoveFile/index.js index c3ae80968..8c00f383e 100644 --- a/ui/js/modal/modalRemoveFile/index.js +++ b/ui/js/modal/modalRemoveFile/index.js @@ -2,16 +2,17 @@ import React from "react"; import { connect } from "react-redux"; import { doCloseModal } from "actions/app"; import { doDeleteFileAndGoBack } from "actions/file_info"; -import { makeSelectClaimForUriIsMine } from "selectors/claims"; - +import { + makeSelectMetadataForUri, + makeSelectClaimIsMine, +} from "selectors/claims"; +import { makeSelectFileInfoForUri } from "selectors/file_info"; import ModalRemoveFile from "./view"; -import { makeSelectFileInfoForUri } from "../../selectors/file_info"; const select = (state, props) => ({ - claimIsMine: makeSelectClaimForUriIsMine()(state, props), - uri: makeSelectCurrentParam("uri")(state, props), - metadata: makeSelectMetadataForUri()(state, props), - outpoint: makeSelectFileInfoForUri()(state, props), + claimIsMine: makeSelectClaimIsMine(props.uri)(state), + metadata: makeSelectMetadataForUri(props.uri)(state), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), }); const perform = dispatch => ({ diff --git a/ui/js/modal/modalRemoveFile/view.jsx b/ui/js/modal/modalRemoveFile/view.jsx index 6dfa9152f..f646c5400 100644 --- a/ui/js/modal/modalRemoveFile/view.jsx +++ b/ui/js/modal/modalRemoveFile/view.jsx @@ -25,7 +25,13 @@ class ModalRemoveFile extends React.PureComponent { } render() { - const { claimIsMine, closeModal, deleteFile, outpoint, title } = this.props; + const { + claimIsMine, + closeModal, + deleteFile, + fileInfo: { outpoint }, + metadata: { title }, + } = this.props; const { deleteChecked, abandonClaimChecked } = this.state; return ( diff --git a/ui/js/modal/modalRouter/index.js b/ui/js/modal/modalRouter/index.js index 79f02385f..c0c637167 100644 --- a/ui/js/modal/modalRouter/index.js +++ b/ui/js/modal/modalRouter/index.js @@ -2,7 +2,7 @@ import React from "react"; import { connect } from "react-redux"; import { doOpenModal } from "actions/app"; import * as settings from "constants/settings"; -import { selectCurrentModal } from "selectors/app"; +import { selectCurrentModal, selectModalProps } from "selectors/app"; import { selectCurrentPage } from "selectors/navigation"; import { selectCostForCurrentPageUri } from "selectors/cost_info"; import { makeSelectClientSetting } from "selectors/settings"; @@ -14,6 +14,7 @@ const select = (state, props) => ({ balance: selectBalance(state), showPageCost: selectCostForCurrentPageUri(state), modal: selectCurrentModal(state), + modalProps: selectModalProps(state), page: selectCurrentPage(state), isWelcomeAcknowledged: makeSelectClientSetting( settings.NEW_USER_ACKNOWLEDGED diff --git a/ui/js/modal/modalRouter/view.jsx b/ui/js/modal/modalRouter/view.jsx index d74cddc44..8d2bf912e 100644 --- a/ui/js/modal/modalRouter/view.jsx +++ b/ui/js/modal/modalRouter/view.jsx @@ -8,6 +8,7 @@ import ModalWelcome from "modal/modalWelcome"; import ModalFirstReward from "modal/modalFirstReward"; import ModalRewardApprovalRequired from "modal/modalRewardApprovalRequired"; import ModalCreditIntro from "modal/modalCreditIntro"; +import ModalRemoveFile from "modal/modalRemoveFile"; import ModalTransactionFailed from "modal/modalTransactionFailed"; import ModalInsufficientBalance from "modal/modalInsufficientBalance"; import ModalFileTimeout from "modal/modalFileTimeout"; @@ -33,7 +34,7 @@ class ModalRouter extends React.PureComponent { } showTransitionModals(props) { - const { modal, openModal, page } = props; + const { modal, modalProps, openModal, page } = props; if (modal) { return; @@ -100,37 +101,37 @@ class ModalRouter extends React.PureComponent { } render() { - const { modal } = this.props; + const { modal, modalProps } = this.props; switch (modal) { case modals.UPGRADE: - return ; + return ; case modals.DOWNLOADING: - return ; + return ; case modals.ERROR: - return ; + return ; case modals.FILE_TIMEOUT: - return ; + return ; case modals.INSUFFICIENT_CREDITS: - return ; + return ; case modals.WELCOME: - return ; + return ; case modals.FIRST_REWARD: - return ; + return ; case modals.AUTHENTICATION_FAILURE: - return ; + return ; case modals.CREDIT_INTRO: - return ; + return ; case modals.TRANSACTION_FAILED: - return ; + return ; case modals.INSUFFICIENT_BALANCE: - return ; + return ; case modals.REWARD_APPROVAL_REQUIRED: - return ; + return ; case modals.CONFIRM_FILE_REMOVE: - return ; + return ; case modals.AFFIRM_PURCHASE: - return ; + return ; default: return null; } diff --git a/ui/js/page/channel/index.js b/ui/js/page/channel/index.js index 95134bdc3..a407f8c48 100644 --- a/ui/js/page/channel/index.js +++ b/ui/js/page/channel/index.js @@ -14,22 +14,16 @@ import { doNavigate } from "actions/navigation"; import { makeSelectTotalPagesForChannel } from "selectors/content"; import ChannelPage from "./view"; -const makeSelect = () => { - const selectClaim = makeSelectClaimForUri(), - selectClaimsInChannel = makeSelectClaimsInChannelForCurrentPage(), - selectFetchingChannelClaims = makeSelectFetchingChannelClaims(), - selectTotalPagesForChannel = makeSelectTotalPagesForChannel(); - - const select = (state, props) => ({ - claim: selectClaim(state, props), - claimsInChannel: selectClaimsInChannel(state, props), - fetching: selectFetchingChannelClaims(state, props), - totalPages: selectTotalPagesForChannel(state, props), - params: selectCurrentParams(state), - }); - - return select; -}; +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + claimsInChannel: makeSelectClaimsInChannelForCurrentPage( + props.uri, + props.page + )(state), + fetching: makeSelectFetchingChannelClaims(props.uri)(state), + params: selectCurrentParams(state), + totalPages: makeSelectTotalPagesForChannel(props.uri)(state), +}); const perform = dispatch => ({ fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)), @@ -37,4 +31,4 @@ const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), }); -export default connect(makeSelect, perform)(ChannelPage); +export default connect(select, perform)(ChannelPage); diff --git a/ui/js/page/channel/view.jsx b/ui/js/page/channel/view.jsx index 1d17fe8b5..617ef84ba 100644 --- a/ui/js/page/channel/view.jsx +++ b/ui/js/page/channel/view.jsx @@ -7,20 +7,19 @@ import ReactPaginate from "react-paginate"; class ChannelPage extends React.PureComponent { componentDidMount() { - const { uri, params, fetchClaims, fetchClaimCount } = this.props; + const { uri, page, fetchClaims, fetchClaimCount } = this.props; - fetchClaims(uri, params.page || 1); + fetchClaims(uri, page || 1); fetchClaimCount(uri); } componentWillReceiveProps(nextProps) { - const { params, fetching, fetchClaims, fetchClaimCount } = this.props; - const nextParams = nextProps.params; + const { page, uri, fetching, fetchClaims, fetchClaimCount } = this.props; - if (fetching !== nextParams.page && params.page !== nextParams.page) { - fetchClaims(nextProps.uri, nextParams.page); + if (fetching !== nextProps.page && page !== nextProps.page) { + fetchClaims(nextProps.uri, nextProps.page); } - if (nextProps.uri != this.props.uri) { + if (nextProps.uri != uri) { fetchClaimCount(uri); } } @@ -38,10 +37,9 @@ class ChannelPage extends React.PureComponent { claimsInChannel, claim, uri, - params, + page, totalPages, } = this.props; - const { page } = params; let contentList; if (claimsInChannel === undefined) { diff --git a/ui/js/page/file/index.js b/ui/js/page/file/index.js index 19cdde31f..d0d1fb476 100644 --- a/ui/js/page/file/index.js +++ b/ui/js/page/file/index.js @@ -14,25 +14,15 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { selectShowNsfw } from "selectors/settings"; import FilePage from "./view"; -const makeSelect = () => { - const selectClaim = makeSelectClaimForUri(), - selectContentType = makeSelectContentTypeForUri(), - selectFileInfo = makeSelectFileInfoForUri(), - selectCostInfo = makeSelectCostInfoForUri(), - selectMetadata = makeSelectMetadataForUri(); - - const select = (state, props) => ({ - claim: selectClaim(state, props), - contentType: selectContentType(state, props), - costInfo: selectCostInfo(state, props), - metadata: selectMetadata(state, props), - obscureNsfw: !selectShowNsfw(state), - fileInfo: selectFileInfo(state, props), - rewardedContentClaimIds: selectRewardContentClaimIds(state, props), - }); - - return select; -}; +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + contentType: makeSelectContentTypeForUri(props.uri)(state), + costInfo: makeSelectCostInfoForUri(props.uri)(state), + metadata: makeSelectMetadataForUri(props.uri)(state), + obscureNsfw: !selectShowNsfw(state), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + rewardedContentClaimIds: selectRewardContentClaimIds(state, props), +}); const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), @@ -40,4 +30,4 @@ const perform = dispatch => ({ fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)), }); -export default connect(makeSelect, perform)(FilePage); +export default connect(select, perform)(FilePage); diff --git a/ui/js/page/show/index.js b/ui/js/page/show/index.js index 6306e5e33..94b380381 100644 --- a/ui/js/page/show/index.js +++ b/ui/js/page/show/index.js @@ -2,23 +2,16 @@ import React from "react"; import { connect } from "react-redux"; import { doResolveUri } from "actions/content"; import { makeSelectClaimForUri } from "selectors/claims"; -import { makeSelectIsResolvingForUri } from "selectors/content"; +import { makeSelectIsUriResolving } from "selectors/content"; import ShowPage from "./view"; -const makeSelect = () => { - const selectClaim = makeSelectClaimForUri(), - selectIsResolving = makeSelectIsResolvingForUri(); - - const select = (state, props) => ({ - claim: selectClaim(state, props.params), - isResolvingUri: selectIsResolving(state, props.params), - }); - - return select; -}; +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + isResolvingUri: makeSelectIsUriResolving(props.uri)(state), +}); const perform = dispatch => ({ resolveUri: uri => dispatch(doResolveUri(uri)), }); -export default connect(makeSelect, perform)(ShowPage); +export default connect(select, perform)(ShowPage); diff --git a/ui/js/page/show/view.jsx b/ui/js/page/show/view.jsx index aae0aabfe..679626d28 100644 --- a/ui/js/page/show/view.jsx +++ b/ui/js/page/show/view.jsx @@ -6,15 +6,13 @@ import FilePage from "page/file"; class ShowPage extends React.PureComponent { componentWillMount() { - const { isResolvingUri, resolveUri, params } = this.props; - const { uri } = params; + const { isResolvingUri, resolveUri, uri } = this.props; if (!isResolvingUri) resolveUri(uri); } componentWillReceiveProps(nextProps) { - const { isResolvingUri, resolveUri, claim, params } = nextProps; - const { uri } = params; + const { isResolvingUri, resolveUri, claim, uri } = nextProps; if (!isResolvingUri && claim === undefined && uri) { resolveUri(uri); @@ -22,8 +20,7 @@ class ShowPage extends React.PureComponent { } render() { - const { claim, params, isResolvingUri } = this.props; - const { uri } = params; + const { claim, isResolvingUri, uri } = this.props; let innerContent = ""; diff --git a/ui/js/reducers/app.js b/ui/js/reducers/app.js index 857a5a708..4ca5f888b 100644 --- a/ui/js/reducers/app.js +++ b/ui/js/reducers/app.js @@ -8,6 +8,8 @@ const win = remote.BrowserWindow.getFocusedWindow(); const reducers = {}; const defaultState = { isLoaded: false, + modal: null, + modalProps: {}, platform: process.platform, upgradeSkipped: sessionStorage.getItem("upgradeSkipped"), daemonVersionMatched: null, @@ -76,14 +78,14 @@ reducers[types.UPDATE_VERSION] = function(state, action) { reducers[types.OPEN_MODAL] = function(state, action) { return Object.assign({}, state, { modal: action.data.modal, - modalExtraContent: action.data.extraContent, + modalProps: action.data.modalProps || {}, }); }; reducers[types.CLOSE_MODAL] = function(state, action) { return Object.assign({}, state, { modal: undefined, - modalExtraContent: undefined, + modalProps: {}, }); }; diff --git a/ui/js/selectors/app.js b/ui/js/selectors/app.js index 3e8e68223..c721916c0 100644 --- a/ui/js/selectors/app.js +++ b/ui/js/selectors/app.js @@ -71,9 +71,9 @@ export const selectUpgradeDownloadItem = createSelector( state => state.downloadItem ); -export const selectModalExtraContent = createSelector( +export const selectModalProps = createSelector( _selectState, - state => state.modalExtraContent + state => state.modalProps ); export const selectDaemonReady = createSelector( diff --git a/ui/js/selectors/availability.js b/ui/js/selectors/availability.js index 1200dd904..99bf63ad9 100644 --- a/ui/js/selectors/availability.js +++ b/ui/js/selectors/availability.js @@ -7,14 +7,10 @@ export const selectAvailabilityByUri = createSelector( state => state.byUri || {} ); -const selectAvailabilityForUri = (state, props) => { - return selectAvailabilityByUri(state)[props.uri]; -}; - -export const makeSelectIsAvailableForUri = () => { +export const makeSelectIsAvailableForUri = uri => { return createSelector( - selectAvailabilityForUri, - availability => (availability === undefined ? undefined : availability > 0) + selectAvailabilityByUri, + byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0) ); }; @@ -23,10 +19,9 @@ export const selectFetchingAvailability = createSelector( state => state.fetching || {} ); -const selectFetchingAvailabilityForUri = (state, props) => { - return selectFetchingAvailability(state)[props.uri]; -}; - -export const makeSelectFetchingAvailabilityForUri = () => { - return createSelector(selectFetchingAvailabilityForUri, fetching => fetching); +export const makeSelectFetchingAvailabilityForUri = uri => { + return createSelector( + selectFetchingAvailability, + byUri => byUri && byUri[uri] + ); }; diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index f4b6344b5..ce8ebc8cd 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -40,24 +40,24 @@ export const selectAllClaimsByChannel = createSelector( state => state.claimsByChannel || {} ); -const selectClaimForUri = (state, props) => { - const uri = lbryuri.normalize(props.uri); - return selectClaimsByUri(state)[uri]; +export const makeSelectClaimForUri = uri => { + return createSelector( + selectClaimsByUri, + claims => claims && claims[lbryuri.normalize(uri)] + ); }; -export const makeSelectClaimForUri = () => { - return createSelector(selectClaimForUri, claim => claim); -}; - -const selectClaimForUriIsMine = (state, props) => { - const uri = lbryuri.normalize(props.uri); - const claim = selectClaimsByUri(state)[uri]; - const myClaims = selectMyClaimsRaw(state); - return myClaims && myClaims.has(claim.claim_id); -}; - -export const makeSelectClaimForUriIsMine = () => { - return createSelector(selectClaimForUriIsMine, isMine => isMine); +export const makeSelectClaimIsMine = rawUri => { + const uri = lbryuri.normalize(rawUri); + return createSelector( + selectClaimsByUri, + selectMyClaimsRaw, + (claims, myClaims) => + claims && + claims[uri] && + claims[uri].claim_id && + myClaims.has(claims[uri].claim_id) + ); }; export const selectAllFetchingChannelClaims = createSelector( @@ -65,86 +65,46 @@ export const selectAllFetchingChannelClaims = createSelector( state => state.fetchingChannelClaims || {} ); -const selectFetchingChannelClaims = (state, props) => { - const allFetchingChannelClaims = selectAllFetchingChannelClaims(state); - - return allFetchingChannelClaims[props.uri]; -}; - -export const makeSelectFetchingChannelClaims = (state, props) => { - return createSelector(selectFetchingChannelClaims, fetching => fetching); -}; - -export const selectClaimsInChannelForUri = (state, props) => { - const byId = selectClaimsById(state); - const byChannel = selectAllClaimsByChannel(state)[props.uri] || {}; - const claimIds = byChannel["all"]; - - if (!claimIds) return claimIds; - - const claims = []; - - claimIds.forEach(claimId => claims.push(byId[claimId])); - - return claims; -}; - -export const makeSelectClaimsInChannelForUri = () => { - return createSelector(selectClaimsInChannelForUri, claims => claims); -}; - -export const selectClaimsInChannelForCurrentPage = (state, props) => { - const byId = selectClaimsById(state); - const byChannel = selectAllClaimsByChannel(state)[props.uri] || {}; - const params = selectCurrentParams(state); - const page = params && params.page ? params.page : 1; - const claimIds = byChannel[page]; - - if (!claimIds) return claimIds; - - const claims = []; - - claimIds.forEach(claimId => claims.push(byId[claimId])); - - return claims; -}; - -export const makeSelectClaimsInChannelForCurrentPage = () => { - return createSelector(selectClaimsInChannelForCurrentPage, claims => claims); -}; - -const selectMetadataForUri = (state, props) => { - const claim = selectClaimForUri(state, props); - const metadata = - claim && claim.value && claim.value.stream && claim.value.stream.metadata; - - const value = metadata ? metadata : claim === undefined ? undefined : null; - return value; -}; - -export const makeSelectMetadataForUri = () => { - return createSelector(selectMetadataForUri, metadata => metadata); -}; - -const selectSourceForUri = (state, props) => { - const claim = selectClaimForUri(state, props); - const source = - claim && claim.value && claim.value.stream && claim.value.stream.source; - - return source ? source : claim === undefined ? undefined : null; -}; - -export const makeSelectSourceForUri = () => { - return createSelector(selectSourceForUri, source => source); -}; - -export const makeSelectContentTypeForUri = () => { - return createSelector( - selectSourceForUri, - source => (source ? source.contentType : source) +export const makeSelectFetchingChannelClaims = uri => { + createSelector( + selectAllFetchingChannelClaims, + fetching => fetching && fetching[uri] ); }; +export const makeSelectClaimsInChannelForCurrentPage = (uri, page = 1) => { + return createSelector( + selectClaimsById, + selectAllClaimsByChannel, + (byId, allClaims) => { + const byChannel = allClaims[uri] || {}; + const claimIds = byChannel[page]; + + if (!claimIds) return claimIds; + + return claimIds.map(claimId => byId[claimId]); + } + ); +}; + +export const makeSelectMetadataForUri = uri => { + return createSelector(makeSelectClaimForUri(uri), claim => { + const metadata = + claim && claim.value && claim.value.stream && claim.value.stream.metadata; + + const value = metadata ? metadata : claim === undefined ? undefined : null; + return value; + }); +}; + +export const makeSelectContentTypeForUri = uri => { + return createSelector(makeSelectClaimForUri(uri), claim => { + const source = + claim && claim.value && claim.value.stream && claim.value.stream.source; + return source ? source.contentType : undefined; + }); +}; + export const selectIsFetchingClaimListMine = createSelector( _selectState, state => !!state.isFetchingClaimListMine diff --git a/ui/js/selectors/content.js b/ui/js/selectors/content.js index 3bf6926a6..e8c0d42cc 100644 --- a/ui/js/selectors/content.js +++ b/ui/js/selectors/content.js @@ -17,12 +17,11 @@ export const selectResolvingUris = createSelector( state => state.resolvingUris || [] ); -const selectResolvingUri = (state, props) => { - return selectResolvingUris(state).indexOf(props.uri) != -1; -}; - -export const makeSelectIsResolvingForUri = () => { - return createSelector(selectResolvingUri, resolving => resolving); +export const makeSelectIsUriResolving = uri => { + return createSelector( + selectResolvingUris, + resolvingUris => resolvingUris && resolvingUris.indexOf(uri) != -1 + ); }; export const selectChannelPages = createSelector( @@ -30,12 +29,8 @@ export const selectChannelPages = createSelector( state => state.channelPages || {} ); -const selectTotalPagesForChannel = (state, props) => { - return selectChannelPages(state)[props.uri]; -}; - -export const makeSelectTotalPagesForChannel = () => { - return createSelector(selectTotalPagesForChannel, totalPages => totalPages); +export const makeSelectTotalPagesForChannel = uri => { + return createSelector(selectChannelPages, byUri => byUri && byUri[uri]); }; export const selectRewardContentClaimIds = createSelector( diff --git a/ui/js/selectors/cost_info.js b/ui/js/selectors/cost_info.js index b40d62d5e..d7c17cefa 100644 --- a/ui/js/selectors/cost_info.js +++ b/ui/js/selectors/cost_info.js @@ -8,12 +8,11 @@ export const selectAllCostInfoByUri = createSelector( state => state.byUri || {} ); -export const selectCostInfoForUri = (state, props) => { - return selectAllCostInfoByUri(state)[props.uri]; -}; - -export const makeSelectCostInfoForUri = () => { - return createSelector(selectCostInfoForUri, costInfo => costInfo); +export const makeSelectCostInfoForUri = uri => { + return createSelector( + selectAllCostInfoByUri, + costInfos => costInfos && costInfos[uri] + ); }; export const selectCostForCurrentPageUri = createSelector( @@ -28,10 +27,9 @@ export const selectFetchingCostInfo = createSelector( state => state.fetching || {} ); -const selectFetchingCostInfoForUri = (state, props) => { - return selectFetchingCostInfo(state)[props.uri]; -}; - -export const makeSelectFetchingCostInfoForUri = () => { - return createSelector(selectFetchingCostInfoForUri, fetching => !!fetching); +export const makeSelectFetchingCostInfoForUri = uri => { + return createSelector( + selectFetchingCostInfo, + fetchingByUri => fetchingByUri && fetchingByUri[uri] + ); }; diff --git a/ui/js/selectors/file_info.js b/ui/js/selectors/file_info.js index 1b3dc7982..431454dfc 100644 --- a/ui/js/selectors/file_info.js +++ b/ui/js/selectors/file_info.js @@ -26,17 +26,17 @@ export const selectIsFetchingFileListDownloadedOrPublished = createSelector( isFetchingFileList || isFetchingClaimListMine ); -export const selectFileInfoForUri = (state, props) => { - const claims = selectClaimsByUri(state), - claim = claims[props.uri], - byOutpoint = selectFileInfosByOutpoint(state), - outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined; +export const makeSelectFileInfoForUri = uri => { + return createSelector( + selectClaimsByUri, + selectFileInfosByOutpoint, + (claims, byOutpoint) => { + const claim = claims[uri], + outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined; - return outpoint ? byOutpoint[outpoint] : undefined; -}; - -export const makeSelectFileInfoForUri = () => { - return createSelector(selectFileInfoForUri, fileInfo => fileInfo); + return outpoint ? byOutpoint[outpoint] : undefined; + } + ); }; export const selectDownloadingByOutpoint = createSelector( @@ -44,19 +44,14 @@ export const selectDownloadingByOutpoint = createSelector( state => state.downloadingByOutpoint || {} ); -const selectDownloadingForUri = (state, props) => { - const byOutpoint = selectDownloadingByOutpoint(state); - const fileInfo = selectFileInfoForUri(state, props); - - if (!fileInfo) return false; - - return byOutpoint[fileInfo.outpoint]; -}; - -export const makeSelectDownloadingForUri = () => { +export const makeSelectDownloadingForUri = uri => { return createSelector( - selectDownloadingForUri, - downloadingForUri => !!downloadingForUri + selectDownloadingByOutpoint, + makeSelectFileInfoForUri(uri), + (byOutpoint, fileInfo) => { + if (!fileInfo) return false; + return byOutpoint[fileInfo.outpoint]; + } ); }; @@ -65,13 +60,8 @@ export const selectUrisLoading = createSelector( state => state.urisLoading || {} ); -const selectLoadingForUri = (state, props) => { - const byUri = selectUrisLoading(state); - return byUri[props.uri]; -}; - -export const makeSelectLoadingForUri = () => { - return createSelector(selectLoadingForUri, loading => !!loading); +export const makeSelectLoadingForUri = uri => { + return createSelector(selectUrisLoading, byUri => byUri && byUri[uri]); }; export const selectFileInfosPendingPublish = createSelector( From be44455b7ab24f89c98f1ead74acdb279e1a3a9e Mon Sep 17 00:00:00 2001 From: MSFTserver Date: Fri, 8 Sep 2017 23:46:26 -0700 Subject: [PATCH 090/132] added color to echo's to stand out more --- build/build.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/build.sh b/build/build.sh index 92c2c5e8f..f73230469 100755 --- a/build/build.sh +++ b/build/build.sh @@ -14,7 +14,7 @@ if [ "$(uname)" == "Darwin" ]; then elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then LINUX=true else - echo "Platform detection failed" + echo -e "\033[1;31mPlatform detection failed\x1b[m" exit 1 fi @@ -90,7 +90,7 @@ if [[ ! -f $DAEMON_VER_PATH || ! -f $ROOT/app/dist/lbrynet-daemon || "$(< "$DAEM rm "$BUILD_DIR/daemon.zip" echo "$DAEMON_VER" > "$DAEMON_VER_PATH" else - echo "Already have daemon version $DAEMON_VER, skipping download" + echo -e "\033[4;31mAlready have daemon version $DAEMON_VER, skipping download\x1b[m" fi @@ -133,7 +133,7 @@ if [ "$FULL_BUILD" == "true" ]; then deactivate - echo 'Build and packaging complete.' + echo -e '\033[0;32mBuild and packaging complete.\x1b[m' else - echo 'Build complete. Run `./node_modules/.bin/electron app` to launch the app' + echo -e 'Build complete. Run \033[1;31m./node_modules/.bin/electron app\x1b[m to launch the app' fi From ebd0949ce2792fd7bd374415acae98f6fa54b99d Mon Sep 17 00:00:00 2001 From: MSFTserver Date: Tue, 12 Sep 2017 22:19:50 -0700 Subject: [PATCH 091/132] better (build.sh) better set -x wrappers for non-debugging everything and added a couple extra echos --- build/build.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/build/build.sh b/build/build.sh index f73230469..343435468 100755 --- a/build/build.sh +++ b/build/build.sh @@ -1,7 +1,6 @@ #!/bin/bash set -euo pipefail -set -x ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" cd "$ROOT" @@ -10,9 +9,13 @@ BUILD_DIR="$ROOT/build" LINUX=false OSX=false if [ "$(uname)" == "Darwin" ]; then +set -x OSX=true +set +x elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then +set -x LINUX=true +set +x else echo -e "\033[1;31mPlatform detection failed\x1b[m" exit 1 @@ -23,14 +26,16 @@ if $OSX; then else ICON="$BUILD_DIR/icons/lbry48.png" fi - +set -x FULL_BUILD="${FULL_BUILD:-false}" +set +x if [ -n "${TEAMCITY_VERSION:-}" -o -n "${APPVEYOR:-}" ]; then FULL_BUILD="true" fi if [ "$FULL_BUILD" == "true" ]; then # install dependencies + echo -e "\033[0;32mInstalling Dependencies\x1b[m" $BUILD_DIR/prebuild.sh VENV="$BUILD_DIR/venv" @@ -57,7 +62,7 @@ yarn install ############ # UI # ############ - +echo -e "\033[0;32mCompiling UI\x1b[m" ( cd "$ROOT/ui" yarn install @@ -73,7 +78,7 @@ yarn install #################### # daemon and cli # #################### - +echo -e "\033[0;32mGrabbing Daemon and CLI\x1b[m" if $OSX; then OSNAME="macos" else @@ -99,7 +104,7 @@ fi ################### # Build the app # ################### - +echo -e '\033[0;32mBuilding Lbry-app\x1b[m' ( cd "$ROOT/app" yarn install From abcd8a2ba86bf7fae67b4bc9aba57e24a15365f1 Mon Sep 17 00:00:00 2001 From: Baltazar Gomez Date: Wed, 13 Sep 2017 20:40:44 -0600 Subject: [PATCH 092/132] add missign icons - fix #543 --- ui/scss/_icons.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/scss/_icons.scss b/ui/scss/_icons.scss index cb487975b..508e927c4 100644 --- a/ui/scss/_icons.scss +++ b/ui/scss/_icons.scss @@ -1658,3 +1658,9 @@ .icon-medium:before { content: "\f23a"; } +.icon-address-book:before { + content: "\f2b9"; +} +.icon-envelope-open:before { + content: "\f2b6"; +} From d8e4f0c49ff42a0c6a0bca6febcb750729279082 Mon Sep 17 00:00:00 2001 From: Mat Waller Date: Fri, 15 Sep 2017 00:34:55 +0100 Subject: [PATCH 093/132] Adding Windows Build Instructions Adding guide on how to build for windows. --- README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5e94a8bf5..623ee135a 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,52 @@ to create distributable packages, which is run by calling: `node_modules/.bin/build -p never` -### Development on Windows +## Development on Windows -This project has currently only been worked on in Linux and macOS. If you are on Windows, you can -checkout out the build steps in [appveyor.yml](https://github.com/lbryio/lbry-app/blob/master/.appveyor.yml) and probably figure out something from there. +### Windows Dependency + +1. Download and install `npm` and `node` from nodejs.org +2. Download and install `python 2.7` from python.org +3. Download and Install `Microsoft Visual C++ Compiler for Python 2.7` from Microsoft +4. Download and install `.NET Framework 2.0 Software Development Kit (SDK) (x64)` from Microsoft + +### One-time Setup +1. Open command prompt in the root of the project and run the following; +``` +python -m pip install -r build\requirements.txt +python build\set_version.py +npm install -g yarn +yarn install +``` +2. Change directory to `app` and run the following; +``` +yarn install +node_modules\.bin\electron-rebuild +node_modules\.bin\electron-rebuild +cd .. +``` +3. Change directory to `ui` and run the following +``` +yarn install +npm rebuild node-sass +node node_modules\node-sass\bin\node-sass --output dist\css --sourcemap=none scss\ +node_modules\.bin\webpack --config webpack.dev.config.js +xcopy dist ..\app\dist +cd .. +``` +4. Download the lbry daemon and cli binaries and place them in `app\dist\` + +### Building lbry-app +1. run `node_modules\.bin\build -p never` from the root of the project. + +### Running the electron app +1. Run `./node_modules/.bin/electron app` + +### Ongoing Development +1. `cd ui` +2. `watch.bat` + +This will set up a monitor that will automatically compile any changes to JS or CSS folders inside of the `ui` folder. This allows you to make changes and see them immediately by reloading the app. ## Internationalization From acdeafe6dbbd2554537e208c895a693a82154a41 Mon Sep 17 00:00:00 2001 From: Mat Waller Date: Fri, 15 Sep 2017 03:27:20 +0100 Subject: [PATCH 094/132] Watch Batch Batch file to provide node-sass/webpack watching for windows users. --- ui/watch.bat | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 ui/watch.bat diff --git a/ui/watch.bat b/ui/watch.bat new file mode 100644 index 000000000..0c064759a --- /dev/null +++ b/ui/watch.bat @@ -0,0 +1,11 @@ +@echo off + +set found= +for %%F in ( + "%~dp0\node_modules\node-sass\bin\node-sass" + "%~dp0\node_modules\.bin\webpack" +) do if exist %%F (set found=1) +if not defined found EXIT + +node %~dp0\node_modules\node-sass\bin\node-sass --output %~dp0\..\app\dist\css --sourcemap=none %~dp0\scss +%~dp0\node_modules\.bin\webpack --config %~dp0\webpack.dev.config.js --progress --colors --watch \ No newline at end of file From e119533973c4d0d77c38b742fde5ed20392f2d73 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Fri, 15 Sep 2017 09:56:32 -0400 Subject: [PATCH 095/132] more progress but probably more breakage --- ui/js/component/fileActions/index.js | 2 - ui/js/component/fileActions/view.jsx | 55 ++++++------------- ui/js/component/fileDownloadLink/view.jsx | 4 +- ui/js/component/fileList/view.jsx | 1 + ui/js/component/fileTile/view.jsx | 17 +++--- .../component/video/internal/play-button.jsx | 19 ++++--- ui/js/page/file/view.jsx | 12 ++-- ui/scss/all.scss | 2 +- ui/scss/component/_card.scss | 4 ++ ..._file-actions.scss => _file-download.scss} | 23 ++++---- 10 files changed, 63 insertions(+), 76 deletions(-) rename ui/scss/component/{_file-actions.scss => _file-download.scss} (70%) diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index f8a5d8424..fea552312 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -14,14 +14,12 @@ import FileActions from "./view"; const select = (state, props) => ({ fileInfo: makeSelectFileInfoForUri(props.uri)(state), /*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/ - platform: selectPlatform(state), costInfo: makeSelectCostInfoForUri(props.uri)(state), claimIsMine: makeSelectClaimIsMine(props.uri)(state), }); const perform = dispatch => ({ checkAvailability: uri => dispatch(doFetchAvailability(uri)), - openInFolder: fileInfo => dispatch(doOpenFileInFolder(fileInfo)), openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)), startDownload: uri => dispatch(doPurchaseUri(uri)), diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index d530f4ea7..eed07ab44 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,7 +1,6 @@ import React from "react"; import Link from "component/link"; import FileDownloadLink from "component/fileDownloadLink"; -import { DropDownMenu, DropDownMenuItem } from "component/menu"; import * as modals from "constants/modal_types"; class FileActions extends React.PureComponent { @@ -10,58 +9,38 @@ class FileActions extends React.PureComponent { } render() { - const { - fileInfo, - platform, - uri, - openInFolder, - openModal, - claimIsMine, - editClaim, - } = this.props; + const { fileInfo, uri, openModal, claimIsMine, editClaim } = this.props; const name = fileInfo ? fileInfo.name : null; const channel = fileInfo ? fileInfo.channel_name : null; const metadata = fileInfo ? fileInfo.metadata : null, - openInFolderMessage = platform.startsWith("Mac") - ? __("Open in Finder") - : __("Open in Folder"), showMenu = fileInfo && Object.keys(fileInfo).length > 0, title = metadata ? metadata.title : uri; return ( -
+
+ {claimIsMine && + editClaim({ name, channel })} + />} - {showMenu - ?
- - openInFolder(fileInfo)} - label={openInFolderMessage} - /> - {claimIsMine && - editClaim({ name, channel })} - label={__("Edit claim")} - />} - openModal(modals.CONFIRM_FILE_REMOVE, { uri })} - label={__("Remove...")} - /> - -
- : ""} - + openModal(modals.CONFIRM_FILE_REMOVE, { uri })} + />
); } diff --git a/ui/js/component/fileDownloadLink/view.jsx b/ui/js/component/fileDownloadLink/view.jsx index fd1818ed7..82bae5b8a 100644 --- a/ui/js/component/fileDownloadLink/view.jsx +++ b/ui/js/component/fileDownloadLink/view.jsx @@ -61,9 +61,9 @@ class FileDownloadLink extends React.PureComponent { ); return ( -
+
{labelWithIcon} diff --git a/ui/js/component/fileList/view.jsx b/ui/js/component/fileList/view.jsx index 57d4d991f..8fad10cdc 100644 --- a/ui/js/component/fileList/view.jsx +++ b/ui/js/component/fileList/view.jsx @@ -88,6 +88,7 @@ class FileList extends React.PureComponent { key={fileInfo.outpoint || fileInfo.claim_id} uri={uri} hidePrice={true} + showActions={true} showEmpty={this.props.fileTileShowEmpty} /> ); diff --git a/ui/js/component/fileTile/view.jsx b/ui/js/component/fileTile/view.jsx index c57172408..1abd44952 100644 --- a/ui/js/component/fileTile/view.jsx +++ b/ui/js/component/fileTile/view.jsx @@ -1,6 +1,7 @@ import React from "react"; import lbryuri from "lbryuri.js"; import CardMedia from "component/cardMedia"; +import FileActions from "component/fileActions"; import Link from "component/link"; import { TruncatedText } from "component/common.js"; import FilePrice from "component/filePrice"; @@ -53,6 +54,7 @@ class FileTile extends React.PureComponent { render() { const { claim, + showActions, metadata, isResolvingUri, showEmpty, @@ -104,7 +106,7 @@ class FileTile extends React.PureComponent { onMouseEnter={this.handleMouseOver.bind(this)} onMouseLeave={this.handleMouseOut.bind(this)} > - +
@@ -116,14 +118,15 @@ class FileTile extends React.PureComponent { {title}
-
- - {description} - -
+ {description && +
+ + {description} + +
}
- +
{this.state.showNsfwHelp && }
); diff --git a/ui/js/component/video/internal/play-button.jsx b/ui/js/component/video/internal/play-button.jsx index 2df2b2ea4..23f9259aa 100644 --- a/ui/js/component/video/internal/play-button.jsx +++ b/ui/js/component/video/internal/play-button.jsx @@ -47,15 +47,16 @@ class VideoPlayButton extends React.PureComponent { ? "icon-play" : "icon-folder-o"; - return; - ; + return ( + + ); } } diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index 0d2ed0bc3..3e1a2e2f9 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -23,7 +23,7 @@ const FormatItem = props => { const mediaType = lbry.getMediaType(contentType); return ( - +
@@ -156,12 +156,10 @@ class FilePage extends React.PureComponent { : uriIndicator} -
- -
+ {!showTipBox &&
diff --git a/ui/scss/all.scss b/ui/scss/all.scss index 61f636b77..69656fa41 100644 --- a/ui/scss/all.scss +++ b/ui/scss/all.scss @@ -6,7 +6,7 @@ @import "component/_table"; @import "component/_button.scss"; @import "component/_card.scss"; -@import "component/_file-actions.scss"; +@import "component/_file-download.scss"; @import "component/_file-selector.scss"; @import "component/_file-tile.scss"; @import "component/_form-field.scss"; diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index d81f408ac..156a5406f 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -51,6 +51,9 @@ margin-top: $spacing-vertical; margin-bottom: var(--card-margin); } +.card__action--right { + float: right; +} .card__content { margin-top: var(--card-margin); margin-bottom: var(--card-margin); @@ -84,6 +87,7 @@ $font-size-subtext-multiple: 0.82; .card__link { display: block; + cursor: pointer; } .card--link { transition: transform 120ms ease-in-out; diff --git a/ui/scss/component/_file-actions.scss b/ui/scss/component/_file-download.scss similarity index 70% rename from ui/scss/component/_file-actions.scss rename to ui/scss/component/_file-download.scss index 0350dad90..13ce6e1f3 100644 --- a/ui/scss/component/_file-actions.scss +++ b/ui/scss/component/_file-download.scss @@ -1,22 +1,15 @@ - -.file-actions -{ - line-height: var(--button-height); - min-height: var(--button-height); -} - -.file-actions__download-status-bar, .file-actions__download-status-bar-overlay { +.file-download, .file-download__overlay { .button__content { margin: 0 var(--text-link-padding); } } -.file-actions__download-status-bar +.file-download { position: relative; color: var(--color-download); } -.file-actions__download-status-bar-overlay +.file-download__overlay { background: var(--color-download); color: white; @@ -27,3 +20,13 @@ top: 0px; left: 0px; } + +/* + +.file-actions +{ + line-height: var(--button-height); + min-height: var(--button-height); +} + + */ \ No newline at end of file From f7367f5c6a6ce13c325612b2df823b0df6275168 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 16 Sep 2017 19:50:44 -0600 Subject: [PATCH 096/132] tidy up edit / publish logic edit claim by id fix #553 display title and icon based on action: edit / publish tidy up remove unused code --- ui/js/component/fileActions/index.js | 2 +- ui/js/component/fileActions/view.jsx | 17 +++-- ui/js/component/publishForm/view.jsx | 68 ++++++++++---------- ui/js/selectors/navigation.js | 2 +- ui/js/selectors/search.js | 92 +++++++++++++++------------- 5 files changed, 98 insertions(+), 83 deletions(-) diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index fea552312..b94e2bbcb 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -24,7 +24,7 @@ const perform = dispatch => ({ openModal: (modal, props) => dispatch(doOpenModal(modal, props)), startDownload: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), - editClaim: fileInfo => dispatch(doNavigate("/publish", fileInfo)), + editClaim: claimId => dispatch(doNavigate("/publish", { id: claimId })), }); export default connect(select, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index eed07ab44..361338b89 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -9,12 +9,17 @@ class FileActions extends React.PureComponent { } render() { - const { fileInfo, uri, openModal, claimIsMine, editClaim } = this.props; + const { + fileInfo, + uri, + openModal, + claimIsMine, + editClaim, + checkAvailability, + } = this.props; - const name = fileInfo ? fileInfo.name : null; - const channel = fileInfo ? fileInfo.channel_name : null; - - const metadata = fileInfo ? fileInfo.metadata : null, + const claimId = fileInfo ? fileInfo.claim_id : null, + metadata = fileInfo ? fileInfo.metadata : null, showMenu = fileInfo && Object.keys(fileInfo).length > 0, title = metadata ? metadata.title : uri; @@ -25,7 +30,7 @@ class FileActions extends React.PureComponent { button="text" icon="icon-edit" label={__("Edit")} - onClick={() => editClaim({ name, channel })} + onClick={() => editClaim(claimId)} />} claim.name === name + claim => claim.claim_id === id ); } @@ -272,9 +273,10 @@ class PublishForm extends React.PureComponent { }); } - handlePrefillClicked() { - const claimInfo = this.myClaimInfo(); - const { source } = claimInfo.value.stream; + handlePrefillClaim(claimInfo) { + const { claim_id, name, channel_name, amount } = claimInfo; + const { source, metadata } = claimInfo.value.stream; + const { license, licenseUrl, @@ -283,17 +285,21 @@ class PublishForm extends React.PureComponent { description, language, nsfw, - } = claimInfo.value.stream.metadata; + } = metadata; let newState = { - mode: "edit", + id: claim_id, + channel: channel_name || "anonymous", + bid: amount, meta_title: title, meta_thumbnail: thumbnail, meta_description: description, meta_language: language, meta_nsfw: nsfw, + mode: "edit", prefillDone: true, - bid: claimInfo.amount, + rawName: name, + name, source, }; @@ -423,16 +429,11 @@ class PublishForm extends React.PureComponent { } componentWillMount() { - let { name, channel } = this.props.params; - - channel = channel || this.state.channel; - this.props.fetchClaimListMine(); this._updateChannelList(); - if (name) { - this.setState({ name, rawName: name, channel }); - } + const { id } = this.props.params; + this.setState({ id }); } componentDidMount() { @@ -461,37 +462,38 @@ class PublishForm extends React.PureComponent { } getNameBidHelpText() { - if (this.state.prefillDone) { + const { prefillDone, name, uri } = this.state; + const { resolvingUris } = this.props; + const claim = this.claim(); + + if (prefillDone) { return __("Existing claim data was prefilled"); } - if ( - this.state.uri && - this.props.resolvingUris.indexOf(this.state.uri) !== -1 && - this.claim() === undefined - ) { + if (uri && resolvingUris.indexOf(uri) !== -1 && claim === undefined) { return __("Checking..."); - } else if (!this.state.name) { + } else if (!name) { return __("Select a URL for this publish."); - } else if (!this.claim()) { + } else if (!claim) { return __("This URL is unused."); - } else if (this.myClaimExists() && !this.state.prefillDone) { + } else if (this.myClaimExists() && !prefillDone) { return ( {__("You already have a claim with this name.")}{" "} this.handlePrefillClicked()} + onClick={() => this.handleEditClaim()} /> ); - } else if (this.claim()) { - if (this.topClaimValue() === 1) { + } else if (claim) { + const topClaimValue = this.topClaimValue(); + if (topClaimValue === 1) { return ( {__( 'A deposit of at least one credit is required to win "%s". However, you can still get a permanent URL for any amount.', - this.state.name + name )} ); @@ -500,8 +502,8 @@ class PublishForm extends React.PureComponent { {__( 'A deposit of at least "%s" credits is required to win "%s". However, you can still get a permanent URL for any amount.', - this.topClaimValue(), - this.state.name + topClaimValue, + name )} ); diff --git a/ui/js/selectors/navigation.js b/ui/js/selectors/navigation.js index 08ae51774..f11f35eb9 100644 --- a/ui/js/selectors/navigation.js +++ b/ui/js/selectors/navigation.js @@ -87,7 +87,7 @@ export const selectPageTitle = createSelector( case "start": return __("Start"); case "publish": - return __("Publish"); + return params.id ? __("Edit") : __("Publish"); case "help": return __("Help"); case "developer": diff --git a/ui/js/selectors/search.js b/ui/js/selectors/search.js index e3c6fbb4a..4e02c2542 100644 --- a/ui/js/selectors/search.js +++ b/ui/js/selectors/search.js @@ -1,5 +1,9 @@ import { createSelector } from "reselect"; -import { selectPageTitle, selectCurrentPage } from "selectors/navigation"; +import { + selectPageTitle, + selectCurrentPage, + selectCurrentParams, +} from "selectors/navigation"; export const _selectState = state => state.search || {}; @@ -36,45 +40,49 @@ export const selectWunderBarAddress = createSelector( (page, title, query) => (page != "search" ? title : query ? query : title) ); -export const selectWunderBarIcon = createSelector(selectCurrentPage, page => { - switch (page) { - case "auth": - return "icon-user"; - case "search": - return "icon-search"; - case "settings": - return "icon-gear"; - case "help": - return "icon-question"; - case "report": - return "icon-file"; - case "downloaded": - return "icon-folder"; - case "published": - return "icon-folder"; - case "history": - return "icon-history"; - case "send": - return "icon-send"; - case "rewards": - return "icon-rocket"; - case "invite": - return "icon-envelope-open"; - case "address": - case "receive": - return "icon-address-book"; - case "wallet": - case "backup": - return "icon-bank"; - case "show": - return "icon-file"; - case "publish": - return "icon-upload"; - case "developer": - return "icon-code"; - case "discover": - return "icon-home"; - default: - return "icon-file"; +export const selectWunderBarIcon = createSelector( + selectCurrentPage, + selectCurrentParams, + (page, params) => { + switch (page) { + case "auth": + return "icon-user"; + case "search": + return "icon-search"; + case "settings": + return "icon-gear"; + case "help": + return "icon-question"; + case "report": + return "icon-file"; + case "downloaded": + return "icon-folder"; + case "published": + return "icon-folder"; + case "history": + return "icon-history"; + case "send": + return "icon-send"; + case "rewards": + return "icon-rocket"; + case "invite": + return "icon-envelope-open"; + case "address": + case "receive": + return "icon-address-book"; + case "wallet": + case "backup": + return "icon-bank"; + case "show": + return "icon-file"; + case "publish": + return params.id ? __("icon-pencil") : __("icon-upload"); + case "developer": + return "icon-code"; + case "discover": + return "icon-home"; + default: + return "icon-file"; + } } -}); +); From c3a9eee10a34bac35dcdc47832fd5a4eafebaa29 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 12:43:18 -0400 Subject: [PATCH 097/132] Fix multi-line URLs on cards --- CHANGELOG.md | 2 +- ui/scss/component/_card.scss | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5fc9edc2..156b5190e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Fixed - * + * URLs on cards no longer wrap and show an ellipsis if longer than one line * ### Deprecated diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 156a5406f..e5dff4e73 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -35,6 +35,11 @@ margin-top: var(--card-margin); margin-bottom: var(--card-margin); } +.card__title-primary .meta { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} .card__title-identity { margin-top: $spacing-vertical * 1/3; margin-bottom: $spacing-vertical * 1/3; From ae81843c051c668147ea35b881bc4284829c3446 Mon Sep 17 00:00:00 2001 From: hackrush Date: Sat, 16 Sep 2017 16:32:54 +0530 Subject: [PATCH 098/132] Additional tipping fixes/changes - [x] Display empty message on empty filtered Tx list - [ ] Tipping form has to stay open until success is detected(or closed by user) - [ ] Storing the older transaction list, and refreshing the new one in the background. Tip Box shown until valid Txn or manually cancelled Cleanup of show tip box logic --- ui/js/actions/claims.js | 13 ++++++-- ui/js/component/fileActions/index.js | 2 ++ ui/js/component/fileActions/view.jsx | 6 +--- ui/js/component/tipLink/index.js | 3 +- ui/js/component/tipLink/view.jsx | 5 ++-- .../internal/TransactionListBody.jsx | 21 ++++++++++--- ui/js/constants/action_types.js | 2 ++ ui/js/page/file/index.js | 2 ++ ui/js/page/file/view.jsx | 28 ++--------------- ui/js/reducers/claims.js | 30 +++++++++++++++++-- ui/js/selectors/claims.js | 5 ++++ 11 files changed, 75 insertions(+), 42 deletions(-) diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js index 71f94852c..e8e45f341 100644 --- a/ui/js/actions/claims.js +++ b/ui/js/actions/claims.js @@ -4,6 +4,14 @@ import { doOpenModal, doShowSnackBar } from "actions/app"; import * as types from "constants/action_types"; import * as modals from "constants/modal_types"; +export function doShowTipBox() { + return { type: types.SHOW_TIP_BOX }; +} + +export function doHideTipBox() { + return { type: types.HIDE_TIP_BOX }; +} + export function doSendSupport(amount, claim_id) { return function(dispatch, getState) { const state = getState(); @@ -22,6 +30,7 @@ export function doSendSupport(amount, claim_id) { dispatch({ type: types.SUPPORT_TRANSACTION_COMPLETED, }); + dispatch(doHideTipBox); dispatch( doShowSnackBar({ message: __(`You sent ${amount} LBC as support, Mahalo!`), @@ -32,7 +41,7 @@ export function doSendSupport(amount, claim_id) { } else { dispatch({ type: types.SUPPORT_TRANSACTION_FAILED, - data: { error: results }, + data: { error: results.code }, }); dispatch(doOpenModal(modals.TRANSACTION_FAILED)); } @@ -41,7 +50,7 @@ export function doSendSupport(amount, claim_id) { const errorCallback = error => { dispatch({ type: types.SUPPORT_TRANSACTION_FAILED, - data: { error: error.message }, + data: { error: error.code }, }); dispatch(doOpenModal(modals.TRANSACTION_FAILED)); }; diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index b94e2bbcb..851b28507 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -9,6 +9,7 @@ import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; import { makeSelectClaimIsMine } from "selectors/claims"; import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; import { doNavigate } from "actions/navigation"; +import { doShowTipBox } from "actions/claims"; import FileActions from "./view"; const select = (state, props) => ({ @@ -25,6 +26,7 @@ const perform = dispatch => ({ startDownload: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), editClaim: claimId => dispatch(doNavigate("/publish", { id: claimId })), + showTipBox: () => dispatch(doShowTipBox()), }); export default connect(select, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 361338b89..bffcfa664 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -4,10 +4,6 @@ import FileDownloadLink from "component/fileDownloadLink"; import * as modals from "constants/modal_types"; class FileActions extends React.PureComponent { - handleSupportButtonClicked() { - this.props.onTipShow(); - } - render() { const { fileInfo, @@ -37,7 +33,7 @@ class FileActions extends React.PureComponent { button="text" icon="icon-gift" label={__("Support")} - onClick={this.handleSupportButtonClicked.bind(this)} + onClick={this.props.showTipBox} /> ({}); const perform = dispatch => ({ sendSupport: (amount, claim_id) => dispatch(doSendSupport(amount, claim_id)), + hideTipBox: () => dispatch(doHideTipBox()), }); export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 831806d48..00c2639f3 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -7,7 +7,7 @@ class TipLink extends React.PureComponent { super(props); this.state = { - tipAmount: 1.0, + tipAmount: 0.0, }; } @@ -15,11 +15,10 @@ class TipLink extends React.PureComponent { let claim_id = this.props.claim_id; let amount = this.state.tipAmount; this.props.sendSupport(amount, claim_id); - this.props.onTipHide(); } handleSupportCancelButtonClicked() { - this.props.onTipHide(); + this.props.hideTipBox(); } handleSupportPriceChange(event) { diff --git a/ui/js/component/transactionList/internal/TransactionListBody.jsx b/ui/js/component/transactionList/internal/TransactionListBody.jsx index 12beb2e8d..6ad795f05 100644 --- a/ui/js/component/transactionList/internal/TransactionListBody.jsx +++ b/ui/js/component/transactionList/internal/TransactionListBody.jsx @@ -125,13 +125,26 @@ class TransactionTableBody extends React.PureComponent { render() { const { transactions, filter } = this.props; + let transactionList = transactions + .filter(this.filterList, this) + .filter(this.removeFeeTx, this) + .map(this.renderBody, this); + + if (transactionList.length == 0) { + return ( +
+ + + + + ); + } return ( - {transactions - .filter(this.filterList, this) - .filter(this.removeFeeTx, this) - .map(this.renderBody, this)} + {transactionList} ); } diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 5281e6b97..57466b17f 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -136,6 +136,8 @@ export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; +export const HIDE_TIP_BOX = "HIDE_TIP_BOX"; +export const SHOW_TIP_BOX = "SHOW_TIP_BOX"; //Language export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED"; diff --git a/ui/js/page/file/index.js b/ui/js/page/file/index.js index d0d1fb476..0154d00a0 100644 --- a/ui/js/page/file/index.js +++ b/ui/js/page/file/index.js @@ -9,6 +9,7 @@ import { makeSelectClaimForUri, makeSelectContentTypeForUri, makeSelectMetadataForUri, + selectShowTipBox, } from "selectors/claims"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { selectShowNsfw } from "selectors/settings"; @@ -20,6 +21,7 @@ const select = (state, props) => ({ costInfo: makeSelectCostInfoForUri(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state), obscureNsfw: !selectShowNsfw(state), + showTipBox: selectShowTipBox(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state), rewardedContentClaimIds: selectRewardContentClaimIds(state, props), }); diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index 3e1a2e2f9..f27d0ab01 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -71,18 +71,6 @@ class FilePage extends React.PureComponent { } } - handleTipShow() { - this.setState({ - showTipBox: true, - }); - } - - handleTipHide() { - this.setState({ - showTipBox: false, - }); - } - render() { const { claim, @@ -91,10 +79,9 @@ class FilePage extends React.PureComponent { contentType, uri, rewardedContentClaimIds, + showTipBox, } = this.props; - const { showTipBox } = this.state; - if (!claim || !metadata) { return ( {__("Empty claim or metadata info.")} @@ -156,10 +143,7 @@ class FilePage extends React.PureComponent { : uriIndicator} - + {!showTipBox &&
@@ -179,13 +163,7 @@ class FilePage extends React.PureComponent { />
: ""} - {showTipBox - ? - : ""} + {showTipBox ? : ""} {!showTipBox &&
({ + tipBoxShown: false, +}); + +const defaultState = { + supportTransaction: buildSupportTransaction(), +}; reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) { const { uri, certificate, claim } = action.data; @@ -189,6 +196,22 @@ reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) { }); }; +reducers[types.HIDE_TIP_BOX] = function(state, action) { + return Object.assign({}, state, { + supportTransaction: buildSupportTransaction(), + }); +}; + +reducers[types.SHOW_TIP_BOX] = function(state, action) { + const newSupportTransaction = Object.assign({}, state.supportTransaction, { + tipBoxShown: true, + }); + + return Object.assign({}, state, { + supportTransaction: newSupportTransaction, + }); +}; + reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { const newSupportTransaction = Object.assign({}, state.supportTransaction, { sendingSupport: true, @@ -200,13 +223,16 @@ reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { }; reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { - return Object.assign({}, state); + return Object.assign({}, state, { + supportTransaction: buildSupportTransaction(), + }); }; reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { const newSupportTransaction = Object.assign({}, state.supportTransaction, { sendingSupport: false, error: action.data.error, + tipBoxShown: true, }); return Object.assign({}, state, { diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index ce8ebc8cd..45643722a 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -174,3 +174,8 @@ export const selectMyChannelClaims = createSelector( return claims; } ); + +export const selectShowTipBox = createSelector( + _selectState, + state => state.supportTransaction.tipBoxShown +); From c05edc40426febd95a0a5877ea1b1d63f1f83051 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 14:26:55 -0400 Subject: [PATCH 099/132] clean up tip and search navigation --- app/package.json | 2 +- ui/js/actions/claims.js | 9 ------ ui/js/actions/navigation.js | 38 +++++++------------------ ui/js/component/fileActions/index.js | 9 ++---- ui/js/component/fileActions/view.jsx | 34 +++++++++------------- ui/js/component/fileListSearch/view.jsx | 12 +++++++- ui/js/component/link/index.js | 2 +- ui/js/component/link/view.jsx | 3 +- ui/js/component/tipLink/index.js | 3 +- ui/js/component/tipLink/view.jsx | 9 +++--- ui/js/constants/action_types.js | 1 - ui/js/page/file/index.js | 4 +-- ui/js/page/file/view.jsx | 14 +++------ ui/js/reducers/claims.js | 7 +---- ui/js/reducers/navigation.js | 15 ++++------ ui/js/reducers/search.js | 3 -- ui/js/selectors/claims.js | 2 +- ui/js/selectors/navigation.js | 5 +++- ui/js/selectors/search.js | 5 ++-- 19 files changed, 68 insertions(+), 109 deletions(-) diff --git a/app/package.json b/app/package.json index e9022a2e9..ec2657777 100644 --- a/app/package.json +++ b/app/package.json @@ -20,7 +20,7 @@ "electron-rebuild": "^1.5.11" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.16.0rc8", + "lbrynetDaemonVersion": "0.16.0rc9", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip" }, "license": "MIT" diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js index e8e45f341..51c50785d 100644 --- a/ui/js/actions/claims.js +++ b/ui/js/actions/claims.js @@ -4,14 +4,6 @@ import { doOpenModal, doShowSnackBar } from "actions/app"; import * as types from "constants/action_types"; import * as modals from "constants/modal_types"; -export function doShowTipBox() { - return { type: types.SHOW_TIP_BOX }; -} - -export function doHideTipBox() { - return { type: types.HIDE_TIP_BOX }; -} - export function doSendSupport(amount, claim_id) { return function(dispatch, getState) { const state = getState(); @@ -30,7 +22,6 @@ export function doSendSupport(amount, claim_id) { dispatch({ type: types.SUPPORT_TRANSACTION_COMPLETED, }); - dispatch(doHideTipBox); dispatch( doShowSnackBar({ message: __(`You sent ${amount} LBC as support, Mahalo!`), diff --git a/ui/js/actions/navigation.js b/ui/js/actions/navigation.js index b34a2e876..0ab3a22eb 100644 --- a/ui/js/actions/navigation.js +++ b/ui/js/actions/navigation.js @@ -1,5 +1,6 @@ import * as types from "constants/action_types"; import { + computePageFromPath, selectPageTitle, selectCurrentPage, selectCurrentParams, @@ -20,9 +21,17 @@ export function doNavigate(path, params = {}, options = {}) { url += "?" + toQueryString(params); } - dispatch(doChangePath(url, options)); + const state = getState(), + currentPage = selectCurrentPage(state), + nextPage = computePageFromPath(path), + scrollY = options.scrollY; - const pageTitle = selectPageTitle(getState()) + " - LBRY"; + if (currentPage != nextPage) { + //I wasn't seeing it scroll to the proper position without this -- possibly because the page isn't fully rendered? Not sure - Jeremy + setTimeout(() => { + window.scrollTo(0, scrollY ? scrollY : 0); + }, 100); + } dispatch({ type: types.HISTORY_NAVIGATE, @@ -45,31 +54,6 @@ export function doAuthNavigate(pathAfterAuth = null, params = {}) { }; } -export function doChangePath(path, options = {}) { - return function(dispatch, getState) { - dispatch({ - type: types.CHANGE_PATH, - data: { - path, - }, - }); - - const state = getState(); - const scrollY = options.scrollY; - - //I wasn't seeing it scroll to the proper position without this -- possibly because the page isn't fully rendered? Not sure - Jeremy - setTimeout(() => { - window.scrollTo(0, scrollY ? scrollY : 0); - }, 100); - - const currentPage = selectCurrentPage(state); - if (currentPage === "search") { - const params = selectCurrentParams(state); - dispatch(doSearch(params.query)); - } - }; -} - export function doHistoryTraverse(dispatch, state, modifier) { const stack = selectHistoryStack(state), index = selectHistoryIndex(state) + modifier; diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 851b28507..75eaeff9a 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -1,15 +1,13 @@ import React from "react"; import { connect } from "react-redux"; -import { selectPlatform } from "selectors/app"; import { makeSelectFileInfoForUri } from "selectors/file_info"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doOpenModal } from "actions/app"; import { doFetchAvailability } from "actions/availability"; -import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info"; +import { doOpenFileInShell } from "actions/file_info"; import { makeSelectClaimIsMine } from "selectors/claims"; -import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content"; +import { doPurchaseUri, doStartDownload } from "actions/content"; import { doNavigate } from "actions/navigation"; -import { doShowTipBox } from "actions/claims"; import FileActions from "./view"; const select = (state, props) => ({ @@ -21,12 +19,11 @@ const select = (state, props) => ({ const perform = dispatch => ({ checkAvailability: uri => dispatch(doFetchAvailability(uri)), + navigate: (path, params) => dispatch(doNavigate(path, params)), openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)), startDownload: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), - editClaim: claimId => dispatch(doNavigate("/publish", { id: claimId })), - showTipBox: () => dispatch(doShowTipBox()), }); export default connect(select, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index bffcfa664..ecb218228 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -5,19 +5,10 @@ import * as modals from "constants/modal_types"; class FileActions extends React.PureComponent { render() { - const { - fileInfo, - uri, - openModal, - claimIsMine, - editClaim, - checkAvailability, - } = this.props; + const { fileInfo, uri, openModal, claimIsMine } = this.props; const claimId = fileInfo ? fileInfo.claim_id : null, - metadata = fileInfo ? fileInfo.metadata : null, - showMenu = fileInfo && Object.keys(fileInfo).length > 0, - title = metadata ? metadata.title : uri; + showDelete = fileInfo && Object.keys(fileInfo).length > 0; return (
@@ -26,22 +17,25 @@ class FileActions extends React.PureComponent { button="text" icon="icon-edit" label={__("Edit")} - onClick={() => editClaim(claimId)} + navigate="/publish" + navigateParams={{ id: claimId }} />} - openModal(modals.CONFIRM_FILE_REMOVE, { uri })} + navigate="/show" + navigateParams={{ uri, tab: "tip" }} /> + {showDelete && + openModal(modals.CONFIRM_FILE_REMOVE, { uri })} + />}
); } diff --git a/ui/js/component/fileListSearch/view.jsx b/ui/js/component/fileListSearch/view.jsx index 682d07e7c..59884da8e 100644 --- a/ui/js/component/fileListSearch/view.jsx +++ b/ui/js/component/fileListSearch/view.jsx @@ -49,7 +49,17 @@ const FileListSearchResults = props => { class FileListSearch extends React.PureComponent { componentWillMount() { - this.props.search(this.props.query); + this.doSearch(this.props); + } + + componentWillReceiveProps(props) { + if (props.query != this.props.query) { + this.doSearch(props); + } + } + + doSearch(props) { + this.props.search(props.query); } render() { diff --git a/ui/js/component/link/index.js b/ui/js/component/link/index.js index 5847c97d9..37340987a 100644 --- a/ui/js/component/link/index.js +++ b/ui/js/component/link/index.js @@ -4,7 +4,7 @@ import { doNavigate } from "actions/navigation"; import Link from "./view"; const perform = dispatch => ({ - doNavigate: path => dispatch(doNavigate(path)), + doNavigate: (path, params) => dispatch(doNavigate(path, params)), }); export default connect(null, perform)(Link); diff --git a/ui/js/component/link/view.jsx b/ui/js/component/link/view.jsx index a30d1a981..1ba8f4b52 100644 --- a/ui/js/component/link/view.jsx +++ b/ui/js/component/link/view.jsx @@ -12,6 +12,7 @@ const Link = props => { disabled, children, navigate, + navigateParams, doNavigate, } = props; @@ -23,7 +24,7 @@ const Link = props => { const onClick = !props.onClick && navigate ? () => { - doNavigate(navigate); + doNavigate(navigate, navigateParams || {}); } : props.onClick; diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js index 53ca5e10d..b43f225ac 100644 --- a/ui/js/component/tipLink/index.js +++ b/ui/js/component/tipLink/index.js @@ -1,13 +1,12 @@ import React from "react"; import { connect } from "react-redux"; -import { doSendSupport, doHideTipBox } from "actions/claims"; +import { doSendSupport } from "actions/claims"; import TipLink from "./view"; const select = state => ({}); const perform = dispatch => ({ sendSupport: (amount, claim_id) => dispatch(doSendSupport(amount, claim_id)), - hideTipBox: () => dispatch(doHideTipBox()), }); export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 00c2639f3..81e0aa31a 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -17,10 +17,6 @@ class TipLink extends React.PureComponent { this.props.sendSupport(amount, claim_id); } - handleSupportCancelButtonClicked() { - this.props.hideTipBox(); - } - handleSupportPriceChange(event) { this.setState({ tipAmount: Number(event.target.value), @@ -28,6 +24,8 @@ class TipLink extends React.PureComponent { } render() { + const { uri } = this.props; + return (
@@ -59,7 +57,8 @@ class TipLink extends React.PureComponent {
diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 57466b17f..d1c75403d 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -9,7 +9,6 @@ export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH"; export const VOLUME_CHANGED = "VOLUME_CHANGED"; // Navigation -export const CHANGE_PATH = "CHANGE_PATH"; export const CHANGE_AFTER_AUTH_PATH = "CHANGE_AFTER_AUTH_PATH"; export const WINDOW_SCROLLED = "WINDOW_SCROLLED"; export const HISTORY_NAVIGATE = "HISTORY_NAVIGATE"; diff --git a/ui/js/page/file/index.js b/ui/js/page/file/index.js index 0154d00a0..cf81056f0 100644 --- a/ui/js/page/file/index.js +++ b/ui/js/page/file/index.js @@ -9,11 +9,11 @@ import { makeSelectClaimForUri, makeSelectContentTypeForUri, makeSelectMetadataForUri, - selectShowTipBox, } from "selectors/claims"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { selectShowNsfw } from "selectors/settings"; import FilePage from "./view"; +import { makeSelectCurrentParam } from "../../selectors/navigation"; const select = (state, props) => ({ claim: makeSelectClaimForUri(props.uri)(state), @@ -21,7 +21,7 @@ const select = (state, props) => ({ costInfo: makeSelectCostInfoForUri(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state), obscureNsfw: !selectShowNsfw(state), - showTipBox: selectShowTipBox(state), + tab: makeSelectCurrentParam("tab")(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state), rewardedContentClaimIds: selectRewardContentClaimIds(state, props), }); diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index f27d0ab01..73d2ed405 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -14,7 +14,6 @@ import DateTime from "component/dateTime"; const FormatItem = props => { const { - publishedDate, contentType, claim: { height }, metadata: { language, license }, @@ -43,13 +42,6 @@ const FormatItem = props => { }; class FilePage extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - showTipBox: false, - }; - } - componentDidMount() { this.fetchFileInfo(this.props); this.fetchCostInfo(this.props); @@ -77,11 +69,13 @@ class FilePage extends React.PureComponent { fileInfo, metadata, contentType, + tab, uri, rewardedContentClaimIds, - showTipBox, } = this.props; + const showTipBox = tab == "tip"; + if (!claim || !metadata) { return ( {__("Empty claim or metadata info.")} @@ -163,7 +157,7 @@ class FilePage extends React.PureComponent { />
: ""} - {showTipBox ? : ""} + {showTipBox ? : ""} {!showTipBox &&
({ - tipBoxShown: false, -}); - const defaultState = { - supportTransaction: buildSupportTransaction(), + supportTransaction: {}, }; reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) { @@ -232,7 +228,6 @@ reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { const newSupportTransaction = Object.assign({}, state.supportTransaction, { sendingSupport: false, error: action.data.error, - tipBoxShown: true, }); return Object.assign({}, state, { diff --git a/ui/js/reducers/navigation.js b/ui/js/reducers/navigation.js index 821db9183..1ebcab2c9 100644 --- a/ui/js/reducers/navigation.js +++ b/ui/js/reducers/navigation.js @@ -24,12 +24,6 @@ reducers[types.DAEMON_READY] = function(state, action) { }); }; -reducers[types.CHANGE_PATH] = function(state, action) { - return Object.assign({}, state, { - currentPath: action.data.path, - }); -}; - reducers[types.CHANGE_AFTER_AUTH_PATH] = function(state, action) { return Object.assign({}, state, { pathAfterAuth: action.data.path, @@ -38,15 +32,16 @@ reducers[types.CHANGE_AFTER_AUTH_PATH] = function(state, action) { reducers[types.HISTORY_NAVIGATE] = (state, action) => { const { stack, index } = state; - - let newState = {}; - const path = action.data.url; - // Check for duplicated + let newState = { + currentPath: path, + }; + if (action.data.index >= 0) { newState.index = action.data.index; } else if (!stack[index] || stack[index].path !== path) { + // ^ Check for duplicated newState.stack = [...stack.slice(0, index + 1), { path, scrollY: 0 }]; newState.index = newState.stack.length - 1; } diff --git a/ui/js/reducers/search.js b/ui/js/reducers/search.js index be6c3bec7..ed500b987 100644 --- a/ui/js/reducers/search.js +++ b/ui/js/reducers/search.js @@ -1,5 +1,4 @@ import * as types from "constants/action_types"; -import lbryuri from "lbryuri"; const reducers = {}; const defaultState = {}; @@ -9,7 +8,6 @@ reducers[types.SEARCH_STARTED] = function(state, action) { return Object.assign({}, state, { searching: true, - query: query, }); }; @@ -31,7 +29,6 @@ reducers[types.SEARCH_COMPLETED] = function(state, action) { reducers[types.SEARCH_CANCELLED] = function(state, action) { return Object.assign({}, state, { searching: false, - query: undefined, }); }; diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 45643722a..14ac231fc 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -66,7 +66,7 @@ export const selectAllFetchingChannelClaims = createSelector( ); export const makeSelectFetchingChannelClaims = uri => { - createSelector( + return createSelector( selectAllFetchingChannelClaims, fetching => fetching && fetching[uri] ); diff --git a/ui/js/selectors/navigation.js b/ui/js/selectors/navigation.js index f11f35eb9..b5eb98ade 100644 --- a/ui/js/selectors/navigation.js +++ b/ui/js/selectors/navigation.js @@ -10,8 +10,11 @@ export const selectCurrentPath = createSelector( state => state.currentPath ); +export const computePageFromPath = path => + path.replace(/^\//, "").split("?")[0]; + export const selectCurrentPage = createSelector(selectCurrentPath, path => { - return path.replace(/^\//, "").split("?")[0]; + return computePageFromPath(path); }); export const selectCurrentParams = createSelector(selectCurrentPath, path => { diff --git a/ui/js/selectors/search.js b/ui/js/selectors/search.js index 4e02c2542..9b967d66e 100644 --- a/ui/js/selectors/search.js +++ b/ui/js/selectors/search.js @@ -8,8 +8,9 @@ import { export const _selectState = state => state.search || {}; export const selectSearchQuery = createSelector( - _selectState, - state => state.query + selectCurrentPage, + selectCurrentParams, + (page, params) => (page === "search" ? params && params.query : null) ); export const selectIsSearching = createSelector( From e9b48f0bd6b943b637ef9e220ae5a2d63ced632d Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 16:33:52 -0400 Subject: [PATCH 100/132] tip clean up and refactor --- ui/js/actions/claims.js | 56 ------------ ui/js/actions/wallet.js | 53 +++++++++++ ui/js/component/fileDetails/index.js | 16 ++++ ui/js/component/fileDetails/view.jsx | 64 +++++++++++++ ui/js/component/tipLink/index.js | 12 --- ui/js/component/tipLink/view.jsx | 69 -------------- ui/js/component/uriIndicator/view.jsx | 27 +++++- ui/js/component/walletSendTip/index.js | 18 ++++ ui/js/component/walletSendTip/view.jsx | 79 ++++++++++++++++ ui/js/constants/action_types.js | 36 ++++---- ui/js/modal/modalRemoveFile/index.js | 7 +- ui/js/modal/modalRemoveFile/view.jsx | 2 +- ui/js/page/file/view.jsx | 120 +++++-------------------- ui/js/reducers/claims.js | 47 +--------- ui/js/reducers/wallet.js | 20 +++++ ui/js/selectors/claims.js | 12 +-- ui/js/selectors/wallet.js | 5 ++ ui/scss/component/_card.scss | 6 ++ 18 files changed, 335 insertions(+), 314 deletions(-) delete mode 100644 ui/js/actions/claims.js create mode 100644 ui/js/component/fileDetails/index.js create mode 100644 ui/js/component/fileDetails/view.jsx delete mode 100644 ui/js/component/tipLink/index.js delete mode 100644 ui/js/component/tipLink/view.jsx create mode 100644 ui/js/component/walletSendTip/index.js create mode 100644 ui/js/component/walletSendTip/view.jsx diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js deleted file mode 100644 index 51c50785d..000000000 --- a/ui/js/actions/claims.js +++ /dev/null @@ -1,56 +0,0 @@ -import lbry from "lbry"; -import { selectBalance } from "selectors/wallet"; -import { doOpenModal, doShowSnackBar } from "actions/app"; -import * as types from "constants/action_types"; -import * as modals from "constants/modal_types"; - -export function doSendSupport(amount, claim_id) { - return function(dispatch, getState) { - const state = getState(); - const balance = selectBalance(state); - - if (balance - amount <= 0) { - return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); - } - - dispatch({ - type: types.SUPPORT_TRANSACTION_STARTED, - }); - - const successCallback = results => { - if (results.txid) { - dispatch({ - type: types.SUPPORT_TRANSACTION_COMPLETED, - }); - dispatch( - doShowSnackBar({ - message: __(`You sent ${amount} LBC as support, Mahalo!`), - linkText: __("History"), - linkTarget: __("/wallet"), - }) - ); - } else { - dispatch({ - type: types.SUPPORT_TRANSACTION_FAILED, - data: { error: results.code }, - }); - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); - } - }; - - const errorCallback = error => { - dispatch({ - type: types.SUPPORT_TRANSACTION_FAILED, - data: { error: error.code }, - }); - dispatch(doOpenModal(modals.TRANSACTION_FAILED)); - }; - - lbry - .wallet_send({ - claim_id: claim_id, - amount: amount, - }) - .then(successCallback, errorCallback); - }; -} diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 025cb1def..0e90266fb 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -6,6 +6,7 @@ import { selectBalance, } from "selectors/wallet"; import { doOpenModal, doShowSnackBar } from "actions/app"; +import { doNavigate } from "actions/navigation"; import * as modals from "constants/modal_types"; export function doUpdateBalance(balance) { @@ -143,3 +144,55 @@ export function doSetDraftTransactionAddress(address) { data: { address }, }; } + +export function doSendSupport(amount, claim_id, uri) { + return function(dispatch, getState) { + const state = getState(); + const balance = selectBalance(state); + + if (balance - amount <= 0) { + return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); + } + + dispatch({ + type: types.SUPPORT_TRANSACTION_STARTED, + }); + + const successCallback = results => { + if (results.txid) { + dispatch({ + type: types.SUPPORT_TRANSACTION_COMPLETED, + }); + dispatch( + doShowSnackBar({ + message: __(`You sent ${amount} LBC as support, Mahalo!`), + linkText: __("History"), + linkTarget: __("/wallet"), + }) + ); + dispatch(doNavigate("/show", { uri })); + } else { + dispatch({ + type: types.SUPPORT_TRANSACTION_FAILED, + data: { error: results.code }, + }); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + } + }; + + const errorCallback = error => { + dispatch({ + type: types.SUPPORT_TRANSACTION_FAILED, + data: { error: error.code }, + }); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + }; + + lbry + .wallet_send({ + claim_id: claim_id, + amount: amount, + }) + .then(successCallback, errorCallback); + }; +} diff --git a/ui/js/component/fileDetails/index.js b/ui/js/component/fileDetails/index.js new file mode 100644 index 000000000..385959ed2 --- /dev/null +++ b/ui/js/component/fileDetails/index.js @@ -0,0 +1,16 @@ +import React from "react"; +import { connect } from "react-redux"; +import { + makeSelectClaimForUri, + makeSelectContentTypeForUri, + makeSelectMetadataForUri, +} from "selectors/claims"; +import FileDetails from "./view"; + +const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), + contentType: makeSelectContentTypeForUri(props.uri)(state), + metadata: makeSelectMetadataForUri(props.uri)(state), +}); + +export default connect(select, null)(FileDetails); diff --git a/ui/js/component/fileDetails/view.jsx b/ui/js/component/fileDetails/view.jsx new file mode 100644 index 000000000..dfcc47699 --- /dev/null +++ b/ui/js/component/fileDetails/view.jsx @@ -0,0 +1,64 @@ +import React from "react"; +import ReactMarkdown from "react-markdown"; +import lbry from "lbry.js"; +import FileActions from "component/fileActions"; +import Link from "component/link"; +import DateTime from "component/dateTime"; + +class FileDetails extends React.PureComponent { + render() { + const { claim, contentType, metadata, uri } = this.props; + + if (!claim || !metadata) { + return ( +
+ {__("Empty claim or metadata info.")} +
+ ); + } + + const { description, language, license } = metadata; + const { height } = claim; + const mediaType = lbry.getMediaType(contentType); + + return ( +
+ +
+ +
+
+
{__("Published on")}
+ {__("There are no transactions of this type.")} +
+ + + + + + + + + + + + + + + +
{__("Published on")}
{__("Content-Type")}{mediaType}
{__("Language")}{language}
{__("License")}{license}
+

+ +

+ + + ); + } +} + +export default FileDetails; diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js deleted file mode 100644 index b43f225ac..000000000 --- a/ui/js/component/tipLink/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { doSendSupport } from "actions/claims"; -import TipLink from "./view"; - -const select = state => ({}); - -const perform = dispatch => ({ - sendSupport: (amount, claim_id) => dispatch(doSendSupport(amount, claim_id)), -}); - -export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx deleted file mode 100644 index 81e0aa31a..000000000 --- a/ui/js/component/tipLink/view.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from "react"; -import Link from "component/link"; -import { FormRow } from "component/form"; - -class TipLink extends React.PureComponent { - constructor(props) { - super(props); - - this.state = { - tipAmount: 0.0, - }; - } - - handleSendButtonClicked() { - let claim_id = this.props.claim_id; - let amount = this.state.tipAmount; - this.props.sendSupport(amount, claim_id); - } - - handleSupportPriceChange(event) { - this.setState({ - tipAmount: Number(event.target.value), - }); - } - - render() { - const { uri } = this.props; - - return ( -
-
-

{__("Support")}

-
-
- {__( - "Support the creator and the success of their content by sending a tip. " - )} - -
-
- this.handleSupportPriceChange(event)} - /> -
-
- - -
-
- ); - } -} - -export default TipLink; diff --git a/ui/js/component/uriIndicator/view.jsx b/ui/js/component/uriIndicator/view.jsx index b69abd591..a6dcb1a50 100644 --- a/ui/js/component/uriIndicator/view.jsx +++ b/ui/js/component/uriIndicator/view.jsx @@ -1,5 +1,7 @@ import React from "react"; import { Icon } from "component/common"; +import Link from "component/link"; +import lbryuri from "lbryuri.js"; class UriIndicator extends React.PureComponent { componentWillMount() { @@ -19,7 +21,7 @@ class UriIndicator extends React.PureComponent { } render() { - const { claim, uri, isResolvingUri } = this.props; + const { claim, link, uri, isResolvingUri } = this.props; if (isResolvingUri && !claim) { return Validating...; @@ -33,21 +35,30 @@ class UriIndicator extends React.PureComponent { channel_name: channelName, has_signature: hasSignature, signature_is_valid: signatureIsValid, + value, } = claim; + const channelClaimId = + value && + value.publisherSignature && + value.publisherSignature.certificateId; if (!hasSignature || !channelName) { return Anonymous; } - let icon, modifier; + let icon, channelLink, modifier; + if (signatureIsValid) { modifier = "valid"; + channelLink = link + ? lbryuri.build({ channelName, claimId: channelClaimId }, false) + : false; } else { icon = "icon-times-circle"; modifier = "invalid"; } - return ( + const inner = ( {channelName} {" "} {!signatureIsValid @@ -58,6 +69,16 @@ class UriIndicator extends React.PureComponent { : ""} ); + + if (!channelLink) { + return inner; + } + + return ( + + {inner} + + ); } } diff --git a/ui/js/component/walletSendTip/index.js b/ui/js/component/walletSendTip/index.js new file mode 100644 index 000000000..6d3275321 --- /dev/null +++ b/ui/js/component/walletSendTip/index.js @@ -0,0 +1,18 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doSendSupport } from "actions/wallet"; +import WalletSendTip from "./view"; +import { makeSelectTitleForUri } from "selectors/claims"; +import { selectIsSendingSupport } from "selectors/wallet"; + +const select = (state, props) => ({ + isPending: selectIsSendingSupport(state), + title: makeSelectTitleForUri(props.uri)(state), +}); + +const perform = dispatch => ({ + sendSupport: (amount, claim_id, uri) => + dispatch(doSendSupport(amount, claim_id, uri)), +}); + +export default connect(select, perform)(WalletSendTip); diff --git a/ui/js/component/walletSendTip/view.jsx b/ui/js/component/walletSendTip/view.jsx new file mode 100644 index 000000000..9b8ce0338 --- /dev/null +++ b/ui/js/component/walletSendTip/view.jsx @@ -0,0 +1,79 @@ +import React from "react"; +import Link from "component/link"; +import { FormRow } from "component/form"; +import UriIndicator from "component/uriIndicator"; + +class WalletSendTip extends React.PureComponent { + constructor(props) { + super(props); + + this.state = { + amount: 0.0, + }; + } + + handleSendButtonClicked() { + const { claim_id, uri } = this.props; + let amount = this.state.amount; + this.props.sendSupport(amount, claim_id, uri); + } + + handleSupportPriceChange(event) { + this.setState({ + amount: Number(event.target.value), + }); + } + + render() { + const { errorMessage, isPending, title, uri } = this.props; + + return ( +
+
+

{__("Support")}

+
+
+ + {__( + 'This will appear as a tip for "%s" located at %s.', + title, + uri + ) + " "} + + + } + placeholder="1.00" + onChange={event => this.handleSupportPriceChange(event)} + /> +
+ + +
+
+
+ ); + } +} + +export default WalletSendTip; diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index d1c75403d..a4cb1afaa 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -39,8 +39,11 @@ export const SEND_TRANSACTION_STARTED = "SEND_TRANSACTION_STARTED"; export const SEND_TRANSACTION_COMPLETED = "SEND_TRANSACTION_COMPLETED"; export const SEND_TRANSACTION_FAILED = "SEND_TRANSACTION_FAILED"; export const FETCH_BLOCK_SUCCESS = "FETCH_BLOCK_SUCCESS"; +export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; +export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; +export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; -// Content +// Claims export const FETCH_FEATURED_CONTENT_STARTED = "FETCH_FEATURED_CONTENT_STARTED"; export const FETCH_FEATURED_CONTENT_COMPLETED = "FETCH_FEATURED_CONTENT_COMPLETED"; @@ -56,6 +59,19 @@ export const FETCH_CHANNEL_CLAIM_COUNT_COMPLETED = export const FETCH_CLAIM_LIST_MINE_STARTED = "FETCH_CLAIM_LIST_MINE_STARTED"; export const FETCH_CLAIM_LIST_MINE_COMPLETED = "FETCH_CLAIM_LIST_MINE_COMPLETED"; +export const ABANDON_CLAIM_STARTED = "ABANDON_CLAIM_STARTED"; +export const ABANDON_CLAIM_SUCCEEDED = "ABANDON_CLAIM_SUCCEEDED"; +export const FETCH_CHANNEL_LIST_MINE_STARTED = + "FETCH_CHANNEL_LIST_MINE_STARTED"; +export const FETCH_CHANNEL_LIST_MINE_COMPLETED = + "FETCH_CHANNEL_LIST_MINE_COMPLETED"; +export const CREATE_CHANNEL_STARTED = "CREATE_CHANNEL_STARTED"; +export const CREATE_CHANNEL_COMPLETED = "CREATE_CHANNEL_COMPLETED"; +export const PUBLISH_STARTED = "PUBLISH_STARTED"; +export const PUBLISH_COMPLETED = "PUBLISH_COMPLETED"; +export const PUBLISH_FAILED = "PUBLISH_FAILED"; + +// Files export const FILE_LIST_STARTED = "FILE_LIST_STARTED"; export const FILE_LIST_SUCCEEDED = "FILE_LIST_SUCCEEDED"; export const FETCH_FILE_INFO_STARTED = "FETCH_FILE_INFO_STARTED"; @@ -72,17 +88,6 @@ export const PLAY_VIDEO_STARTED = "PLAY_VIDEO_STARTED"; export const FETCH_AVAILABILITY_STARTED = "FETCH_AVAILABILITY_STARTED"; export const FETCH_AVAILABILITY_COMPLETED = "FETCH_AVAILABILITY_COMPLETED"; export const FILE_DELETE = "FILE_DELETE"; -export const ABANDON_CLAIM_STARTED = "ABANDON_CLAIM_STARTED"; -export const ABANDON_CLAIM_SUCCEEDED = "ABANDON_CLAIM_SUCCEEDED"; -export const FETCH_CHANNEL_LIST_MINE_STARTED = - "FETCH_CHANNEL_LIST_MINE_STARTED"; -export const FETCH_CHANNEL_LIST_MINE_COMPLETED = - "FETCH_CHANNEL_LIST_MINE_COMPLETED"; -export const CREATE_CHANNEL_STARTED = "CREATE_CHANNEL_STARTED"; -export const CREATE_CHANNEL_COMPLETED = "CREATE_CHANNEL_COMPLETED"; -export const PUBLISH_STARTED = "PUBLISH_STARTED"; -export const PUBLISH_COMPLETED = "PUBLISH_COMPLETED"; -export const PUBLISH_FAILED = "PUBLISH_FAILED"; // Search export const SEARCH_STARTED = "SEARCH_STARTED"; @@ -131,13 +136,6 @@ export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; -// Supports -export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; -export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; -export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; -export const HIDE_TIP_BOX = "HIDE_TIP_BOX"; -export const SHOW_TIP_BOX = "SHOW_TIP_BOX"; - //Language export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED"; export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED"; diff --git a/ui/js/modal/modalRemoveFile/index.js b/ui/js/modal/modalRemoveFile/index.js index 8c00f383e..39ae89ceb 100644 --- a/ui/js/modal/modalRemoveFile/index.js +++ b/ui/js/modal/modalRemoveFile/index.js @@ -2,16 +2,13 @@ import React from "react"; import { connect } from "react-redux"; import { doCloseModal } from "actions/app"; import { doDeleteFileAndGoBack } from "actions/file_info"; -import { - makeSelectMetadataForUri, - makeSelectClaimIsMine, -} from "selectors/claims"; +import { makeSelectTitleForUri, makeSelectClaimIsMine } from "selectors/claims"; import { makeSelectFileInfoForUri } from "selectors/file_info"; import ModalRemoveFile from "./view"; const select = (state, props) => ({ claimIsMine: makeSelectClaimIsMine(props.uri)(state), - metadata: makeSelectMetadataForUri(props.uri)(state), + title: makeSelectTitleForUri(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state), }); diff --git a/ui/js/modal/modalRemoveFile/view.jsx b/ui/js/modal/modalRemoveFile/view.jsx index f646c5400..c18acb6f2 100644 --- a/ui/js/modal/modalRemoveFile/view.jsx +++ b/ui/js/modal/modalRemoveFile/view.jsx @@ -30,7 +30,7 @@ class ModalRemoveFile extends React.PureComponent { closeModal, deleteFile, fileInfo: { outpoint }, - metadata: { title }, + title, } = this.props; const { deleteChecked, abandonClaimChecked } = this.state; diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index 73d2ed405..35209ae18 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -1,45 +1,13 @@ import React from "react"; -import ReactMarkdown from "react-markdown"; import lbry from "lbry.js"; import lbryuri from "lbryuri.js"; import Video from "component/video"; -import TipLink from "component/tipLink"; import { Thumbnail } from "component/common"; import FilePrice from "component/filePrice"; -import FileActions from "component/fileActions"; -import Link from "component/link"; +import FileDetails from "component/fileDetails"; import UriIndicator from "component/uriIndicator"; import IconFeatured from "component/iconFeatured"; -import DateTime from "component/dateTime"; - -const FormatItem = props => { - const { - contentType, - claim: { height }, - metadata: { language, license }, - } = props; - - const mediaType = lbry.getMediaType(contentType); - - return ( - - - - - - - - - - - - - - - -
{__("Published on")}
{__("Content-Type")}{mediaType}
{__("Language")}{language}
{__("License")}{license}
- ); -}; +import WalletSendTip from "component/walletSendTip"; class FilePage extends React.PureComponent { componentDidMount() { @@ -82,24 +50,7 @@ class FilePage extends React.PureComponent { ); } - const { - txid, - nout, - channel_name: channelName, - has_signature: hasSignature, - signature_is_valid: signatureIsValid, - value, - } = claim; - - const outpoint = txid + ":" + nout; const title = metadata.title; - const channelClaimId = claim.value && claim.value.publisherSignature - ? claim.value.publisherSignature.certificateId - : null; - const channelUri = signatureIsValid && hasSignature && channelName - ? lbryuri.build({ channelName, claimId: channelClaimId }, false) - : null; - const uriIndicator = ; const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id); const mediaType = lbry.getMediaType(contentType); const player = require("render-media"); @@ -109,7 +60,7 @@ class FilePage extends React.PureComponent { mediaType === "audio"; return ( -
+
{isPlayable ?
-
- {!fileInfo || fileInfo.written_bytes <= 0 - ? - - {isRewardContent && {" "}} - - : null} -

{title}

-
- {channelUri - ? - this.props.navigate("/show", { uri: channelUri })} - > - {uriIndicator} - - : uriIndicator} -
- -
- {!showTipBox && -
- + {(!tab || tab === "details") && +
+ {" "} {" "} +
+ {!fileInfo || fileInfo.written_bytes <= 0 + ? + + {isRewardContent && {" "}} + + : null} +

{title}

+
+ +
+
+
} + {tab === "tip" && + }
- {metadata && claim && !showTipBox - ?
- -
- : ""} - {showTipBox ? : ""} - {!showTipBox && -
- -
}
-
+ ); } } diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js index ae80f1712..f18433cdc 100644 --- a/ui/js/reducers/claims.js +++ b/ui/js/reducers/claims.js @@ -2,9 +2,7 @@ import * as types from "constants/action_types"; const reducers = {}; -const defaultState = { - supportTransaction: {}, -}; +const defaultState = {}; reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) { const { uri, certificate, claim } = action.data; @@ -192,49 +190,6 @@ reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) { }); }; -reducers[types.HIDE_TIP_BOX] = function(state, action) { - return Object.assign({}, state, { - supportTransaction: buildSupportTransaction(), - }); -}; - -reducers[types.SHOW_TIP_BOX] = function(state, action) { - const newSupportTransaction = Object.assign({}, state.supportTransaction, { - tipBoxShown: true, - }); - - return Object.assign({}, state, { - supportTransaction: newSupportTransaction, - }); -}; - -reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { - const newSupportTransaction = Object.assign({}, state.supportTransaction, { - sendingSupport: true, - }); - - return Object.assign({}, state, { - supportTransaction: newSupportTransaction, - }); -}; - -reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { - return Object.assign({}, state, { - supportTransaction: buildSupportTransaction(), - }); -}; - -reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { - const newSupportTransaction = Object.assign({}, state.supportTransaction, { - sendingSupport: false, - error: action.data.error, - }); - - return Object.assign({}, state, { - supportTransaction: newSupportTransaction, - }); -}; - export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/reducers/wallet.js b/ui/js/reducers/wallet.js index e704222a6..7cc53b54a 100644 --- a/ui/js/reducers/wallet.js +++ b/ui/js/reducers/wallet.js @@ -15,6 +15,7 @@ const defaultState = { receiveAddress: address, gettingNewAddress: false, draftTransaction: buildDraftTransaction(), + sendingSupport: false, }; reducers[types.FETCH_TRANSACTIONS_STARTED] = function(state, action) { @@ -125,6 +126,25 @@ reducers[types.SEND_TRANSACTION_FAILED] = function(state, action) { }); }; +reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { + return Object.assign({}, state, { + sendingSupport: true, + }); +}; + +reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { + return Object.assign({}, state, { + sendingSupport: false, + }); +}; + +reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { + return Object.assign({}, state, { + error: action.data.error, + sendingSupport: false, + }); +}; + reducers[types.FETCH_BLOCK_SUCCESS] = (state, action) => { const { block, block: { height } } = action.data, blocks = Object.assign({}, state.blocks); diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 14ac231fc..61fd5fdc2 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -97,6 +97,13 @@ export const makeSelectMetadataForUri = uri => { }); }; +export const makeSelectTitleForUri = uri => { + return createSelector( + makeSelectMetadataForUri(uri), + metadata => metadata && metadata.title + ); +}; + export const makeSelectContentTypeForUri = uri => { return createSelector(makeSelectClaimForUri(uri), claim => { const source = @@ -174,8 +181,3 @@ export const selectMyChannelClaims = createSelector( return claims; } ); - -export const selectShowTipBox = createSelector( - _selectState, - state => state.supportTransaction.tipBoxShown -); diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index ab7e22e07..7469c2f48 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -61,6 +61,11 @@ export const selectIsFetchingTransactions = createSelector( state => state.fetchingTransactions ); +export const selectIsSendingSupport = createSelector( + _selectState, + state => state.sendingSupport +); + export const selectReceiveAddress = createSelector( _selectState, state => state.receiveAddress diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index e5dff4e73..0562b4040 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -7,6 +7,9 @@ border-radius: var(--card-radius); margin-bottom: var(--card-margin); overflow: auto; + + //below added to prevent scrollbar on long titles when show page loads, would prefer a cleaner CSS solution + overflow-x: hidden; } .card--obscured { @@ -62,6 +65,9 @@ .card__content { margin-top: var(--card-margin); margin-bottom: var(--card-margin); + table:not(:last-child) { + margin-bottom: var(--card-margin); + } } $font-size-subtext-multiple: 0.82; .card__subtext { From 65f65f1aea9035d46dc7247936c0182b81db82c7 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 20:52:57 -0400 Subject: [PATCH 101/132] transaction refactor / cleanup / improvement --- CHANGELOG.md | 6 +- ui/js/component/common.js | 8 +- ui/js/component/dateTime/view.jsx | 19 ++- ui/js/component/linkTransaction/index.js | 4 +- ui/js/component/transactionList/index.js | 5 + .../internal/TransactionListBody.jsx | 153 ------------------ .../internal/TransactionListHeader.jsx | 19 --- .../internal/TransactionListItem.jsx | 78 +++++++++ ui/js/component/transactionList/view.jsx | 87 ++++++---- ui/js/page/discover/view.jsx | 6 +- ui/js/page/transactionHistory/view.jsx | 18 ++- ui/js/reducers/wallet.js | 12 +- ui/js/selectors/rewards.js | 9 ++ ui/js/selectors/wallet.js | 76 ++++++--- ui/scss/_gui.scss | 8 +- ui/scss/component/_table.scss | 8 + 16 files changed, 257 insertions(+), 259 deletions(-) delete mode 100644 ui/js/component/transactionList/internal/TransactionListBody.jsx delete mode 100644 ui/js/component/transactionList/internal/TransactionListHeader.jsx create mode 100644 ui/js/component/transactionList/internal/TransactionListItem.jsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 156b5190e..29596e25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,15 +8,15 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * Added a tipping button to send LBRY Credits to the publisher - * Added edit button on published content / improved UX for editing claims. + * Added a tipping button to send LBRY Credits to a creator. + * Added an edit button on published content. Significantly improved UX for editing claims. + * Significantly more detail is shown about past transactions and new filtering options for transactions. * File pages now show the time of a publish. * The "auth token" displayable on Help offers security warning * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. ### Changed * - * ### Fixed * URLs on cards no longer wrap and show an ellipsis if longer than one line diff --git a/ui/js/component/common.js b/ui/js/component/common.js index 8af8733c2..23b195bc6 100644 --- a/ui/js/component/common.js +++ b/ui/js/component/common.js @@ -70,7 +70,7 @@ export class CreditAmount extends React.PureComponent { showFree: React.PropTypes.bool, showFullPrice: React.PropTypes.bool, showPlus: React.PropTypes.bool, - look: React.PropTypes.oneOf(["indicator", "plain"]), + look: React.PropTypes.oneOf(["indicator", "plain", "fee"]), fee: React.PropTypes.bool, }; @@ -79,7 +79,6 @@ export class CreditAmount extends React.PureComponent { label: true, showFree: false, look: "indicator", - showFree: false, showFullPrice: false, showPlus: false, fee: false, @@ -119,10 +118,7 @@ export class CreditAmount extends React.PureComponent { return ( diff --git a/ui/js/component/dateTime/view.jsx b/ui/js/component/dateTime/view.jsx index 72d47c130..747286daa 100644 --- a/ui/js/component/dateTime/view.jsx +++ b/ui/js/component/dateTime/view.jsx @@ -1,6 +1,10 @@ import React from "react"; class DateTime extends React.PureComponent { + static SHOW_DATE = "date"; + static SHOW_TIME = "time"; + static SHOW_BOTH = "both"; + componentWillMount() { this.refreshDate(this.props); } @@ -17,9 +21,20 @@ class DateTime extends React.PureComponent { } render() { - const { date } = this.props; + const { date, formatOptions } = this.props; + const show = this.props.show || DateTime.SHOW_BOTH; - return {date && date.toLocaleString()}; + return ( + + {date && + (show == DateTime.SHOW_BOTH || show === DateTime.SHOW_DATE) && + date.toLocaleDateString()} + {show == DateTime.SHOW_BOTH && " "} + {date && + (show == DateTime.SHOW_BOTH || show === DateTime.SHOW_TIME) && + date.toLocaleTimeString()} + + ); } } diff --git a/ui/js/component/linkTransaction/index.js b/ui/js/component/linkTransaction/index.js index 601927420..9983f1bfc 100644 --- a/ui/js/component/linkTransaction/index.js +++ b/ui/js/component/linkTransaction/index.js @@ -1,5 +1,5 @@ import React from "react"; import { connect } from "react-redux"; -import Link from "./view"; +import LinkTransaction from "./view"; -export default connect(null, null)(Link); +export default connect(null, null)(LinkTransaction); diff --git a/ui/js/component/transactionList/index.js b/ui/js/component/transactionList/index.js index 0b4d0e1af..5a6c10b6b 100644 --- a/ui/js/component/transactionList/index.js +++ b/ui/js/component/transactionList/index.js @@ -1,8 +1,13 @@ import React from "react"; import { connect } from "react-redux"; import { doNavigate } from "actions/navigation"; +import { selectClaimedRewardsByTransactionId } from "selectors/rewards"; import TransactionList from "./view"; +const select = state => ({ + rewards: selectClaimedRewardsByTransactionId(state), +}); + const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), }); diff --git a/ui/js/component/transactionList/internal/TransactionListBody.jsx b/ui/js/component/transactionList/internal/TransactionListBody.jsx deleted file mode 100644 index 6ad795f05..000000000 --- a/ui/js/component/transactionList/internal/TransactionListBody.jsx +++ /dev/null @@ -1,153 +0,0 @@ -import React from "react"; -import LinkTransaction from "component/linkTransaction"; -import { CreditAmount } from "component/common"; - -class TransactionTableBody extends React.PureComponent { - constructor(props) { - super(props); - } - - getClaimLink(claim_name, claim_id) { - let uri = `lbry://${claim_name}#${claim_id}`; - - return ( -
this.props.navigate(uri)}> - {claim_name} - - ); - } - - filterList(transaction) { - if (this.props.filter == "claim") { - return transaction.claim_info.length > 0; - } else if (this.props.filter == "support") { - return transaction.support_info.length > 0; - } else if (this.props.filter == "update") { - return transaction.update_info.length > 0; - } else { - return transaction; - } - } - - renderBody(transaction) { - const txid = transaction.id; - const date = transaction.date; - const fee = transaction.fee; - const filter = this.props.filter; - const options = { - weekday: "short", - year: "2-digit", - month: "short", - day: "numeric", - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - }; - - if (filter == "tipSupport") - transaction["tipSupport_info"] = transaction["support_info"].filter( - tx => tx.is_tip - ); - - return filter != "unfiltered" - ? transaction[`${filter}_info`].map(item => { - return ( - - - {date - ? date.toLocaleDateString("en-US", options) - : - {__("(Transaction pending)")} - } - - - -
- - - - {this.getClaimLink(item.claim_name, item.claim_id)} - - - - - - ); - }) - : - - {date - ? date.toLocaleDateString("en-US", options) - : - {__("(Transaction pending)")} - } - - - -
- - - - - - ; - } - - removeFeeTx(transaction) { - if (this.props.filter == "unfiltered") - return Math.abs(transaction.amount) != Math.abs(transaction.fee); - else return true; - } - - render() { - const { transactions, filter } = this.props; - let transactionList = transactions - .filter(this.filterList, this) - .filter(this.removeFeeTx, this) - .map(this.renderBody, this); - - if (transactionList.length == 0) { - return ( - - - - {__("There are no transactions of this type.")} - - - - ); - } - - return ( - - {transactionList} - - ); - } -} - -export default TransactionTableBody; diff --git a/ui/js/component/transactionList/internal/TransactionListHeader.jsx b/ui/js/component/transactionList/internal/TransactionListHeader.jsx deleted file mode 100644 index 52f735fb9..000000000 --- a/ui/js/component/transactionList/internal/TransactionListHeader.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react"; - -class TransactionTableHeader extends React.PureComponent { - render() { - const { filter } = this.props; - return ( - - - {__("Date")} - {__("Amount(Fee)")} - {filter != "unfiltered" && {__("Claim Name")} } - {__("Transaction")} - - - ); - } -} - -export default TransactionTableHeader; diff --git a/ui/js/component/transactionList/internal/TransactionListItem.jsx b/ui/js/component/transactionList/internal/TransactionListItem.jsx new file mode 100644 index 000000000..2a4ba28ae --- /dev/null +++ b/ui/js/component/transactionList/internal/TransactionListItem.jsx @@ -0,0 +1,78 @@ +import React from "react"; +import LinkTransaction from "component/linkTransaction"; +import { CreditAmount } from "component/common"; +import DateTime from "component/dateTime"; +import Link from "component/link"; +import lbryuri from "lbryuri"; + +class TransactionListItem extends React.PureComponent { + render() { + const { reward, transaction } = this.props; + const { + amount, + claim_id: claimId, + claim_name: name, + date, + fee, + txid, + type, + } = transaction; + + return ( + + + {date + ?
+ +
+ +
+
+ : + {__("(Transaction pending)")} + } + + + +
+ {fee != 0 && + } + + + {type} + + + {reward && + + {__("Reward: %s", reward.reward_title)} + } + {name && + claimId && + + {name} + } + + + + + + ); + } +} + +export default TransactionListItem; diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index ee78e2acc..beb2f8514 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -1,6 +1,5 @@ import React from "react"; -import TransactionTableHeader from "./internal/TransactionListHeader"; -import TransactionTableBody from "./internal/TransactionListBody"; +import TransactionListItem from "./internal/TransactionListItem"; import FormField from "component/formField"; class TransactionList extends React.PureComponent { @@ -8,7 +7,7 @@ class TransactionList extends React.PureComponent { super(props); this.state = { - filter: "unfiltered", + filter: null, }; } @@ -18,45 +17,63 @@ class TransactionList extends React.PureComponent { }); } - handleClaimNameClicked(uri) { - this.props.navigate("/show", { uri }); + filterTransaction(transaction) { + const { filter } = this.state; + + return !filter || filter == transaction.type; } render() { - const { emptyMessage, transactions } = this.props; - const { filter } = this.state; + const { emptyMessage, rewards, transactions } = this.props; - if (!transactions || !transactions.length) { - return ( -
- {emptyMessage || __("No transactions to list.")} -
- ); - } + let transactionList = transactions.filter( + this.filterTransaction.bind(this) + ); return (
- - {__("Filter")} {" "} - - - - - - - - - - - -
+ {(transactionList.length || this.state.filter) && + + {__("Filter")} {" "} + + + + + + + + + + + } + {!transactionList.length && +
+ {emptyMessage || __("No transactions to list.")} +
} + {Boolean(transactionList.length) && + + + + + + + + + + + + {transactionList.map(t => + + )} + +
{__("Date")}{__("Amount (Fee)")}{__("Type")} {__("Details")} {__("Transaction")}
}
); } diff --git a/ui/js/page/discover/view.jsx b/ui/js/page/discover/view.jsx index 5f4138cbf..bc86a9597 100644 --- a/ui/js/page/discover/view.jsx +++ b/ui/js/page/discover/view.jsx @@ -215,11 +215,7 @@ class DiscoverPage extends React.PureComponent { failedToLoad = !fetchingFeaturedUris && !hasContent; return ( -
+
{!hasContent && fetchingFeaturedUris && } diff --git a/ui/js/page/transactionHistory/view.jsx b/ui/js/page/transactionHistory/view.jsx index 8b9f1a90b..2f3a75715 100644 --- a/ui/js/page/transactionHistory/view.jsx +++ b/ui/js/page/transactionHistory/view.jsx @@ -10,18 +10,26 @@ class TransactionHistoryPage extends React.PureComponent { render() { const { fetchingTransactions, transactions } = this.props; + return (
-
+

{__("Transaction History")}

- {fetchingTransactions && - } - {!fetchingTransactions && - } + {fetchingTransactions && !transactions.length + ? + : ""} + {transactions && transactions.length + ? + : ""}
diff --git a/ui/js/reducers/wallet.js b/ui/js/reducers/wallet.js index 7cc53b54a..a4e25b964 100644 --- a/ui/js/reducers/wallet.js +++ b/ui/js/reducers/wallet.js @@ -10,7 +10,7 @@ const buildDraftTransaction = () => ({ const defaultState = { balance: undefined, blocks: {}, - transactions: [], + transactions: {}, fetchingTransactions: false, receiveAddress: address, gettingNewAddress: false, @@ -25,20 +25,16 @@ reducers[types.FETCH_TRANSACTIONS_STARTED] = function(state, action) { }; reducers[types.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { - const oldTransactions = Object.assign({}, state.transactions); - const byId = Object.assign({}, oldTransactions.byId); + let byId = Object.assign({}, state.transactions); + const { transactions } = action.data; transactions.forEach(transaction => { byId[transaction.txid] = transaction; }); - const newTransactions = Object.assign({}, oldTransactions, { - byId: byId, - }); - return Object.assign({}, state, { - transactions: newTransactions, + transactions: byId, fetchingTransactions: false, }); }; diff --git a/ui/js/selectors/rewards.js b/ui/js/selectors/rewards.js index c2a646563..f9fbc4fe4 100644 --- a/ui/js/selectors/rewards.js +++ b/ui/js/selectors/rewards.js @@ -19,6 +19,15 @@ export const selectClaimedRewards = createSelector( byId => Object.values(byId) || [] ); +export const selectClaimedRewardsByTransactionId = createSelector( + selectClaimedRewards, + rewards => + rewards.reduce((map, reward) => { + map[reward.transaction_id] = reward; + return map; + }, {}) +); + export const selectUnclaimedRewards = createSelector( selectUnclaimedRewardsByType, byType => diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index 7469c2f48..fbf63770f 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -7,34 +7,70 @@ export const selectBalance = createSelector( state => state.balance ); -export const selectTransactions = createSelector( - _selectState, - state => state.transactions || {} -); - export const selectTransactionsById = createSelector( - selectTransactions, - transactions => transactions.byId || {} + _selectState, + state => state.transactions ); export const selectTransactionItems = createSelector( selectTransactionsById, byId => { - const transactionItems = []; - const txids = Object.keys(byId); - txids.forEach(txid => { + const items = []; + + Object.keys(byId).forEach(txid => { const tx = byId[txid]; - transactionItems.push({ - id: txid, - date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, - amount: parseFloat(tx.value), - claim_info: tx.claim_info, - support_info: tx.support_info, - update_info: tx.update_info, - fee: tx.fee, - }); + + //ignore dust/fees + if (Math.abs(tx.amount) === Math.abs(tx.fee)) { + return; + } + + let append = []; + + append.push( + ...tx.claim_info.map(item => + Object.assign({}, item, { + type: item.claim_name[0] === "@" ? "channel" : "publish", + }) + ) + ); + append.push( + ...tx.support_info.map(item => + Object.assign({}, item, { type: !item.is_tip ? "support" : "tip" }) + ) + ); + append.push( + ...tx.update_info.map(item => + Object.assign({}, item, { type: "update" }) + ) + ); + + if (!append.length) { + append.push( + Object.assign({}, tx, { + type: tx.value < 0 ? "spend" : "receive", + }) + ); + } + + items.push( + ...append.map(item => { + const amount = parseFloat(item.value || -1 * item.amount); //it's value on a transaction, amount on an outpoint (which has the sign the opposite way) + + return { + txid: txid, + date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, + amount: amount, + fee: amount < 0 ? -1 * tx.fee / append.length : 0, + claim_id: item.claim_id, + claim_name: item.claim_name, + type: item.type || "send", + nout: item.nout, + }; + }) + ); }); - return transactionItems.reverse(); + return items.reverse(); } ); diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index 0f4b13be5..90b3212bc 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -27,6 +27,11 @@ body font-weight: bold; color: var(--color-money); } +.credit-amount--fee +{ + font-size: 0.9em; + color: var(--color-meta-light); +} #main-content { @@ -44,7 +49,8 @@ body width: $width-page-constrained; } } -main.main--refreshing { + +.reloading { &:before { $width: 30px; position: absolute; diff --git a/ui/scss/component/_table.scss b/ui/scss/component/_table.scss index 2e2b664a1..59edeb480 100644 --- a/ui/scss/component/_table.scss +++ b/ui/scss/component/_table.scss @@ -60,3 +60,11 @@ table.table-standard { table.table-stretch { width: 100%; } + +table.table-transactions { + td:nth-of-type(1) { width: 15%; } + td:nth-of-type(2) { width: 15%; } + td:nth-of-type(3) { width: 15%; } + td:nth-of-type(4) { width: 40%; } + td:nth-of-type(5) { width: 15%; } +} \ No newline at end of file From b5dc588e2336a8eaf5313129676b3533d399f985 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 21:03:44 -0400 Subject: [PATCH 102/132] remove unused property --- ui/js/component/common.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/js/component/common.js b/ui/js/component/common.js index 23b195bc6..598e61a31 100644 --- a/ui/js/component/common.js +++ b/ui/js/component/common.js @@ -71,7 +71,6 @@ export class CreditAmount extends React.PureComponent { showFullPrice: React.PropTypes.bool, showPlus: React.PropTypes.bool, look: React.PropTypes.oneOf(["indicator", "plain", "fee"]), - fee: React.PropTypes.bool, }; static defaultProps = { @@ -81,7 +80,6 @@ export class CreditAmount extends React.PureComponent { look: "indicator", showFullPrice: false, showPlus: false, - fee: false, }; render() { From e741d5ee273e2e351d0ef377bb4ef9fc59271178 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 22:08:43 -0400 Subject: [PATCH 103/132] fix pending play issue introduced much earlier in branch --- ui/js/actions/content.js | 55 +++++++++++-------- ui/js/component/fileActions/index.js | 9 --- ui/js/component/fileDownloadLink/index.js | 3 +- ui/js/component/fileDownloadLink/view.jsx | 4 +- ui/js/component/video/index.js | 10 ++-- .../component/video/internal/play-button.jsx | 14 ++--- ui/js/component/video/view.jsx | 28 ++-------- ui/js/constants/action_types.js | 1 + ui/js/modal/modalAffirmPurchase/index.js | 6 +- ui/js/modal/modalAffirmPurchase/view.jsx | 4 +- ui/js/reducers/content.js | 7 +++ ui/js/selectors/content.js | 5 ++ 12 files changed, 67 insertions(+), 79 deletions(-) diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index ed9324f77..a3005a374 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -322,38 +322,29 @@ export function doPurchaseUri(uri) { const downloadingByOutpoint = selectDownloadingByOutpoint(state); const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint]; - - // we already fully downloaded the file. - if (fileInfo && fileInfo.completed) { - // If written_bytes is false that means the user has deleted/moved the - // file manually on their file system, so we need to dispatch a - // doLoadVideo action to reconstruct the file from the blobs - if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri)); - - return Promise.resolve(); - } - - // we are already downloading the file - if (alreadyDownloading) { - return Promise.resolve(); - } - const costInfo = makeSelectCostInfoForUri(uri)(state); const { cost } = costInfo; - // the file is free or we have partially downloaded it - if (cost === 0 || (fileInfo && fileInfo.download_directory)) { - dispatch(doLoadVideo(uri)); - return Promise.resolve(); + if ( + alreadyDownloading || + (fileInfo && fileInfo.completed && fileInfo.written_bytes > 0) + ) { + return; + } + + // we already fully downloaded the file. + if ( + cost === 0 || + (fileInfo && (fileInfo.completed || fileInfo.download_directory)) + ) { + return dispatch(doLoadVideo(uri)); } if (cost > balance) { - dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS)); - } else { - dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri })); + return dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS)); } - return Promise.resolve(); + return dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri })); }; } @@ -420,6 +411,22 @@ export function doFetchClaimListMine() { }; } +export function doPlayUri(uri) { + return function(dispatch, getState) { + dispatch(doSetPlayingUri(uri)); + dispatch(doPurchaseUri(uri)); + }; +} + +export function doSetPlayingUri(uri) { + return function(dispatch, getState) { + dispatch({ + type: types.SET_PLAYING_URI, + data: { uri }, + }); + }; +} + export function doFetchChannelListMine() { return function(dispatch, getState) { dispatch({ diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 75eaeff9a..68597a571 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -3,11 +3,7 @@ import { connect } from "react-redux"; import { makeSelectFileInfoForUri } from "selectors/file_info"; import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doOpenModal } from "actions/app"; -import { doFetchAvailability } from "actions/availability"; -import { doOpenFileInShell } from "actions/file_info"; import { makeSelectClaimIsMine } from "selectors/claims"; -import { doPurchaseUri, doStartDownload } from "actions/content"; -import { doNavigate } from "actions/navigation"; import FileActions from "./view"; const select = (state, props) => ({ @@ -18,12 +14,7 @@ const select = (state, props) => ({ }); const perform = dispatch => ({ - checkAvailability: uri => dispatch(doFetchAvailability(uri)), - navigate: (path, params) => dispatch(doNavigate(path, params)), - openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)), - startDownload: uri => dispatch(doPurchaseUri(uri)), - restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), }); export default connect(select, perform)(FileActions); diff --git a/ui/js/component/fileDownloadLink/index.js b/ui/js/component/fileDownloadLink/index.js index f9657f17b..9843a1701 100644 --- a/ui/js/component/fileDownloadLink/index.js +++ b/ui/js/component/fileDownloadLink/index.js @@ -23,8 +23,7 @@ const select = (state, props) => ({ const perform = dispatch => ({ checkAvailability: uri => dispatch(doFetchAvailability(uri)), openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), - startDownload: uri => - dispatch(doPurchaseUri(uri, modals.CONFIRM_FILE_PURCHASE)), + purchaseUri: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), }); diff --git a/ui/js/component/fileDownloadLink/view.jsx b/ui/js/component/fileDownloadLink/view.jsx index 82bae5b8a..1a0a8dc1c 100644 --- a/ui/js/component/fileDownloadLink/view.jsx +++ b/ui/js/component/fileDownloadLink/view.jsx @@ -39,7 +39,7 @@ class FileDownloadLink extends React.PureComponent { downloading, uri, openInShell, - startDownload, + purchaseUri, costInfo, loading, } = this.props; @@ -81,7 +81,7 @@ class FileDownloadLink extends React.PureComponent { label={__("Download")} icon="icon-download" onClick={() => { - startDownload(uri); + purchaseUri(uri); }} /> ); diff --git a/ui/js/component/video/index.js b/ui/js/component/video/index.js index 36eeb3168..160816cef 100644 --- a/ui/js/component/video/index.js +++ b/ui/js/component/video/index.js @@ -1,9 +1,8 @@ import React from "react"; import { connect } from "react-redux"; -import { doCloseModal } from "actions/app"; import { doChangeVolume } from "actions/app"; -import { selectCurrentModal, selectVolume } from "selectors/app"; -import { doPurchaseUri, doLoadVideo } from "actions/content"; +import { selectVolume } from "selectors/app"; +import { doPlayUri } from "actions/content"; import { makeSelectMetadataForUri, makeSelectContentTypeForUri, @@ -16,6 +15,7 @@ import { import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { selectShowNsfw } from "selectors/settings"; import Video from "./view"; +import { selectPlayingUri } from "selectors/content"; const select = (state, props) => ({ costInfo: makeSelectCostInfoForUri(props.uri)(state), @@ -24,13 +24,13 @@ const select = (state, props) => ({ obscureNsfw: !selectShowNsfw(state), isLoading: makeSelectLoadingForUri(props.uri)(state), isDownloading: makeSelectDownloadingForUri(props.uri)(state), + playingUri: selectPlayingUri(state), contentType: makeSelectContentTypeForUri(props.uri)(state), volume: selectVolume(state), }); const perform = dispatch => ({ - loadVideo: uri => dispatch(doLoadVideo(uri)), - purchaseUri: uri => dispatch(doPurchaseUri(uri)), + play: uri => dispatch(doPlayUri(uri)), changeVolume: volume => dispatch(doChangeVolume(volume)), }); diff --git a/ui/js/component/video/internal/play-button.jsx b/ui/js/component/video/internal/play-button.jsx index 23f9259aa..73905f298 100644 --- a/ui/js/component/video/internal/play-button.jsx +++ b/ui/js/component/video/internal/play-button.jsx @@ -17,18 +17,12 @@ class VideoPlayButton extends React.PureComponent { "Space" === event.code ) { event.preventDefault(); - this.onWatchClick(); + this.watch(); } } - onWatchClick() { - this.props.purchaseUri(this.props.uri).then(() => { - if (!this.props.modal) { - this.props.startPlaying(); - } else { - alert("fix me set pending play"); - } - }); + watch() { + this.props.play(this.props.uri); } render() { @@ -54,7 +48,7 @@ class VideoPlayButton extends React.PureComponent { label={label ? label : ""} className="video__play-button" icon={icon} - onClick={this.onWatchClick.bind(this)} + onClick={() => this.watch()} /> ); } diff --git a/ui/js/component/video/view.jsx b/ui/js/component/video/view.jsx index 4e396ddd4..0e6c35c6a 100644 --- a/ui/js/component/video/view.jsx +++ b/ui/js/component/video/view.jsx @@ -9,22 +9,10 @@ class Video extends React.PureComponent { constructor(props) { super(props); this.state = { - isPlaying: false, showNsfwHelp: false, }; } - componentWillReceiveProps(nextProps) { - // reset playing state upon change path action - if ( - !this.isMediaSame(nextProps) && - this.props.fileInfo && - this.state.isPlaying - ) { - this.state.isPlaying = false; - } - } - isMediaSame(nextProps) { return ( this.props.fileInfo && @@ -33,12 +21,6 @@ class Video extends React.PureComponent { ); } - startPlaying() { - this.setState({ - isPlaying: true, - }); - } - handleMouseOver() { if ( this.props.obscureNsfw && @@ -64,13 +46,15 @@ class Video extends React.PureComponent { metadata, isLoading, isDownloading, + playingUri, fileInfo, contentType, changeVolume, volume, + uri, } = this.props; - const { isPlaying = false } = this.state; + const isPlaying = playingUri === uri; const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0; const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; const mediaType = lbry.getMediaType( @@ -129,11 +113,7 @@ class Video extends React.PureComponent { className="video__cover" style={{ backgroundImage: 'url("' + metadata.thumbnail + '")' }} > - + } {this.state.showNsfwHelp && } diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index a4cb1afaa..140509461 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -70,6 +70,7 @@ export const CREATE_CHANNEL_COMPLETED = "CREATE_CHANNEL_COMPLETED"; export const PUBLISH_STARTED = "PUBLISH_STARTED"; export const PUBLISH_COMPLETED = "PUBLISH_COMPLETED"; export const PUBLISH_FAILED = "PUBLISH_FAILED"; +export const SET_PLAYING_URI = "PLAY_URI"; // Files export const FILE_LIST_STARTED = "FILE_LIST_STARTED"; diff --git a/ui/js/modal/modalAffirmPurchase/index.js b/ui/js/modal/modalAffirmPurchase/index.js index c42afc373..d0f4affa2 100644 --- a/ui/js/modal/modalAffirmPurchase/index.js +++ b/ui/js/modal/modalAffirmPurchase/index.js @@ -1,7 +1,7 @@ import React from "react"; import { connect } from "react-redux"; import { doCloseModal } from "actions/app"; -import { doLoadVideo } from "actions/content"; +import { doLoadVideo, doSetPlayingUri } from "actions/content"; import { makeSelectMetadataForUri } from "selectors/claims"; import ModalAffirmPurchase from "./view"; @@ -10,6 +10,10 @@ const select = (state, props) => ({ }); const perform = dispatch => ({ + cancelPurchase: () => { + dispatch(doSetPlayingUri(null)); + dispatch(doCloseModal()); + }, closeModal: () => dispatch(doCloseModal()), loadVideo: uri => dispatch(doLoadVideo(uri)), }); diff --git a/ui/js/modal/modalAffirmPurchase/view.jsx b/ui/js/modal/modalAffirmPurchase/view.jsx index a38e82f1c..96dd6c1c9 100644 --- a/ui/js/modal/modalAffirmPurchase/view.jsx +++ b/ui/js/modal/modalAffirmPurchase/view.jsx @@ -9,7 +9,7 @@ class ModalAffirmPurchase extends React.PureComponent { } render() { - const { closeModal, metadata: { title }, uri } = this.props; + const { cancelPurchase, metadata: { title }, uri } = this.props; return ( {__("This will purchase")} {title} {__("for")}{" "} diff --git a/ui/js/reducers/content.js b/ui/js/reducers/content.js index 9d8c5867e..8cb2eae2c 100644 --- a/ui/js/reducers/content.js +++ b/ui/js/reducers/content.js @@ -2,6 +2,7 @@ import * as types from "constants/action_types"; const reducers = {}; const defaultState = { + playingUri: null, rewardedContentClaimIds: [], channelPages: {}, }; @@ -58,6 +59,12 @@ reducers[types.RESOLVE_URI_CANCELED] = reducers[ }); }; +reducers[types.SET_PLAYING_URI] = (state, action) => { + return Object.assign({}, state, { + playingUri: action.data.uri, + }); +}; + // reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { // const channelPages = Object.assign({}, state.channelPages); // const { uri, claims } = action.data; diff --git a/ui/js/selectors/content.js b/ui/js/selectors/content.js index e8c0d42cc..0818134de 100644 --- a/ui/js/selectors/content.js +++ b/ui/js/selectors/content.js @@ -17,6 +17,11 @@ export const selectResolvingUris = createSelector( state => state.resolvingUris || [] ); +export const selectPlayingUri = createSelector( + _selectState, + state => state.playingUri +); + export const makeSelectIsUriResolving = uri => { return createSelector( selectResolvingUris, From 2dfd071e166c9e036605ed3def0a21ca7031ddbf Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 22:13:05 -0400 Subject: [PATCH 104/132] cancel play on navigate away --- ui/js/component/video/index.js | 3 ++- ui/js/component/video/view.jsx | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/js/component/video/index.js b/ui/js/component/video/index.js index 160816cef..3c80869dc 100644 --- a/ui/js/component/video/index.js +++ b/ui/js/component/video/index.js @@ -2,7 +2,7 @@ import React from "react"; import { connect } from "react-redux"; import { doChangeVolume } from "actions/app"; import { selectVolume } from "selectors/app"; -import { doPlayUri } from "actions/content"; +import { doPlayUri, doSetPlayingUri } from "actions/content"; import { makeSelectMetadataForUri, makeSelectContentTypeForUri, @@ -31,6 +31,7 @@ const select = (state, props) => ({ const perform = dispatch => ({ play: uri => dispatch(doPlayUri(uri)), + cancelPlay: () => dispatch(doSetPlayingUri(null)), changeVolume: volume => dispatch(doChangeVolume(volume)), }); diff --git a/ui/js/component/video/view.jsx b/ui/js/component/video/view.jsx index 0e6c35c6a..fb1bd3420 100644 --- a/ui/js/component/video/view.jsx +++ b/ui/js/component/video/view.jsx @@ -13,6 +13,10 @@ class Video extends React.PureComponent { }; } + componentWillUnmount() { + this.props.cancelPlay(); + } + isMediaSame(nextProps) { return ( this.props.fileInfo && From 3e4aea3a15101ab9a3ce611d1f49dc4551e8e9c2 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Sun, 17 Sep 2017 22:14:48 -0400 Subject: [PATCH 105/132] lost theming in changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29596e25b..a7def3512 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,13 +10,14 @@ Web UI version numbers should always match the corresponding version of LBRY App ### Added * Added a tipping button to send LBRY Credits to a creator. * Added an edit button on published content. Significantly improved UX for editing claims. + * Added theme settings option and new Dark theme. * Significantly more detail is shown about past transactions and new filtering options for transactions. * File pages now show the time of a publish. * The "auth token" displayable on Help offers security warning * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. ### Changed - * + * CSS significantly refactored to support CSS vars (and consequently easy theming). ### Fixed * URLs on cards no longer wrap and show an ellipsis if longer than one line From 4866fa8b84a40d35b6e9ab54a7667311ef7f7aae Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 18 Sep 2017 17:42:11 -0400 Subject: [PATCH 106/132] update to daemon v0.16.0 proper, fix bug on new publishes --- app/package.json | 2 +- ui/js/reducers/claims.js | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/package.json b/app/package.json index ec2657777..106c7e7c8 100644 --- a/app/package.json +++ b/app/package.json @@ -20,7 +20,7 @@ "electron-rebuild": "^1.5.11" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.16.0rc9", + "lbrynetDaemonVersion": "0.16.0", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip" }, "license": "MIT" diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js index f18433cdc..7f883a4ea 100644 --- a/ui/js/reducers/claims.js +++ b/ui/js/reducers/claims.js @@ -50,21 +50,23 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) { .filter(claimId => Object.keys(abandoningById).indexOf(claimId) === -1) ); - claims.filter(claim => claim.category.match(/claim/)).forEach(claim => { - byId[claim.claim_id] = claim; + claims + .filter(claim => claim.category && claim.category.match(/claim/)) + .forEach(claim => { + byId[claim.claim_id] = claim; - const pending = Object.values(pendingById).find(pendingClaim => { - return ( - pendingClaim.name == claim.name && - pendingClaim.channel_name == claim.channel_name - ); + const pending = Object.values(pendingById).find(pendingClaim => { + return ( + pendingClaim.name == claim.name && + pendingClaim.channel_name == claim.channel_name + ); + }); + + if (pending) { + delete pendingById[pending.claim_id]; + } }); - if (pending) { - delete pendingById[pending.claim_id]; - } - }); - // Remove old timed out pending publishes const old = Object.values(pendingById) .filter(pendingClaim => Date.now() - pendingClaim.time >= 20 * 60 * 1000) From abb83c17edbb894c959fd4efc088e5d05116d5b7 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 18 Sep 2017 17:49:41 -0400 Subject: [PATCH 107/132] =?UTF-8?q?Bump=20version:=200.15.1=20=E2=86=92=20?= =?UTF-8?q?0.16.0rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b00c73445..c51a07f98 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.15.1 +current_version = 0.16.0rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index 106c7e7c8..a30268ed2 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.15.1", + "version": "0.16.0rc1", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index c0e6e73b5..b389c431a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.15.1", + "version": "0.16.0rc1", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From b7b885169838df5f7a794f946a7d56e8d43524df Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 10 Sep 2017 19:25:24 -0600 Subject: [PATCH 108/132] fix #542 implement submit component fix weird behaviour in wallet send prevent refresh on enter key fix wallet send -> submit handler implement form component fix conflicts remove unused files better submit handler better validation for walletSend prevent / remove missign parameters error (popup) minor fix minor fix for submit validation in walletSend --- ui/js/component/form.js | 44 +++++++++ ui/js/component/inviteNew/view.jsx | 22 ++--- ui/js/component/publishForm/view.jsx | 27 ++---- ui/js/component/userEmailNew/view.jsx | 25 ++---- ui/js/component/userEmailVerify/view.jsx | 25 ++---- ui/js/component/walletSend/view.jsx | 109 +++++++++++++---------- ui/scss/_gui.scss | 1 + ui/scss/component/_button.scss | 6 ++ 8 files changed, 142 insertions(+), 117 deletions(-) diff --git a/ui/js/component/form.js b/ui/js/component/form.js index 4b353eb94..668146388 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -1,5 +1,6 @@ import React from "react"; import FormField from "component/formField"; +import { Icon } from "component/common.js"; let formFieldCounter = 0; @@ -9,6 +10,25 @@ export function formFieldId() { return "form-field-" + ++formFieldCounter; } +export class Form extends React.PureComponent { + constructor(props) { + super(props); + } + + handleSubmit(event) { + event.preventDefault(); + this.props.onSubmit(); + } + + render() { + return ( + this.handleSubmit(event)}> + {this.props.children} + + ); + } +} + export class FormRow extends React.PureComponent { static propTypes = { label: React.PropTypes.oneOfType([ @@ -131,3 +151,27 @@ export class FormRow extends React.PureComponent { ); } } + +export const Submit = props => { + const { title, label, icon, disabled } = props; + + const className = + "button-block" + + " button-primary" + + " button-set-item" + + " button--submit" + + (disabled ? " disabled" : ""); + + const content = ( + + {"icon" in props ? : null} + {label ? {label} : null} + + ); + + return ( + + ); +}; diff --git a/ui/js/component/inviteNew/view.jsx b/ui/js/component/inviteNew/view.jsx index 3f37e9c1b..af15a5fd2 100644 --- a/ui/js/component/inviteNew/view.jsx +++ b/ui/js/component/inviteNew/view.jsx @@ -1,7 +1,6 @@ import React from "react"; import { BusyMessage, CreditAmount } from "component/common"; -import Link from "component/link"; -import { FormRow } from "component/form.js"; +import { Form, FormRow, Submit } from "component/form.js"; class FormInviteNew extends React.PureComponent { constructor(props) { @@ -18,16 +17,16 @@ class FormInviteNew extends React.PureComponent { }); } - handleSubmit(event) { - event.preventDefault(); - this.props.inviteNew(this.state.email); + handleSubmit() { + const { email } = this.state; + this.props.inviteNew(email); } render() { const { errorMessage, isPending } = this.props; return ( -
+
- { - this.handleSubmit(event); - }} - /> +
- + ); } } diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index 4da552459..b502f4add 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -2,7 +2,7 @@ import React from "react"; import lbry from "lbry"; import lbryuri from "lbryuri"; import FormField from "component/formField"; -import { FormRow } from "component/form.js"; +import { Form, FormRow, Submit } from "component/form.js"; import Link from "component/link"; import FormFieldPrice from "component/formFieldPrice"; import Modal from "modal/modal"; @@ -59,11 +59,7 @@ class PublishForm extends React.PureComponent { if (!fetchingChannels) fetchChannelListMine(); } - handleSubmit(event) { - if (typeof event !== "undefined") { - event.preventDefault(); - } - + handleSubmit() { this.setState({ submitting: true, }); @@ -534,11 +530,7 @@ class PublishForm extends React.PureComponent { return (
-
{ - this.handleSubmit(event); - }} - > +

{__("Content")}

@@ -872,12 +864,10 @@ class PublishForm extends React.PureComponent {
- { - this.handleSubmit(event); - }} + -
-
+ { - this.handleSubmit(event); - }} - > +

{__( "This process is required to prevent abuse of the rewards program." @@ -53,16 +49,9 @@ class UserEmailNew extends React.PureComponent { }} />

- { - this.handleSubmit(event); - }} - /> +
-
+ ); } } diff --git a/ui/js/component/userEmailVerify/view.jsx b/ui/js/component/userEmailVerify/view.jsx index 47ed10bc9..1ec92202e 100644 --- a/ui/js/component/userEmailVerify/view.jsx +++ b/ui/js/component/userEmailVerify/view.jsx @@ -1,6 +1,6 @@ import React from "react"; import Link from "component/link"; -import { FormRow } from "component/form.js"; +import { Form, FormRow, Submit } from "component/form.js"; class UserEmailVerify extends React.PureComponent { constructor(props) { @@ -17,19 +17,15 @@ class UserEmailVerify extends React.PureComponent { }); } - handleSubmit(event) { - event.preventDefault(); - this.props.verifyUserEmail(this.state.code); + handleSubmit() { + const { code } = this.state; + this.props.verifyUserEmail(code); } render() { const { errorMessage, isPending } = this.props; return ( -
{ - this.handleSubmit(event); - }} - > +

{__("Please enter the verification code emailed to you.")}

- { - this.handleSubmit(event); - }} - /> +
- + ); } } diff --git a/ui/js/component/walletSend/view.jsx b/ui/js/component/walletSend/view.jsx index adaf9ad84..00beb2a86 100644 --- a/ui/js/component/walletSend/view.jsx +++ b/ui/js/component/walletSend/view.jsx @@ -1,54 +1,69 @@ import React from "react"; -import Link from "component/link"; -import { FormRow } from "component/form"; +import { Form, FormRow, Submit } from "component/form"; import lbryuri from "lbryuri"; -const WalletSend = props => { - const { sendToAddress, setAmount, setAddress, amount, address } = props; +class WalletSend extends React.PureComponent { + handleSubmit() { + const { amount, address, sendToAddress } = this.props; + const validSubmit = parseFloat(amount) > 0.0 && address; - return ( -
-
-
-

{__("Send Credits")}

-
-
- -
-
- -
- 0.0) || !address} - /> - + if (validSubmit) { + sendToAddress(); + } + } + + render() { + const { + closeModal, + modal, + setAmount, + setAddress, + amount, + address, + error, + } = this.props; + + return ( +
+ +
+

{__("Send Credits")}

-
- -
- ); -}; +
+ +
+
+ +
+ 0.0) || !address} + /> +
+
+ +
+ ); + } +} export default WalletSend; diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index 90b3212bc..9ca64b4e5 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -3,6 +3,7 @@ html height: 100%; font-size: var(--font-size); } + body { color: var(--text-color); diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss index 28075c123..acc67e0aa 100644 --- a/ui/scss/component/_button.scss +++ b/ui/scss/component/_button.scss @@ -86,3 +86,9 @@ $button-focus-shift: 12%; { box-shadow: none !important; } + +.button--submit { + font-family: inherit; + font-size: inherit; + line-height: 0; +} From cfcdbd48f1367a730c45783826508de8c087ce3d Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 18 Sep 2017 18:16:00 -0400 Subject: [PATCH 109/132] add required prop type --- ui/js/component/form.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/js/component/form.js b/ui/js/component/form.js index 668146388..7eaac87e4 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -11,6 +11,10 @@ export function formFieldId() { } export class Form extends React.PureComponent { + static propTypes = { + onSubmit: React.PropTypes.func.isRequired, + }; + constructor(props) { super(props); } From ae512ea68e83319680f12dd67f4d8da4bd9cd118 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 18 Sep 2017 18:17:01 -0400 Subject: [PATCH 110/132] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7def3512..3d6c73333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * File pages now show the time of a publish. * The "auth token" displayable on Help offers security warning * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. + * Added a `Form` component, to further progress towards form sanity. ### Changed * CSS significantly refactored to support CSS vars (and consequently easy theming). From 2746627fb15f617725192a51cc8f6ba4f053915a Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 08:47:08 -0400 Subject: [PATCH 111/132] fix availability issue and restore open in folder --- ui/js/actions/availability.js | 5 +++++ ui/js/actions/file_info.js | 10 +++++----- ui/js/component/fileDetails/index.js | 9 ++++++++- ui/js/component/fileDetails/view.jsx | 23 ++++++++++++++++++++++- ui/js/component/fileDownloadLink/index.js | 3 +-- ui/js/component/fileDownloadLink/view.jsx | 2 +- ui/js/page/show/view.jsx | 1 + 7 files changed, 43 insertions(+), 10 deletions(-) diff --git a/ui/js/actions/availability.js b/ui/js/actions/availability.js index 2c7cbc3cb..4cde9d2ed 100644 --- a/ui/js/actions/availability.js +++ b/ui/js/actions/availability.js @@ -4,6 +4,11 @@ import { selectFetchingAvailability } from "selectors/availability"; export function doFetchAvailability(uri) { return function(dispatch, getState) { + /* + this is disabled atm - Jeremy + */ + return; + const state = getState(); const alreadyFetching = !!selectFetchingAvailability(state)[uri]; diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js index eb317e484..49c949e5c 100644 --- a/ui/js/actions/file_info.js +++ b/ui/js/actions/file_info.js @@ -71,18 +71,18 @@ export function doFileList() { }; } -export function doOpenFileInShell(fileInfo) { +export function doOpenFileInShell(path) { return function(dispatch, getState) { - const success = shell.openItem(fileInfo.download_path); + const success = shell.openItem(path); if (!success) { - dispatch(doOpenFileInFolder(fileInfo)); + dispatch(doOpenFileInFolder(path)); } }; } -export function doOpenFileInFolder(fileInfo) { +export function doOpenFileInFolder(path) { return function(dispatch, getState) { - shell.showItemInFolder(fileInfo.download_path); + shell.showItemInFolder(path); }; } diff --git a/ui/js/component/fileDetails/index.js b/ui/js/component/fileDetails/index.js index 385959ed2..738746d0a 100644 --- a/ui/js/component/fileDetails/index.js +++ b/ui/js/component/fileDetails/index.js @@ -6,11 +6,18 @@ import { makeSelectMetadataForUri, } from "selectors/claims"; import FileDetails from "./view"; +import { doOpenFileInFolder } from "actions/file_info"; +import { makeSelectFileInfoForUri } from "selectors/file_info"; const select = (state, props) => ({ claim: makeSelectClaimForUri(props.uri)(state), contentType: makeSelectContentTypeForUri(props.uri)(state), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state), }); -export default connect(select, null)(FileDetails); +const perform = dispatch => ({ + openFolder: path => dispatch(doOpenFileInFolder(path)), +}); + +export default connect(select, perform)(FileDetails); diff --git a/ui/js/component/fileDetails/view.jsx b/ui/js/component/fileDetails/view.jsx index dfcc47699..c2cfda468 100644 --- a/ui/js/component/fileDetails/view.jsx +++ b/ui/js/component/fileDetails/view.jsx @@ -5,9 +5,18 @@ import FileActions from "component/fileActions"; import Link from "component/link"; import DateTime from "component/dateTime"; +const path = require("path"); + class FileDetails extends React.PureComponent { render() { - const { claim, contentType, metadata, uri } = this.props; + const { + claim, + contentType, + fileInfo, + metadata, + openFolder, + uri, + } = this.props; if (!claim || !metadata) { return ( @@ -20,6 +29,9 @@ class FileDetails extends React.PureComponent { const { description, language, license } = metadata; const { height } = claim; const mediaType = lbry.getMediaType(contentType); + const directory = fileInfo && fileInfo.download_path + ? path.dirname(fileInfo.download_path) + : null; return (
@@ -47,6 +59,15 @@ class FileDetails extends React.PureComponent { {__("License")}{license} + {directory && + + {__("Downloaded to")} + + openFolder(directory)}> + {directory} + + + }

diff --git a/ui/js/component/fileDownloadLink/index.js b/ui/js/component/fileDownloadLink/index.js index 9843a1701..2131b5f78 100644 --- a/ui/js/component/fileDownloadLink/index.js +++ b/ui/js/component/fileDownloadLink/index.js @@ -10,7 +10,6 @@ import { doFetchAvailability } from "actions/availability"; import { doOpenFileInShell } from "actions/file_info"; import { doPurchaseUri, doStartDownload } from "actions/content"; import FileDownloadLink from "./view"; -import * as modals from "constants/modal_types"; const select = (state, props) => ({ fileInfo: makeSelectFileInfoForUri(props.uri)(state), @@ -22,7 +21,7 @@ const select = (state, props) => ({ const perform = dispatch => ({ checkAvailability: uri => dispatch(doFetchAvailability(uri)), - openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), + openInShell: path => dispatch(doOpenFileInShell(path)), purchaseUri: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), }); diff --git a/ui/js/component/fileDownloadLink/view.jsx b/ui/js/component/fileDownloadLink/view.jsx index 1a0a8dc1c..49c6c29ce 100644 --- a/ui/js/component/fileDownloadLink/view.jsx +++ b/ui/js/component/fileDownloadLink/view.jsx @@ -92,7 +92,7 @@ class FileDownloadLink extends React.PureComponent { label={__("Open")} button="text" icon="icon-external-link-square" - onClick={() => openInShell(fileInfo)} + onClick={() => openInShell(fileInfo.download_path)} /> ); } diff --git a/ui/js/page/show/view.jsx b/ui/js/page/show/view.jsx index 679626d28..8b1e05789 100644 --- a/ui/js/page/show/view.jsx +++ b/ui/js/page/show/view.jsx @@ -36,6 +36,7 @@ class ShowPage extends React.PureComponent { message={__("Loading magic decentralized data...")} />} {claim === null && + !isResolvingUri && {__("There's nothing at this location.")} } From ef882b40b8baa50beb76a5f4468008aa7f53bd08 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 08:47:55 -0400 Subject: [PATCH 112/132] =?UTF-8?q?Bump=20version:=200.16.0rc1=20=E2=86=92?= =?UTF-8?q?=200.16.0rc2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c51a07f98..3875c5bda 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc1 +current_version = 0.16.0rc2 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index a30268ed2..8159c626c 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc1", + "version": "0.16.0rc2", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index b389c431a..1d2e3280b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc1", + "version": "0.16.0rc2", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From 4553418f988e4ecccb6d7e8f1cd5b80dc3fb6010 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 09:38:24 -0400 Subject: [PATCH 113/132] remove dependency on lighthouse for size --- ui/js/actions/cost_info.js | 2 +- ui/js/lbry.js | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/ui/js/actions/cost_info.js b/ui/js/actions/cost_info.js index 6568a3575..06044633a 100644 --- a/ui/js/actions/cost_info.js +++ b/ui/js/actions/cost_info.js @@ -45,7 +45,7 @@ export function doFetchCostInfoForUri(uri) { } else if (fee.currency == "LBC") { resolve({ cost: fee.amount, includesData: true }); } else { - begin(); + // begin(); lbryio.getExchangeRates().then(({ lbc_usd }) => { resolve({ cost: fee.amount / lbc_usd, includesData: true }); }); diff --git a/ui/js/lbry.js b/ui/js/lbry.js index a0b270647..bbdfd1962 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -207,24 +207,12 @@ lbry.getCostInfo = function(uri) { return resolve(costInfoCache[uri]); } - function getCost(uri, size) { - lbry - .stream_cost_estimate({ uri, ...(size !== null ? { size } : {}) }) - .then(cost => { - cacheAndResolve(cost, size !== null); - }, reject); - } - const uriObj = lbryuri.parse(uri); const name = uriObj.path || uriObj.name; - lighthouse.get_size_for_name(name).then(size => { - if (size) { - getCost(name, size); - } else { - getCost(name, null); - } - }); + lbry.stream_cost_estimate({ uri }).then(cost => { + cacheAndResolve(cost, size !== null); + }, reject); }); } return lbry.costPromiseCache[uri]; From 13074fef0c32be81794f6b734c7766283da492f4 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 09:43:49 -0400 Subject: [PATCH 114/132] no data is included --- ui/js/lbry.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/js/lbry.js b/ui/js/lbry.js index bbdfd1962..5ad0671b8 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -193,7 +193,8 @@ lbry.getCostInfo = function(uri) { const COST_INFO_CACHE_KEY = "cost_info_cache"; let costInfoCache = getSession(COST_INFO_CACHE_KEY, {}); - function cacheAndResolve(cost, includesData) { + function cacheAndResolve(cost) { + const includesData = false; costInfoCache[uri] = { cost, includesData }; setSession(COST_INFO_CACHE_KEY, costInfoCache); resolve({ cost, includesData }); @@ -211,7 +212,7 @@ lbry.getCostInfo = function(uri) { const name = uriObj.path || uriObj.name; lbry.stream_cost_estimate({ uri }).then(cost => { - cacheAndResolve(cost, size !== null); + cacheAndResolve(cost); }, reject); }); } From 2a15331e8844d191fcfbec8de2a77e4d19b71150 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 09:43:59 -0400 Subject: [PATCH 115/132] =?UTF-8?q?Bump=20version:=200.16.0rc2=20=E2=86=92?= =?UTF-8?q?=200.16.0rc3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 3875c5bda..60f014c32 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc2 +current_version = 0.16.0rc3 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index 8159c626c..62a0e1350 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc2", + "version": "0.16.0rc3", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index 1d2e3280b..acacd985a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc2", + "version": "0.16.0rc3", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From 16bc650d6a61d46066c62d807cd1b0236ec5753c Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 10:39:51 -0400 Subject: [PATCH 116/132] fix sign on some transaction outpoints --- ui/js/selectors/wallet.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index fbf63770f..8aafcf6dc 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -55,7 +55,11 @@ export const selectTransactionItems = createSelector( items.push( ...append.map(item => { - const amount = parseFloat(item.value || -1 * item.amount); //it's value on a transaction, amount on an outpoint (which has the sign the opposite way) + //value on transaction, amount on outpoint + //amount is always positive, but should match sign of value + const amount = parseFloat( + item.value || (item.value < 0 ? -1 : 1) * item.amount + ); return { txid: txid, From a22a77363383b8da2642878d956b48f26c7a8784 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 10:57:43 -0400 Subject: [PATCH 117/132] fix channel pagination --- ui/js/page/channel/view.jsx | 2 +- ui/js/selectors/claims.js | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/js/page/channel/view.jsx b/ui/js/page/channel/view.jsx index 617ef84ba..45db54e4c 100644 --- a/ui/js/page/channel/view.jsx +++ b/ui/js/page/channel/view.jsx @@ -25,7 +25,7 @@ class ChannelPage extends React.PureComponent { } changePage(pageNumber) { - const { params, currentPage } = this.props; + const { params } = this.props; const newParams = Object.assign({}, params, { page: pageNumber }); this.props.navigate("/show", newParams); diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 61fd5fdc2..9c63369fe 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -1,6 +1,7 @@ import { createSelector } from "reselect"; import { selectCurrentParams } from "selectors/navigation"; import lbryuri from "lbryuri"; +import { makeSelectCurrentParam } from "./navigation"; const _selectState = state => state.claims || {}; @@ -72,11 +73,14 @@ export const makeSelectFetchingChannelClaims = uri => { ); }; -export const makeSelectClaimsInChannelForCurrentPage = (uri, page = 1) => { +export const makeSelectClaimsInChannelForCurrentPage = uri => { + const pageSelector = makeSelectCurrentParam("page"); + return createSelector( selectClaimsById, selectAllClaimsByChannel, - (byId, allClaims) => { + pageSelector, + (byId, allClaims, page) => { const byChannel = allClaims[uri] || {}; const claimIds = byChannel[page]; From 33c51588189660284dcf77f479ead5b8eb28ad85 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 13:12:53 -0400 Subject: [PATCH 118/132] channel navigation fixes --- app/package.json | 2 +- ui/js/actions/content.js | 2 +- ui/js/page/channel/index.js | 11 ++++++----- ui/js/page/channel/view.jsx | 9 ++++----- ui/js/page/file/index.js | 2 +- ui/js/reducers/content.js | 2 +- ui/js/selectors/claims.js | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/package.json b/app/package.json index 62a0e1350..eae996ea7 100644 --- a/app/package.json +++ b/app/package.json @@ -20,7 +20,7 @@ "electron-rebuild": "^1.5.11" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.16.0", + "lbrynetDaemonVersion": "0.16.1rc1", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip" }, "license": "MIT" diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index a3005a374..eb62506a2 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -355,7 +355,7 @@ export function doFetchClaimsByChannel(uri, page) { data: { uri, page }, }); - lbry.claim_list_by_channel({ uri, page }).then(result => { + lbry.claim_list_by_channel({ uri, page: page || 1 }).then(result => { const claimResult = result[uri], claims = claimResult ? claimResult.claims_in_channel : [], currentPage = claimResult ? claimResult.returned_page : undefined; diff --git a/ui/js/page/channel/index.js b/ui/js/page/channel/index.js index a407f8c48..f69d5b15e 100644 --- a/ui/js/page/channel/index.js +++ b/ui/js/page/channel/index.js @@ -9,18 +9,19 @@ import { makeSelectClaimsInChannelForCurrentPage, makeSelectFetchingChannelClaims, } from "selectors/claims"; -import { selectCurrentParams } from "selectors/navigation"; +import { + makeSelectCurrentParam, + selectCurrentParams, +} from "selectors/navigation"; import { doNavigate } from "actions/navigation"; import { makeSelectTotalPagesForChannel } from "selectors/content"; import ChannelPage from "./view"; const select = (state, props) => ({ claim: makeSelectClaimForUri(props.uri)(state), - claimsInChannel: makeSelectClaimsInChannelForCurrentPage( - props.uri, - props.page - )(state), + claimsInChannel: makeSelectClaimsInChannelForCurrentPage(props.uri)(state), fetching: makeSelectFetchingChannelClaims(props.uri)(state), + page: makeSelectCurrentParam("page")(state), params: selectCurrentParams(state), totalPages: makeSelectTotalPagesForChannel(props.uri)(state), }); diff --git a/ui/js/page/channel/view.jsx b/ui/js/page/channel/view.jsx index 45db54e4c..f7ccd1c8f 100644 --- a/ui/js/page/channel/view.jsx +++ b/ui/js/page/channel/view.jsx @@ -2,7 +2,6 @@ import React from "react"; import lbryuri from "lbryuri"; import { BusyMessage } from "component/common"; import FileTile from "component/fileTile"; -import Link from "component/link"; import ReactPaginate from "react-paginate"; class ChannelPage extends React.PureComponent { @@ -16,7 +15,7 @@ class ChannelPage extends React.PureComponent { componentWillReceiveProps(nextProps) { const { page, uri, fetching, fetchClaims, fetchClaimCount } = this.props; - if (fetching !== nextProps.page && page !== nextProps.page) { + if (nextProps.page && page !== nextProps.page) { fetchClaims(nextProps.uri, nextProps.page); } if (nextProps.uri != uri) { @@ -42,10 +41,10 @@ class ChannelPage extends React.PureComponent { } = this.props; let contentList; - if (claimsInChannel === undefined) { + if (fetching) { contentList = ; - } else if (claimsInChannel) { - contentList = claimsInChannel.length + } else { + contentList = claimsInChannel && claimsInChannel.length ? claimsInChannel.map(claim => ({ claim: makeSelectClaimForUri(props.uri)(state), diff --git a/ui/js/reducers/content.js b/ui/js/reducers/content.js index 8cb2eae2c..56195e917 100644 --- a/ui/js/reducers/content.js +++ b/ui/js/reducers/content.js @@ -80,7 +80,7 @@ reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) { const channelPages = Object.assign({}, state.channelPages); const { uri, totalClaims } = action.data; - channelPages[uri] = totalClaims / 10; + channelPages[uri] = Math.ceil(totalClaims / 10); return Object.assign({}, state, { channelPages, diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 9c63369fe..34c4ea688 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -82,7 +82,7 @@ export const makeSelectClaimsInChannelForCurrentPage = uri => { pageSelector, (byId, allClaims, page) => { const byChannel = allClaims[uri] || {}; - const claimIds = byChannel[page]; + const claimIds = byChannel[page || 1]; if (!claimIds) return claimIds; From 7b7a63b892b12c0bbcf26432ade362e0768096f1 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 13:20:02 -0400 Subject: [PATCH 119/132] disable anything cost related other than direct content cost --- ui/js/actions/cost_info.js | 65 +++++++++++++++++++++++++++----------- ui/js/lbry.js | 43 ------------------------- 2 files changed, 46 insertions(+), 62 deletions(-) diff --git a/ui/js/actions/cost_info.js b/ui/js/actions/cost_info.js index 06044633a..001c4ae56 100644 --- a/ui/js/actions/cost_info.js +++ b/ui/js/actions/cost_info.js @@ -33,26 +33,53 @@ export function doFetchCostInfoForUri(uri) { }); } - if (isGenerous && claim) { - let cost; - const fee = claim.value && - claim.value.stream && - claim.value.stream.metadata - ? claim.value.stream.metadata.fee - : undefined; - if (fee === undefined) { - resolve({ cost: 0, includesData: true }); - } else if (fee.currency == "LBC") { - resolve({ cost: fee.amount, includesData: true }); - } else { - // begin(); - lbryio.getExchangeRates().then(({ lbc_usd }) => { - resolve({ cost: fee.amount / lbc_usd, includesData: true }); - }); - } + /** + * "Generous" check below is disabled. We're no longer attempting to include or estimate data fees regardless of settings. + * + * This should be modified when lbry.stream_cost_estimate is reliable and performant. + */ + + /* + lbry.stream_cost_estimate({ uri }).then(cost => { + cacheAndResolve(cost); + }, reject); + */ + + const fee = claim.value && claim.value.stream && claim.value.stream.metadata + ? claim.value.stream.metadata.fee + : undefined; + + if (fee === undefined) { + resolve({ cost: 0, includesData: true }); + } else if (fee.currency == "LBC") { + resolve({ cost: fee.amount, includesData: true }); } else { - begin(); - lbry.getCostInfo(uri).then(resolve); + // begin(); + lbryio.getExchangeRates().then(({ lbc_usd }) => { + resolve({ cost: fee.amount / lbc_usd, includesData: true }); + }); } + + // if (isGenerous && claim) { + // let cost; + // const fee = claim.value && + // claim.value.stream && + // claim.value.stream.metadata + // ? claim.value.stream.metadata.fee + // : undefined; + // if (fee === undefined) { + // resolve({ cost: 0, includesData: true }); + // } else if (fee.currency == "LBC") { + // resolve({ cost: fee.amount, includesData: true }); + // } else { + // // begin(); + // lbryio.getExchangeRates().then(({ lbc_usd }) => { + // resolve({ cost: fee.amount / lbc_usd, includesData: true }); + // }); + // } + // } else { + // begin(); + // lbry.getCostInfo(uri).then(resolve); + // } }; } diff --git a/ui/js/lbry.js b/ui/js/lbry.js index 5ad0671b8..767d4479c 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -176,49 +176,6 @@ lbry.connect = function() { return lbry._connectPromise; }; -/** - * Takes a LBRY URI; will first try and calculate a total cost using - * Lighthouse. If Lighthouse can't be reached, it just retrives the - * key fee. - * - * Returns an object with members: - * - cost: Number; the calculated cost of the name - * - includes_data: Boolean; indicates whether or not the data fee info - * from Lighthouse is included. - */ -lbry.costPromiseCache = {}; -lbry.getCostInfo = function(uri) { - if (lbry.costPromiseCache[uri] === undefined) { - lbry.costPromiseCache[uri] = new Promise((resolve, reject) => { - const COST_INFO_CACHE_KEY = "cost_info_cache"; - let costInfoCache = getSession(COST_INFO_CACHE_KEY, {}); - - function cacheAndResolve(cost) { - const includesData = false; - costInfoCache[uri] = { cost, includesData }; - setSession(COST_INFO_CACHE_KEY, costInfoCache); - resolve({ cost, includesData }); - } - - if (!uri) { - return reject(new Error(`URI required.`)); - } - - if (costInfoCache[uri] && costInfoCache[uri].cost) { - return resolve(costInfoCache[uri]); - } - - const uriObj = lbryuri.parse(uri); - const name = uriObj.path || uriObj.name; - - lbry.stream_cost_estimate({ uri }).then(cost => { - cacheAndResolve(cost); - }, reject); - }); - } - return lbry.costPromiseCache[uri]; -}; - /** * Publishes a file. The optional fileListedCallback is called when the file becomes available in * lbry.file_list() during the publish process. From 3bb146244eeb453911a9100f6e7d609c16b5ec33 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 13:23:57 -0400 Subject: [PATCH 120/132] =?UTF-8?q?Bump=20version:=200.16.0rc3=20=E2=86=92?= =?UTF-8?q?=200.16.0rc4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 60f014c32..bdc24c25b 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc3 +current_version = 0.16.0rc4 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index eae996ea7..ec55442e8 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc3", + "version": "0.16.0rc4", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index acacd985a..3aab97191 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc3", + "version": "0.16.0rc4", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From 8690d8a41417222878fb65b2c7d30f21522bf452 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 13:55:10 -0400 Subject: [PATCH 121/132] update daemon to 0.16.1 proper --- app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/package.json b/app/package.json index ec55442e8..e700c985d 100644 --- a/app/package.json +++ b/app/package.json @@ -20,7 +20,7 @@ "electron-rebuild": "^1.5.11" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.16.1rc1", + "lbrynetDaemonVersion": "0.16.1", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip" }, "license": "MIT" From 0f8e61982e0a8d853a4445971a303e16e82c83d0 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 13:55:29 -0400 Subject: [PATCH 122/132] =?UTF-8?q?Bump=20version:=200.16.0rc4=20=E2=86=92?= =?UTF-8?q?=200.16.0rc5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index bdc24c25b..b6d663f2d 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc4 +current_version = 0.16.0rc5 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index e700c985d..90d1ce429 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc4", + "version": "0.16.0rc5", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index 3aab97191..51111e031 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc4", + "version": "0.16.0rc5", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From 6b87369bbea7e48481678930a4d5aace8d71bdfb Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 15:27:25 -0400 Subject: [PATCH 123/132] transaction value fix --- ui/js/selectors/wallet.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index 8aafcf6dc..2c9b6704b 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -29,19 +29,21 @@ export const selectTransactionItems = createSelector( append.push( ...tx.claim_info.map(item => - Object.assign({}, item, { + Object.assign({}, tx, item, { type: item.claim_name[0] === "@" ? "channel" : "publish", }) ) ); append.push( ...tx.support_info.map(item => - Object.assign({}, item, { type: !item.is_tip ? "support" : "tip" }) + Object.assign({}, tx, item, { + type: !item.is_tip ? "support" : "tip", + }) ) ); append.push( ...tx.update_info.map(item => - Object.assign({}, item, { type: "update" }) + Object.assign({}, tx, item, { type: "update" }) ) ); @@ -58,7 +60,7 @@ export const selectTransactionItems = createSelector( //value on transaction, amount on outpoint //amount is always positive, but should match sign of value const amount = parseFloat( - item.value || (item.value < 0 ? -1 : 1) * item.amount + item.amount ? (item.value < 0 ? -1 : 1) * item.amount : item.value ); return { From 7b41c199b2ff0a713661ba39776881edb190c434 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 15:27:44 -0400 Subject: [PATCH 124/132] =?UTF-8?q?Bump=20version:=200.16.0rc5=20=E2=86=92?= =?UTF-8?q?=200.16.0rc6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b6d663f2d..0e79b0f49 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc5 +current_version = 0.16.0rc6 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index 90d1ce429..9a30a585d 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc5", + "version": "0.16.0rc6", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index 51111e031..c5fc73e6a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc5", + "version": "0.16.0rc6", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From cac00028c41586710b2aa29bee7ceacc0009c8ba Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 15:45:39 -0400 Subject: [PATCH 125/132] update invite reward check, fix infinite reward loop --- ui/js/component/inviteList/view.jsx | 4 ++-- ui/js/page/rewards/view.jsx | 32 +++++++++++++++++------------ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/ui/js/component/inviteList/view.jsx b/ui/js/component/inviteList/view.jsx index 8d748116a..8e6e0c938 100644 --- a/ui/js/component/inviteList/view.jsx +++ b/ui/js/component/inviteList/view.jsx @@ -47,9 +47,9 @@ class InviteList extends React.PureComponent { {invitee.invite_reward_claimed ? - : invitee.invite_accepted + : invitee.invite_reward_claimable ? : diff --git a/ui/js/page/rewards/view.jsx b/ui/js/page/rewards/view.jsx index 51d75e406..423d45faa 100644 --- a/ui/js/page/rewards/view.jsx +++ b/ui/js/page/rewards/view.jsx @@ -6,21 +6,27 @@ import SubHeader from "component/subHeader"; import Link from "component/link"; class RewardsPage extends React.PureComponent { - componentDidMount() { - this.fetchRewards(this.props); - } + /* + Below is broken for users who have claimed all rewards. - componentWillReceiveProps(nextProps) { - this.fetchRewards(nextProps); - } + It can safely be disabled since we fetch all rewards after authentication, but should be re-enabled once fixed. - fetchRewards(props) { - const { fetching, rewards, fetchRewards } = props; - - if (!fetching && (!rewards || !rewards.length)) { - fetchRewards(); - } - } + */ + // componentDidMount() { + // this.fetchRewards(this.props); + // } + // + // componentWillReceiveProps(nextProps) { + // this.fetchRewards(nextProps); + // } + // + // fetchRewards(props) { + // const { fetching, rewards, fetchRewards } = props; + // + // if (!fetching && (!rewards || !rewards.length)) { + // fetchRewards(); + // } + // } renderPageHeader() { const { doAuth, navigate, user } = this.props; From a01b258f47ad34e0715a338d17eb5e112c09e84c Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 20 Sep 2017 15:45:57 -0400 Subject: [PATCH 126/132] =?UTF-8?q?Bump=20version:=200.16.0rc6=20=E2=86=92?= =?UTF-8?q?=200.16.0rc7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0e79b0f49..2150f74ee 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc6 +current_version = 0.16.0rc7 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index 9a30a585d..6cf1aa602 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc6", + "version": "0.16.0rc7", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index c5fc73e6a..e2be6f8a3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc6", + "version": "0.16.0rc7", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From dbd147f4d1c86c3dfcc176061607d06bcf168cde Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Thu, 21 Sep 2017 08:49:23 -0400 Subject: [PATCH 127/132] add gnome-keyring deb dependency. closes #386. the rest of the `depends` are the defaults see https://www.electron.build/configuration/deb for details --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 673ea306b..afe3ee680 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,9 @@ "Exec": "/opt/LBRY/lbry %U" } }, + "deb": { + "depends": ["gconf2", "gconf-service", "libnotify4", "libappindicator1", "libxtst6", "libnss3", "gnome-keyring"] + }, "win": { "target": "nsis" }, From cba6a4039482a40721f6f9306b659be68656a9e4 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 21 Sep 2017 09:26:32 -0400 Subject: [PATCH 128/132] =?UTF-8?q?Bump=20version:=200.16.0rc7=20=E2=86=92?= =?UTF-8?q?=200.16.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGELOG.md | 37 +++++++++++++++++++++++++++---------- app/package.json | 2 +- ui/package.json | 2 +- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 2150f74ee..206eca6b6 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0rc7 +current_version = 0.16.0 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d6c73333..59c45a89c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,15 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * Added a tipping button to send LBRY Credits to a creator. - * Added an edit button on published content. Significantly improved UX for editing claims. - * Added theme settings option and new Dark theme. - * Significantly more detail is shown about past transactions and new filtering options for transactions. - * File pages now show the time of a publish. - * The "auth token" displayable on Help offers security warning - * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. - * Added a `Form` component, to further progress towards form sanity. + * + * ### Changed - * CSS significantly refactored to support CSS vars (and consequently easy theming). + * + * ### Fixed - * URLs on cards no longer wrap and show an ellipsis if longer than one line + * * ### Deprecated @@ -32,6 +27,28 @@ Web UI version numbers should always match the corresponding version of LBRY App * * +## [0.16.0] - 2017-09-21 + +### Added + * Added a tipping button to send LBRY Credits to a creator. + * Added an edit button on published content. Significantly improved UX for editing claims. + * Added theme settings option and new Dark theme. + * Significantly more detail is shown about past transactions and new filtering options for transactions. + * File pages now show the time of a publish. + * The "auth token" displayable on Help offers security warning + * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. + * Added a `Form` component, to further progress towards form sanity. + + +### Changed + * CSS significantly refactored to support CSS vars (and consequently easy theming). + + +### Fixed + * URLs on cards no longer wrap and show an ellipsis if longer than one line + + + ## [0.15.1] - 2017-09-08 ### Added diff --git a/app/package.json b/app/package.json index 6cf1aa602..15878e6e7 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.16.0rc7", + "version": "0.16.0", "main": "main.js", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "author": { diff --git a/ui/package.json b/ui/package.json index e2be6f8a3..82f5d0889 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.16.0rc7", + "version": "0.16.0", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", From dafe9bb87d6dc3f2438aca22f8a47643dee8fc4f Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Thu, 21 Sep 2017 09:29:51 -0400 Subject: [PATCH 129/132] add message about installing dependencies in build --- build.sh | 3 +-- build/build.sh | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/build.sh b/build.sh index 1105489f8..6dc7044f1 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,4 @@ #!/bin/bash # this is here because teamcity runs /build.sh to build the project -set -euxo pipefail DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -$DIR/build/build.sh \ No newline at end of file +$DIR/build/build.sh diff --git a/build/build.sh b/build/build.sh index 700dd610f..86c9a6217 100755 --- a/build/build.sh +++ b/build/build.sh @@ -9,13 +9,11 @@ BUILD_DIR="$ROOT/build" LINUX=false OSX=false if [ "$(uname)" == "Darwin" ]; then -set -x + echo -e "\033[0;32mBuilding for OSX\x1b[m" OSX=true -set +x elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then -set -x + echo -e "\033[0;32mBuilding for Linux\x1b[m" LINUX=true -set +x else echo -e "\033[1;31mPlatform detection failed\x1b[m" exit 1 @@ -26,12 +24,14 @@ if $OSX; then else ICON="$BUILD_DIR/icons/48x48.png" fi -set -x + FULL_BUILD="${FULL_BUILD:-false}" -set +x if [ -n "${TEAMCITY_VERSION:-}" -o -n "${APPVEYOR:-}" ]; then FULL_BUILD="true" fi +if [ "$FULL_BUILD" != "true" ]; then + echo -e "\033[1;36mDependencies will NOT be installed. Run with 'FULL_BUILD=true' to install dependencies.\x1b[m" +fi if [ "$FULL_BUILD" == "true" ]; then # install dependencies From a2ef39a3cbf51cfa50d259c3201ae77c19a51bd4 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Thu, 21 Sep 2017 09:31:02 -0400 Subject: [PATCH 130/132] forgot to changelog this --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59c45a89c..0e4786a85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * The "auth token" displayable on Help offers security warning * Added a new component for rendering dates and times. This component can render the date and time of a block height, as well. * Added a `Form` component, to further progress towards form sanity. + * Added `gnome-keyring` dependency to .deb ### Changed From 326d76b561c9959cd2d7540af147b6f87c032d5e Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Thu, 21 Sep 2017 10:24:18 -0400 Subject: [PATCH 131/132] we don't need the full gnome-keyring, just libsecret --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index afe3ee680..18565cf6b 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ } }, "deb": { - "depends": ["gconf2", "gconf-service", "libnotify4", "libappindicator1", "libxtst6", "libnss3", "gnome-keyring"] + "depends": ["gconf2", "gconf-service", "libnotify4", "libappindicator1", "libxtst6", "libnss3", "libsecret-1-0"] }, "win": { "target": "nsis" From 4ed7d2cba9e7f6b2f0fccdd22bdc11ae85bfdaf5 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 21 Sep 2017 21:12:18 -0400 Subject: [PATCH 132/132] bad solution for #544 --- ui/js/selectors/claims.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 34c4ea688..c90b78843 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -180,7 +180,12 @@ export const selectMyChannelClaims = createSelector( const ids = state.myChannelClaims || []; const claims = []; - ids.forEach(id => claims.push(byId[id])); + ids.forEach(id => { + if (byId[id]) { + //I'm not sure why this check is necessary, but it ought to be a quick fix for https://github.com/lbryio/lbry-app/issues/544 + claims.push(byId[id]); + } + }); return claims; }