mostly done

refactor modals and settings, clean-up CHANGELOG
This commit is contained in:
Jeremy Kauffman 2017-08-18 13:09:40 -04:00
parent 2018bfb2f2
commit 5bec6accc2
39 changed files with 242 additions and 165 deletions

View file

@ -8,23 +8,24 @@ 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 wallet backup guide reference
* Added feature: forward history
*
* 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
* Updated to daemon [0.15](https://github.com/lbryio/lbry/releases). Most relevant changes for app are improved announcing of content and a fix for the daemon getting stuck running.
* Some form field refactoring as we progress towards form sanity.
* Continued to refine first-run process, process for new users, and introducing people to LBRY and LBRY credits.
* Changed the default price settings.
* When an "Open" button is clicked on a show page, if the file fails to open, the app will try to open the file's folder.
* Removed confusing placeholder text from email input
* Updated several packages and fixed warnings in build process (all but the [fsevents warning](https://github.com/yarnpkg/yarn/issues/3738), which is rather dramatic)
* Some form field refactoring as we take baby steps towards form sanity.
* Replaced confusing placeholder text from email input.
* Refactored modal and settings logic.
* Updated several packages and fixed warnings in build process (all but the [fsevents warning](https://github.com/yarnpkg/yarn/issues/3738), which is a rather dramatic debate)
### Fixed
* Tiles will no longer be blurry on hover (Windows only bug)
* Removed placeholder values from price selection form fields, which was causing confusion that these were real values (#426)
* Fixed showing "other currency" help tip in publish form, which was caused due to not "setting" state for price
* Now using setState in formFieldPrice
* Public page now properly checks for all required fields are filled
* Fixed pagination styling for pages > 5 (#416)
* Fixed sizing on squat videos (#419)

View file

@ -1,12 +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("language")
? lbry.getClientSetting("language")
const language = lbry.getClientSetting(settings.LANGUAGE)
? lbry.getClientSetting(settings.LANGUAGE)
: "en";
const i18n = require("y18n")({
directory: "app/locales",

View file

@ -1,15 +1,8 @@
import React from "react";
import Router from "component/router";
import Router from "component/router/index";
import Header from "component/header";
import ModalError from "component/modalError";
import ModalAuthFailure from "component/modalAuthFailure";
import ModalDownloading from "component/modalDownloading";
import ModalInsufficientCredits from "component/modalInsufficientCredits";
import ModalUpgrade from "component/modalUpgrade";
import ModalWelcome from "component/modalWelcome";
import ModalFirstReward from "component/modalFirstReward";
import ModalRouter from "modal/modalRouter";
import lbry from "lbry";
import * as modals from "constants/modal_types";
class App extends React.PureComponent {
componentWillMount() {
@ -34,50 +27,23 @@ class App extends React.PureComponent {
fetchRewardedContent();
this.showWelcome(this.props);
this.scrollListener = () => this.props.recordScroll(window.scrollY);
window.addEventListener("scroll", this.scrollListener);
}
componentWillReceiveProps(nextProps) {
this.showWelcome(nextProps);
}
showWelcome(props) {
const { isWelcomeAcknowledged, openWelcomeModal, user } = props;
if (
!isWelcomeAcknowledged &&
user &&
!user.is_reward_approved &&
!user.is_identity_verified
) {
openWelcomeModal();
}
}
componentWillUnmount() {
window.removeEventListener("scroll", this.scrollListener);
}
render() {
const { modal } = this.props;
return (
<div id="window">
<Header />
<div id="main-content">
<Router />
</div>
{modal == modals.UPGRADE && <ModalUpgrade />}
{modal == modals.DOWNLOADING && <ModalDownloading />}
{modal == modals.ERROR && <ModalError />}
{modal == modals.INSUFFICIENT_CREDITS && <ModalInsufficientCredits />}
{modal == modals.WELCOME && <ModalWelcome />}
{modal == modals.FIRST_REWARD && <ModalFirstReward />}
{modal == modals.AUTHENTICATION_FAILURE && <ModalAuthFailure />}
<ModalRouter />
</div>
);
}

View file

@ -1,11 +1,11 @@
import React from "react";
import { Icon, BusyMessage } from "component/common";
import FilePrice from "component/filePrice";
import { Modal } from "component/modal";
import { Modal } from "modal/modal";
import Link from "component/link";
import { ToolTip } from "component/tooltip";
import { DropDownMenu, DropDownMenuItem } from "component/menu";
import ModalRemoveFile from "component/modalRemoveFile";
import ModalRemoveFile from "modal/modalRemoveFile";
import * as modals from "constants/modal_types";
class FileActions extends React.PureComponent {

View file

@ -1,84 +0,0 @@
import React from "react";
import { Modal } from "component/modal";
import { CreditAmount } from "component/common";
import Link from "component/link";
import RewardLink from "component/rewardLink";
class ModalWelcome extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
isFirstScreen: true,
};
}
render() {
const { closeModal, totalRewardValue, verifyAccount } = this.props;
const totalRewardRounded = Math.round(totalRewardValue / 10) * 10;
return (
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
{this.state.isFirstScreen &&
<section>
<h3 className="modal__header">{__("Welcome to LBRY")}</h3>
<p>
{__(
"Using LBRY is like dating a centaur. Totally normal up top, and"
)}
{" "}<em>{__("way different")}</em> {__("underneath.")}
</p>
<p>{__("Up top, LBRY is similar to popular media sites.")}</p>
<p>
{__(
"Below, LBRY is controlled by users -- you -- via blockchain and decentralization."
)}
</p>
<div className="modal__buttons">
<Link
button="primary"
onClick={() => {
this.setState({ isFirstScreen: false });
}}
label={__("Continue")}
/>
</div>
</section>}
{!this.state.isFirstScreen &&
<section>
<h3 className="modal__header">{__("Claim Your Credits")}</h3>
<p>
The LBRY network is controlled and powered by credits called{" "}
<em>LBC</em>, a blockchain asset.
</p>
<p>
{__("New patrons receive ")} {" "}
{totalRewardValue
? <CreditAmount amount={totalRewardRounded} />
: <span className="credit-amount">{__("credits")}</span>}
{" "} {__("in rewards for usage and influence of the network.")}
</p>
<p>
{__(
"You'll also earn weekly bonuses for checking out the greatest new stuff."
)}
</p>
<div className="modal__buttons">
<Link
button="primary"
onClick={verifyAccount}
label={__("You Had Me At Free LBC")}
/>
<Link
button="alt"
onClick={closeModal}
label={__("I Burn Money")}
/>
</div>
</section>}
</Modal>
);
}
}
export default ModalWelcome;

View file

@ -5,7 +5,7 @@ import FormField from "component/formField";
import { FormRow } from "component/form.js";
import Link from "component/link";
import FormFieldPrice from "component/formFieldPrice";
import Modal from "component/modal";
import Modal from "modal/modal";
import { BusyMessage } from "component/common";
import ChannelSection from "./internal/channelSection";

View file

@ -1,5 +1,5 @@
import React from "react";
import Modal from "component/modal";
import Modal from "modal/modal";
import Link from "component/link";
const RewardLink = props => {

View file

@ -1,9 +1,9 @@
import React from "react";
import lbry from "../../lbry.js";
import lbry from "lbry.js";
import LoadScreen from "../load_screen.js";
import ModalIncompatibleDaemon from "../modalIncompatibleDaemon";
import ModalUpgrade from "component/modalUpgrade";
import ModalDownloading from "component/modalDownloading";
import ModalIncompatibleDaemon from "modal/modalIncompatibleDaemon";
import ModalUpgrade from "modal/modalUpgrade";
import ModalDownloading from "modal/modalDownloading";
export class SplashScreen extends React.PureComponent {
static propTypes = {

View file

@ -1,7 +1,7 @@
import React from "react";
import FilePrice from "component/filePrice";
import Link from "component/link";
import Modal from "component/modal";
import Modal from "modal/modal";
class VideoPlayButton extends React.PureComponent {
componentDidMount() {

View file

@ -1,6 +1,6 @@
import React from "react";
import Link from "component/link";
import Modal from "component/modal";
import Modal from "modal/modal";
import { FormRow } from "component/form";
const WalletSend = props => {

View file

@ -6,4 +6,5 @@ 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";
export const AUTHENTICATION_FAILURE = "auth_failure";
export const CREDIT_INTRO = "credit_intro";

View file

@ -0,0 +1,5 @@
export const CREDIT_INTRO_ACKNOWLEDGED = "credit_intro_acknowledged";
export const FIRST_RUN_ACKNOWLEDGED = "welcome_acknowledged";
export const LANGUAGE = "language";
export const SHOW_NSFW = "showNsfw";
export const SHOW_UNAVAILABLE = "showUnavailable";

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactModal from "react-modal";
import Link from "component/link";
import app from "../app.js";
import Link from "component/link/index";
import app from "app.js";
export class Modal extends React.PureComponent {
static propTypes = {

View file

@ -1,5 +1,5 @@
import React from "react";
import { Modal } from "component/modal";
import { Modal } from "modal/modal";
class ModalAuthFailure extends React.PureComponent {
render() {
@ -12,11 +12,17 @@ class ModalAuthFailure extends React.PureComponent {
type="confirm"
confirmButtonLabel={__("Reload")}
abortButtonLabel={__("Continue")}
onConfirmed={() => { window.location.reload() }}
onConfirmed={() => {
window.location.reload();
}}
onAborted={close}
>
<h3>{__("Authentication Failure")}</h3>
<p>{__("If reloading does not fix this, or you see this at every start up, please email help@lbry.io.")}</p>
<p>
{__(
"If reloading does not fix this, or you see this at every start up, please email help@lbry.io."
)}
</p>
</Modal>
);
}

View file

@ -9,7 +9,8 @@ import {
makeSelectRewardByType,
selectTotalRewardValue,
} from "selectors/rewards";
import ModalWelcome from "./view";
import * as settings from "constants/settings";
import ModalCreditIntro from "./view";
const select = (state, props) => {
const selectHasClaimed = makeSelectHasClaimedReward(),
@ -24,7 +25,7 @@ const select = (state, props) => {
const perform = dispatch => () => {
const closeModal = () => {
dispatch(doSetClientSetting("welcome_acknowledged", true));
dispatch(doSetClientSetting(settings.CREDIT_INTRO_ACKNOWLEDGED, true));
dispatch(doCloseModal());
};
@ -37,4 +38,4 @@ const perform = dispatch => () => {
};
};
export default connect(select, perform)(ModalWelcome);
export default connect(select, perform)(ModalCreditIntro);

View file

@ -0,0 +1,44 @@
import React from "react";
import { Modal } from "modal/modal";
import { CreditAmount } from "component/common";
import Link from "component/link/index";
const ModalCreditIntro = props => {
const { closeModal, totalRewardValue, verifyAccount } = props;
const totalRewardRounded = Math.round(totalRewardValue / 10) * 10;
return (
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
<section>
<h3 className="modal__header">{__("Claim Your Credits")}</h3>
<p>
The LBRY network is controlled and powered by credits called{" "}
<em>LBC</em>, a blockchain asset.
</p>
<p>
{__("New patrons receive ")} {" "}
{totalRewardValue
? <CreditAmount amount={totalRewardRounded} />
: <span className="credit-amount">{__("credits")}</span>}
{" "} {__("in rewards for usage and influence of the network.")}
</p>
<p>
{__(
"You'll also earn weekly bonuses for checking out the greatest new stuff."
)}
</p>
<div className="modal__buttons">
<Link
button="primary"
onClick={verifyAccount}
label={__("You Had Me At Free LBC")}
/>
<Link button="alt" onClick={closeModal} label={__("I Burn Money")} />
</div>
</section>
</Modal>
);
};
export default ModalCreditIntro;

View file

@ -1,7 +1,7 @@
import React from "react";
import { Modal } from "component/modal";
import { Modal } from "modal/modal";
import { Line } from "rc-progress";
import Link from "component/link";
import Link from "component/link/index";
class ModalDownloading extends React.PureComponent {
render() {

View file

@ -1,6 +1,6 @@
import React from "react";
import lbry from "lbry";
import { ExpandableModal } from "component/modal";
import { ExpandableModal } from "modal/modal";
class ModalError extends React.PureComponent {
render() {

View file

@ -1,5 +1,5 @@
import React from "react";
import { Modal } from "component/modal";
import { Modal } from "modal/modal";
import { CreditAmount } from "component/common";
class ModalFirstReward extends React.PureComponent {

View file

@ -1,6 +1,6 @@
import React from "react";
import { Modal } from "component/modal";
import Link from "component/link";
import { Modal } from "modal/modal";
import Link from "component/link/index";
class ModalIncompatibleDaemon extends React.PureComponent {
render() {

View file

@ -1,5 +1,5 @@
import React from "react";
import { Modal } from "component/modal";
import { Modal } from "modal/modal";
class ModalInsufficientCredits extends React.PureComponent {
render() {

View file

@ -1,6 +1,6 @@
import React from "react";
import { Modal } from "component/modal";
import FormField from "component/formField";
import { Modal } from "modal/modal";
import FormField from "component/formField/index";
class ModalRemoveFile extends React.PureComponent {
constructor(props) {

View file

@ -0,0 +1,20 @@
import React from "react";
import { connect } from "react-redux";
import { selectCurrentModal } from "selectors/app";
import { doOpenModal } from "actions/app";
import { selectWelcomeModalAcknowledged } from "selectors/app";
import { selectUser } from "selectors/user";
import ModalRouter from "./view";
import * as modals from "constants/modal_types";
const select = (state, props) => ({
modal: selectCurrentModal(state),
isWelcomeAcknowledged: selectWelcomeModalAcknowledged(state),
user: selectUser(state),
});
const perform = dispatch => ({
openWelcomeModal: () => dispatch(doOpenModal(modals.WELCOME)),
});
export default connect(select, perform)(ModalRouter);

View file

@ -0,0 +1,60 @@
import React from "react";
import ModalError from "modal/modalError";
import ModalAuthFailure from "modal/modalAuthFailure";
import ModalDownloading from "modal/modalDownloading";
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";
class ModalRouter extends React.PureComponent {
componentWillMount() {
this.showWelcome(this.props);
}
componentWillReceiveProps(nextProps) {
this.showWelcome(nextProps);
}
showWelcome(props) {
const { isWelcomeAcknowledged, openWelcomeModal, user } = props;
if (
!isWelcomeAcknowledged &&
user &&
!user.is_reward_approved &&
!user.is_identity_verified
) {
openWelcomeModal();
}
}
render() {
const { modal } = this.props;
switch (modal) {
case modals.UPGRADE:
return <ModalUpgrade />;
case modals.DOWNLOADING:
return <ModalDownloading />;
case modals.ERROR:
return <ModalError />;
case modals.INSUFFICIENT_CREDITS:
return <ModalInsufficientCredits />;
case modals.WELCOME:
return <ModalWelcome />;
case modals.FIRST_REWARD:
return <ModalFirstReward />;
case modals.AUTHENTICATION_FAILURE:
return <ModalAuthFailure />;
case modals.CREDIT_INTRO:
return <ModalCreditIntro />;
default:
return null;
}
}
}
export default ModalRouter;

View file

@ -1,5 +1,5 @@
import React from "react";
import { Modal } from "component/modal";
import { Modal } from "modal/modal";
class ModalUpgrade extends React.PureComponent {
render() {

View file

@ -0,0 +1,17 @@
import React from "react";
import * as settings from "constants/settings";
import * as modals from "constants/modal_types";
import { connect } from "react-redux";
import { doCloseModal, doOpenModal } from "actions/app";
import { doSetClientSetting } from "actions/settings";
import ModalWelcome from "./view";
const perform = dispatch => () => ({
closeModal: () => {
dispatch(doSetClientSetting(settings.FIRST_RUN_ACKNOWLEDGED, true));
dispatch(doCloseModal());
dispatch(doOpenModal(modals.CREDIT_INTRO));
},
});
export default connect(null, perform)(ModalWelcome);

View file

@ -0,0 +1,32 @@
import React from "react";
import { Modal } from "modal/modal";
import Link from "component/link/index";
const ModalWelcome = props => {
const { closeModal } = props;
return (
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
<section>
<h3 className="modal__header">{__("Welcome to LBRY")}</h3>
<p>
{__(
"Using LBRY is like dating a centaur. Totally normal up top, and"
)}
{" "}<em>{__("way different")}</em> {__("underneath.")}
</p>
<p>{__("Up top, LBRY is similar to popular media sites.")}</p>
<p>
{__(
"Below, LBRY is controlled by users -- you -- via blockchain and decentralization."
)}
</p>
<div className="modal__buttons">
<Link button="primary" onClick={closeModal} label={__("Continue")} />
</div>
</section>
</Modal>
);
};
export default ModalWelcome;

View file

@ -2,6 +2,7 @@ import React from "react";
import FormField from "component/formField";
import { FormRow } from "component/form.js";
import SubHeader from "component/subHeader";
import * as settings from "constants/settings";
import lbry from "lbry.js";
import Link from "component/link";
import FormFieldPrice from "component/formFieldPrice";
@ -17,8 +18,8 @@ class SettingsPage extends React.PureComponent {
this.state = {
// isMaxUpload: daemonSettings && daemonSettings.max_upload != 0,
// isMaxDownload: daemonSettings && daemonSettings.max_download != 0,
showUnavailable: lbry.getClientSetting("showUnavailable"),
language: lbry.getClientSetting("language"),
showUnavailable: lbry.getClientSetting(settings.SHOW_UNAVAILABLE),
language: lbry.getClientSetting(settings.LANGUAGE),
clearingCache: false,
};
}
@ -92,7 +93,7 @@ class SettingsPage extends React.PureComponent {
// }
onShowNsfwChange(event) {
this.props.setClientSetting("showNsfw", event.target.checked);
this.props.setClientSetting(settings.SHOW_NSFW, event.target.checked);
}
// onLanguageChange(language) {

View file

@ -1,5 +1,6 @@
import { createSelector } from "reselect";
import { parseQueryParams, toQueryString } from "util/query_params";
import * as settings from "constants/settings.js";
import lbry from "lbry";
import lbryuri from "lbryuri";
@ -202,9 +203,14 @@ export const selectSnackBarSnacks = createSelector(
snackBar => snackBar.snacks || []
);
export const selectCreditsIntroAcknowledged = createSelector(
_selectState,
state => lbry.getClientSetting(settings.CREDIT_INTRO_ACKNOWLEDGED)
);
export const selectWelcomeModalAcknowledged = createSelector(
_selectState,
state => lbry.getClientSetting("welcome_acknowledged")
state => lbry.getClientSetting(settings.FIRST_RUN_ACKNOWLEDGED)
);
export const selectBadgeNumber = createSelector(

View file

@ -73,7 +73,7 @@
max-width: none;
width: 400px;
}
.error-modal__error-list { /*shitty hack/temp fix for long errors making modals unusable*/
.error-modal__error-list { /*shitty hack/temp fix for long errors making modal unusable*/
border: 1px solid #eee;
padding: 8px;
list-style: none;