diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d1aa2d53..a6118a90e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,14 +3,13 @@
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-## [0.51.2] - [2021-08-20]
+## [Unreleased for Desktop]
### Added
- Show currently active playing item on playlist _community pr!_ ([#6453](https://github.com/lbryio/lbry-desktop/pull/6453))
- Add watch later to hover action for last used playlist on popup _community pr!_ ([#6274](https://github.com/lbryio/lbry-desktop/pull/6274))
- Add confirmation on comment removal _community pr!_ ([#6563](https://github.com/lbryio/lbry-desktop/pull/6563))
- Show on content page if a file is part of a playlist already _community pr!_([#6393](https://github.com/lbryio/lbry-desktop/pull/6393))
-- Add filtering to playlists ([#6905](https://github.com/lbryio/lbry-desktop/pull/6905))
### Changed
- Use Canonical Url for copy link ([#6500](https://github.com/lbryio/lbry-desktop/pull/6500))
diff --git a/package.json b/package.json
index 5e5db1f0a..301ccd167 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "lbry",
- "version": "0.51.2",
+ "version": "0.51.2-rc.4",
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
"keywords": [
"lbry"
diff --git a/static/app-strings.json b/static/app-strings.json
index f786b48e7..896dd1b96 100644
--- a/static/app-strings.json
+++ b/static/app-strings.json
@@ -156,9 +156,8 @@
"Experimental settings": "Experimental settings",
"Autoplay media files": "Autoplay media files",
"Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.": "Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.",
- "Clear application cache": "Clear application cache",
+ "Application cache": "Application cache",
"Clear Cache": "Clear Cache",
- "This might fix issues that you are having. Your wallet will not be affected.": "This might fix issues that you are having. Your wallet will not be affected.",
"Currency": "Currency",
"US Dollars": "US Dollars",
"There's nothing available at this location.": "There's nothing available at this location.",
@@ -494,7 +493,7 @@
"Automatic dark mode": "Automatic dark mode",
"24-hour clock": "24-hour clock",
"Hide wallet balance in header": "Hide wallet balance in header",
- "Max connections": "Max connections",
+ "Max Connections": "Max Connections",
"For users with good bandwidth, try a higher value to improve streaming and download speeds. Low bandwidth users may benefit from a lower setting. Default is 4.": "For users with good bandwidth, try a higher value to improve streaming and download speeds. Low bandwidth users may benefit from a lower setting. Default is 4.",
"Show All": "Show All",
"LBRY names cannot contain spaces or reserved symbols": "LBRY names cannot contain spaces or reserved symbols",
@@ -512,7 +511,7 @@
"Read more": "Read more",
"Multi-language support is brand new and incomplete. Switching your language may have unintended consequences, like glossolalia.": "Multi-language support is brand new and incomplete. Switching your language may have unintended consequences, like glossolalia.",
"Tailor your experience.": "Tailor your experience.",
- "Save wallet password": "Save wallet password",
+ "Save Password": "Save Password",
"Automatically unlock your wallet on startup": "Automatically unlock your wallet on startup",
"Dark": "Dark",
"light": "light",
@@ -657,6 +656,7 @@
"Invalid claim ID %claimId%.": "Invalid claim ID %claimId%.",
"Suggested": "Suggested",
"Startup preferences": "Startup preferences",
+ "This will clear the application cache, and might fix issues you are having. Your wallet will not be affected. ": "This will clear the application cache, and might fix issues you are having. Your wallet will not be affected. ",
"Start minimized": "Start minimized",
"Improve view speed and help the LBRY network by allowing the app to cuddle up in your system tray.": "Improve view speed and help the LBRY network by allowing the app to cuddle up in your system tray.",
"Content Type": "Content Type",
@@ -710,8 +710,7 @@
"Failed to copy RSS URL.": "Failed to copy RSS URL.",
"Text copied": "Text copied",
"Rewards Disabled": "Rewards Disabled",
- "Wallet server": "Wallet server",
- "Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%": "Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%",
+ "Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%.": "Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%.",
"Your Tags": "Your Tags",
"All Content": "All Content",
"Accepted": "Accepted",
@@ -1420,9 +1419,7 @@
"Transcode": "Transcode",
"Estimated transaction fee:": "Estimated transaction fee:",
"Est. transaction fee:": "Est. transaction fee:",
- "Publish confirmation": "Publish confirmation",
"Skip preview and confirmation": "Skip preview and confirmation",
- "Show preview and confirmation dialog before publishing content.": "Show preview and confirmation dialog before publishing content.",
"Upload settings": "Upload settings",
"Currently Uploading": "Currently Uploading",
"Leave the app running until upload is complete": "Leave the app running until upload is complete",
@@ -1453,6 +1450,7 @@
"Controversial": "Controversial",
"Show Replies": "Show Replies",
"Hide replies": "Hide replies",
+ "Unable to create comment, please try again later.": "Unable to create comment, please try again later.",
"Unable to comment. This channel has blocked you.": "Unable to comment. This channel has blocked you.",
"Unable to comment. Your channel has been blocked by an admin.": "Unable to comment. Your channel has been blocked by an admin.",
"Unable to comment. The content owner has disabled comments.": "Unable to comment. The content owner has disabled comments.",
@@ -1613,7 +1611,7 @@
"None selected": "None selected",
"Secondary Language": "Secondary Language",
"Your other content language": "Your other content language",
- "Search only in the selected language by default": "Search only in the selected language by default",
+ "Search only in this language by default": "Search only in this language by default",
"This link leads to an external website.": "This link leads to an external website.",
"No Content Found": "No Content Found",
"No Lists Found": "No Lists Found",
@@ -1623,7 +1621,7 @@
"No Reposts Found": "No Reposts Found",
"Publish Something": "Publish Something",
"Repost Something": "Repost Something",
- "Watch on %SITE_NAME%": "Watch on %SITE_NAME%",
+ "Watch on lbry.tv": "Watch on lbry.tv",
"Paid content cannot be embedded.": "Paid content cannot be embedded.",
"Please wait a bit, we are still getting your account ready.": "Please wait a bit, we are still getting your account ready.",
"this channel is connected to a different account. Contact hello@lbry.com for help.": "this channel is connected to a different account. Contact hello@lbry.com for help.",
@@ -1746,9 +1744,8 @@
"Delegation": "Delegation",
"Add moderator": "Add moderator",
"Enter a @username or URL": "Enter a @username or URL",
- "Enter a channel name or URL to add as a moderator.\nExamples:\n - @channel\n - @channel#3\n - https://odysee.com/@Odysee:8\n - lbry://@Odysee#8": "Enter a channel name or URL to add as a moderator.\nExamples:\n - @channel\n - @channel#3\n - https://odysee.com/@Odysee:8\n - lbry://@Odysee#8",
+ "examples: @channel, @channel#3, https://odysee.com/@Odysee:8, lbry://@Odysee#8": "examples: @channel, @channel#3, https://odysee.com/@Odysee:8, lbry://@Odysee#8",
"Moderators": "Moderators",
- "Moderators can block channels on your behalf. Blocked channels will appear in your \"Blocked and Muted\" list.": "Moderators can block channels on your behalf. Blocked channels will appear in your \"Blocked and Muted\" list.",
"Add as moderator": "Add as moderator",
"Mute (m)": "Mute (m)",
"Playback Rate (<, >)": "Playback Rate (<, >)",
@@ -1937,7 +1934,6 @@
"Clarification": "Clarification",
"Client name": "Client name",
"Creator settings": "Creator settings",
- "Comments and livestream chat containing these words will be blocked.": "Comments and livestream chat containing these words will be blocked.",
"Muted words": "Muted words",
"Add words": "Add words",
"Suggestions": "Suggestions",
@@ -1948,7 +1944,6 @@
"Enabling a minimum amount to comment will force all comments, including livestreams, to have tips associated with them. This can help prevent spam.": "Enabling a minimum amount to comment will force all comments, including livestreams, to have tips associated with them. This can help prevent spam.",
"Minimum %lbc% tip amount for hyperchats": "Minimum %lbc% tip amount for hyperchats",
"Enabling a minimum amount to hyperchat will force all TIPPED comments to have this value in order to be shown. This still allows regular comments to be posted.": "Enabling a minimum amount to hyperchat will force all TIPPED comments to have this value in order to be shown. This still allows regular comments to be posted.",
- "This settings is not applicable if all comments require a tip.": "This settings is not applicable if all comments require a tip.",
"Settings unavailable for this channel": "Settings unavailable for this channel",
"This channel isn't staking enough LBRY Credits to enable Creator Settings.": "This channel isn't staking enough LBRY Credits to enable Creator Settings.",
"Not a channel (prefix with \"@\", or enter the channel URL)": "Not a channel (prefix with \"@\", or enter the channel URL)",
@@ -2052,7 +2047,6 @@
"Commenting server is not set.": "Commenting server is not set.",
"Comments are not currently enabled.": "Comments are not currently enabled.",
"See All": "See All",
- "System": "System",
"Supporting content requires %lbc%": "Supporting content requires %lbc%",
"With %lbc%, you can send tips to your favorite creators, or help boost their content for more people to see.": "With %lbc%, you can send tips to your favorite creators, or help boost their content for more people to see.",
"Show this channel your appreciation by sending a donation in USD.": "Show this channel your appreciation by sending a donation in USD.",
@@ -2096,15 +2090,10 @@
"Expand Comments": "Expand Comments",
"Expand": "Expand",
"Load More": "Load More",
- "%formattedSubCount% Followers": "%formattedSubCount% Followers",
- "1 Follower": "1 Follower",
+ "%channelSubCount% Followers": "%channelSubCount% Followers",
+ "%channelSubCount% Follower": "%channelSubCount% Follower",
"Collection": "Collection",
"%channelName% isn't live right now, but the chat is! Check back later to watch the stream.": "%channelName% isn't live right now, but the chat is! Check back later to watch the stream.",
"Review": "Review",
- "Account History": "Account History",
- "Payment History": "Payment History",
- "There was an error from the server, please try again later": "There was an error from the server, please try again later",
- "There was an error getting your card setup, please try again later": "There was an error getting your card setup, please try again later",
- "View Transactions": "View Transactions",
"--end--": "--end--"
}
diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx
index 00505e48a..aadc719e4 100644
--- a/ui/component/app/view.jsx
+++ b/ui/component/app/view.jsx
@@ -5,7 +5,7 @@ import { lazyImport } from 'util/lazyImport';
import classnames from 'classnames';
import analytics from 'analytics';
import { buildURI, parseURI } from 'lbry-redux';
-import { SIMPLE_SITE } from 'config';
+import { SIMPLE_SITE, ENABLE_PREROLL_ADS } from 'config';
import Router from 'component/router/index';
import ReactModal from 'react-modal';
import { openContextMenu } from 'util/context-menu';
@@ -325,21 +325,21 @@ function App(props: Props) {
}
}, [previousRewardApproved, isRewardApproved]);
- // Load IMA3 SDK for aniview: DISABLED FOR NOW
+ // Load IMA3 SDK for aniview
// @if TARGET='web'
- // useEffect(() => {
- // if (ENABLE_PREROLL_ADS) {
- // const script = document.createElement('script');
- // script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`;
- // script.async = true;
- // // $FlowFixMe
- // document.body.appendChild(script);
- // return () => {
- // // $FlowFixMe
- // document.body.removeChild(script);
- // };
- // }
- // });
+ useEffect(() => {
+ if (ENABLE_PREROLL_ADS) {
+ const script = document.createElement('script');
+ script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`;
+ script.async = true;
+ // $FlowFixMe
+ document.body.appendChild(script);
+ return () => {
+ // $FlowFixMe
+ document.body.removeChild(script);
+ };
+ }
+ });
// @endif
// @if TARGET='app'
diff --git a/ui/component/claimPreview/view.jsx b/ui/component/claimPreview/view.jsx
index 2e1844ac9..650839952 100644
--- a/ui/component/claimPreview/view.jsx
+++ b/ui/component/claimPreview/view.jsx
@@ -172,10 +172,11 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => {
if (channelSubCount === undefined) {
return ;
}
- const formattedSubCount = Number(channelSubCount).toLocaleString();
return (
- {channelSubCount === 1 ? __('1 Follower') : __('%formattedSubCount% Followers', { formattedSubCount })}
+ {channelSubCount === 1
+ ? __('%channelSubCount% Follower', { channelSubCount })
+ : __('%channelSubCount% Followers', { channelSubCount })}
);
}, [channelSubCount]);
diff --git a/ui/component/comment/view.jsx b/ui/component/comment/view.jsx
index 6d3c6dc62..6e3d03e9b 100644
--- a/ui/component/comment/view.jsx
+++ b/ui/component/comment/view.jsx
@@ -373,19 +373,13 @@ function Comment(props: Props) {
setPage(1);
}
}}
- icon={ICONS.DOWN}
/>
)}
{numDirectReplies > 0 && showReplies && (
- setShowReplies(false)}
- icon={ICONS.UP}
- />
+ setShowReplies(false)} />
)}
diff --git a/ui/component/common/card.jsx b/ui/component/common/card.jsx
index 1fb606cdb..29c3f1a9c 100644
--- a/ui/component/common/card.jsx
+++ b/ui/component/common/card.jsx
@@ -10,7 +10,6 @@ type Props = {
title?: string | Node,
subtitle?: string | Node,
titleActions?: string | Node,
- id?: string,
body?: string | Node,
actions?: string | Node,
icon?: string,
@@ -31,7 +30,6 @@ export default function Card(props: Props) {
title,
subtitle,
titleActions,
- id,
body,
actions,
icon,
@@ -55,7 +53,6 @@ export default function Card(props: Props) {
className={classnames(className, 'card', {
'card__multi-pane': Boolean(secondPane),
})}
- id={id}
onClick={(e) => {
if (onClick) {
onClick();
diff --git a/ui/component/common/credit-amount.jsx b/ui/component/common/credit-amount.jsx
index b22e63cab..92adbba4c 100644
--- a/ui/component/common/credit-amount.jsx
+++ b/ui/component/common/credit-amount.jsx
@@ -49,6 +49,11 @@ class CreditAmount extends React.PureComponent {
isFiat,
} = this.props;
const minimumRenderableAmount = 10 ** (-1 * precision);
+
+ // return null, otherwise it will try and convert undefined to a string
+ if (amount === undefined) {
+ return null;
+ }
const fullPrice = formatFullPrice(amount, 2);
const isFree = parseFloat(amount) === 0;
diff --git a/ui/component/common/icon-custom.jsx b/ui/component/common/icon-custom.jsx
index fcd9e0954..c9a181801 100644
--- a/ui/component/common/icon-custom.jsx
+++ b/ui/component/common/icon-custom.jsx
@@ -2318,23 +2318,6 @@ export const icons = {
),
- [ICONS.APPEARANCE]: buildIcon(
-
-
-
-
-
-
-
- ),
- [ICONS.CONTENT]: buildIcon(
-
-
-
-
-
-
- ),
[ICONS.STAR]: buildIcon(
diff --git a/ui/component/homepageSelector/view.jsx b/ui/component/homepageSelector/view.jsx
index b8eb7adef..514cb2f94 100644
--- a/ui/component/homepageSelector/view.jsx
+++ b/ui/component/homepageSelector/view.jsx
@@ -8,7 +8,7 @@ import { getDefaultHomepageKey } from 'util/default-languages';
type Props = {
homepage: string,
- setHomepage: (string) => void,
+ setHomepage: string => void,
};
function SelectHomepage(props: Props) {
@@ -26,10 +26,12 @@ function SelectHomepage(props: Props) {
- {Object.keys(homepages).map((hp) => (
+ {Object.keys(homepages).map(hp => (
{`${LANGUAGES[hp][1]}`}
diff --git a/ui/component/inviteNew/view.jsx b/ui/component/inviteNew/view.jsx
index 78b13336b..00944d830 100644
--- a/ui/component/inviteNew/view.jsx
+++ b/ui/component/inviteNew/view.jsx
@@ -11,7 +11,7 @@ import LbcSymbol from 'component/common/lbc-symbol';
type Props = {
errorMessage: ?string,
- inviteNew: string => void,
+ inviteNew: (string) => void,
isPending: boolean,
referralLink: string,
referralCode: string,
@@ -35,10 +35,10 @@ function InviteNew(props: Props) {
const [referralSource, setReferralSource] = useState(referralCode);
const handleReferralChange = React.useCallback(
- code => {
+ (code) => {
setReferralSource(code);
// TODO: keep track of this in an array?
- const matchingChannel = channels && channels.find(ch => ch.name === code);
+ const matchingChannel = channels && channels.find((ch) => ch.name === code);
if (matchingChannel) {
analytics.apiLogPublish(matchingChannel);
}
@@ -68,80 +68,85 @@ function InviteNew(props: Props) {
}, [topChannel, handleReferralChange]);
function lookupUrlByClaimName(name, channels) {
- const claim = channels.find(channel => channel.name === name);
+ const claim = channels.find((channel) => channel.name === name);
return claim && claim.canonical_url ? claim.canonical_url.replace('lbry://', '') : name;
}
return (
-
}}>
- Earn %lbc% for inviting subscribers, followers, fans, friends, etc. to join and follow you on %SITE_NAME%.
- You can use invites just like affiliate links.
-
- }
- actions={
-
-
- {channels && channels.length > 0 && (
- handleReferralChange(e.target.value)}
- >
- {channels.map(channel => (
-
- {channel.name}
-
- ))}
- {referralCode}
-
- )}
-
- }
- />
-
-
}}>
- Invite someone you know by email and earn %lbc% when they join %SITE_NAME%.
-
- }
- actions={
-
-
);
}
diff --git a/ui/component/livestreamComments/view.jsx b/ui/component/livestreamComments/view.jsx
index 5b133d821..b434592f3 100644
--- a/ui/component/livestreamComments/view.jsx
+++ b/ui/component/livestreamComments/view.jsx
@@ -9,7 +9,6 @@ import UriIndicator from 'component/uriIndicator';
import CreditAmount from 'component/common/credit-amount';
import ChannelThumbnail from 'component/channelThumbnail';
import Tooltip from 'component/common/tooltip';
-import * as ICONS from 'constants/icons';
type Props = {
uri: string,
@@ -298,11 +297,10 @@ export default function LivestreamComments(props: Props) {
{scrollPos < 0 && (
)}
diff --git a/ui/component/maxPurchasePrice/index.js b/ui/component/maxPurchasePrice/index.js
deleted file mode 100644
index ed04f6cfe..000000000
--- a/ui/component/maxPurchasePrice/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { connect } from 'react-redux';
-import { doSetDaemonSetting } from 'redux/actions/settings';
-import { selectDaemonSettings } from 'redux/selectors/settings';
-import MaxPurchasePrice from './view';
-
-const select = (state) => ({
- daemonSettings: selectDaemonSettings(state),
-});
-const perform = (dispatch) => ({
- setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)),
-});
-
-export default connect(select, perform)(MaxPurchasePrice);
diff --git a/ui/component/maxPurchasePrice/view.jsx b/ui/component/maxPurchasePrice/view.jsx
deleted file mode 100644
index bd163ec81..000000000
--- a/ui/component/maxPurchasePrice/view.jsx
+++ /dev/null
@@ -1,72 +0,0 @@
-// @flow
-import React from 'react';
-import { FormField, FormFieldPrice } from 'component/common/form';
-
-type Price = {
- currency: string,
- amount: number,
-};
-
-type DaemonSettings = {
- download_dir: string,
- share_usage_data: boolean,
- max_key_fee?: Price,
- max_connections_per_download?: number,
- save_files: boolean,
- save_blobs: boolean,
- ffmpeg_path: string,
-};
-
-type SetDaemonSettingArg = boolean | string | number | Price;
-
-type Props = {
- daemonSettings: DaemonSettings,
- setDaemonSetting: (string, ?SetDaemonSettingArg) => void,
-};
-
-export default function MaxPurchasePrice(props: Props) {
- const { daemonSettings, setDaemonSetting } = props;
-
- const defaultMaxKeyFee = { currency: 'USD', amount: 50 };
- const disableMaxKeyFee = !(daemonSettings && daemonSettings.max_key_fee);
-
- function onKeyFeeDisableChange(isDisabled: boolean) {
- if (isDisabled) {
- setDaemonSetting('max_key_fee');
- }
- }
-
- function onKeyFeeChange(newValue: Price) {
- setDaemonSetting('max_key_fee', newValue);
- }
-
- return (
- <>
- onKeyFeeDisableChange(true)}
- />
- {
- onKeyFeeDisableChange(false);
- onKeyFeeChange(defaultMaxKeyFee);
- }}
- label={__('Choose limit')}
- />
-
-
- >
- );
-}
diff --git a/ui/component/page/view.jsx b/ui/component/page/view.jsx
index 6d288c3bc..3951ad603 100644
--- a/ui/component/page/view.jsx
+++ b/ui/component/page/view.jsx
@@ -4,7 +4,6 @@ import React, { Fragment } from 'react';
import classnames from 'classnames';
import { lazyImport } from 'util/lazyImport';
import SideNavigation from 'component/sideNavigation';
-import SettingsSideNavigation from 'component/settingsSideNavigation';
import Header from 'component/header';
/* @if TARGET='app' */
import StatusBar from 'component/common/status-bar';
@@ -24,7 +23,6 @@ type Props = {
isUpgradeAvailable: boolean,
authPage: boolean,
filePage: boolean,
- settingsPage?: boolean,
noHeader: boolean,
noFooter: boolean,
noSideNavigation: boolean,
@@ -47,7 +45,6 @@ function Page(props: Props) {
children,
className,
filePage = false,
- settingsPage,
authPage = false,
fullWidthPage = false,
noHeader = false,
@@ -79,24 +76,6 @@ function Page(props: Props) {
const isAbsoluteSideNavHidden = (isOnFilePage || isMobile) && !sidebarOpen;
- function getSideNavElem() {
- if (!authPage) {
- if (settingsPage) {
- return ;
- } else if (!noSideNavigation) {
- return (
-
- );
- }
- }
- return null;
- }
-
React.useEffect(() => {
if (isOnFilePage || isMediumScreen) {
setSidebarOpen(false);
@@ -121,15 +100,20 @@ function Page(props: Props) {
'main-wrapper__inner--theater-mode': isOnFilePage && videoTheaterMode,
})}
>
- {getSideNavElem()}
-
+ {!authPage && !noSideNavigation && (
+
+ )}
({
+ enablePublishPreview: makeSelectClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW)(state),
+});
+
+const perform = dispatch => ({
+ setEnablePublishPreview: value => dispatch(doSetClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW, value)),
+});
+
+export default connect(select, perform)(PublishSettings);
diff --git a/ui/component/publishSettings/view.jsx b/ui/component/publishSettings/view.jsx
new file mode 100644
index 000000000..d59d4e6ea
--- /dev/null
+++ b/ui/component/publishSettings/view.jsx
@@ -0,0 +1,31 @@
+// @flow
+import React from 'react';
+import { FormField } from 'component/common/form';
+import { withRouter } from 'react-router';
+
+type Props = {
+ enablePublishPreview: boolean,
+ setEnablePublishPreview: boolean => void,
+};
+
+function PublishSettings(props: Props) {
+ const { enablePublishPreview, setEnablePublishPreview } = props;
+
+ function handleChange() {
+ setEnablePublishPreview(!enablePublishPreview);
+ }
+
+ return (
+
+
+
+ );
+}
+
+export default withRouter(PublishSettings);
diff --git a/ui/component/router/view.jsx b/ui/component/router/view.jsx
index eb6f74fcf..1e2631970 100644
--- a/ui/component/router/view.jsx
+++ b/ui/component/router/view.jsx
@@ -67,10 +67,9 @@ const RepostNew = lazyImport(() => import('page/repost' /* webpackChunkName: "se
const RewardsPage = lazyImport(() => import('page/rewards' /* webpackChunkName: "secondary" */));
const RewardsVerifyPage = lazyImport(() => import('page/rewardsVerify' /* webpackChunkName: "secondary" */));
const SearchPage = lazyImport(() => import('page/search' /* webpackChunkName: "secondary" */));
+const SettingsAdvancedPage = lazyImport(() => import('page/settingsAdvanced' /* webpackChunkName: "secondary" */));
const SettingsStripeCard = lazyImport(() => import('page/settingsStripeCard' /* webpackChunkName: "secondary" */));
-const SettingsStripeAccount = lazyImport(() =>
- import('page/settingsStripeAccount' /* webpackChunkName: "secondary" */)
-);
+const SettingsStripeAccount = lazyImport(() => import('page/settingsStripeAccount' /* webpackChunkName: "secondary" */));
const SettingsCreatorPage = lazyImport(() => import('page/settingsCreator' /* webpackChunkName: "secondary" */));
const SettingsNotificationsPage = lazyImport(() =>
import('page/settingsNotifications' /* webpackChunkName: "secondary" */)
@@ -82,7 +81,6 @@ const TagsFollowingManagePage = lazyImport(() =>
);
const TagsFollowingPage = lazyImport(() => import('page/tagsFollowing' /* webpackChunkName: "secondary" */));
const TopPage = lazyImport(() => import('page/top' /* webpackChunkName: "secondary" */));
-const UpdatePasswordPage = lazyImport(() => import('page/passwordUpdate' /* webpackChunkName: "passwordUpdate" */));
const Welcome = lazyImport(() => import('page/welcome' /* webpackChunkName: "secondary" */));
const YoutubeSyncPage = lazyImport(() => import('page/youtubeSync' /* webpackChunkName: "secondary" */));
@@ -279,6 +277,7 @@ function AppRouter(props: Props) {
+
@@ -295,7 +294,6 @@ function AppRouter(props: Props) {
-
({
- isAuthenticated: selectUserVerifiedEmail(state),
- walletEncrypted: selectWalletIsEncrypted(state),
- user: selectUser(state),
- language: selectLanguage(state),
-});
-
-const perform = (dispatch) => ({
- doWalletStatus: () => dispatch(doWalletStatus()),
-});
-
-export default connect(select, perform)(SettingAccount);
diff --git a/ui/component/settingAccount/view.jsx b/ui/component/settingAccount/view.jsx
deleted file mode 100644
index bca8861b1..000000000
--- a/ui/component/settingAccount/view.jsx
+++ /dev/null
@@ -1,100 +0,0 @@
-// @flow
-import * as ICONS from 'constants/icons';
-import * as PAGES from 'constants/pages';
-import { SETTINGS_GRP } from 'constants/settings';
-import React from 'react';
-import Button from 'component/button';
-import Card from 'component/common/card';
-import SettingsRow from 'component/settingsRow';
-import SyncToggle from 'component/syncToggle';
-import { getPasswordFromCookie } from 'util/saved-passwords';
-import { getStripeEnvironment } from 'util/stripe';
-
-type Props = {
- // --- select ---
- isAuthenticated: boolean,
- walletEncrypted: boolean,
- user: User,
- // --- perform ---
- doWalletStatus: () => void,
-};
-
-export default function SettingAccount(props: Props) {
- const { isAuthenticated, walletEncrypted, user, doWalletStatus } = props;
- const [storedPassword, setStoredPassword] = React.useState(false);
-
- // Determine if password is stored.
- React.useEffect(() => {
- if (isAuthenticated || !IS_WEB) {
- doWalletStatus();
- getPasswordFromCookie().then((p) => {
- if (typeof p === 'string') {
- setStoredPassword(true);
- }
- });
- }
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
-
- return (
- <>
-
-
{__('Account')}
-
-
-
- {isAuthenticated && (
-
-
-
- )}
-
- {/* @if TARGET='app' */}
-
- {/* @endif */}
-
- {/* @if TARGET='web' */}
- {user && getStripeEnvironment() && (
-
-
-
- )}
- {/* @endif */}
-
- {/* @if TARGET='web' */}
- {isAuthenticated && getStripeEnvironment() && (
-
-
-
- )}
- {/* @endif */}
- >
- }
- />
- >
- );
-}
diff --git a/ui/component/settingAccountPassword/view.jsx b/ui/component/settingAccountPassword/view.jsx
index cc9561f15..a63dff59a 100644
--- a/ui/component/settingAccountPassword/view.jsx
+++ b/ui/component/settingAccountPassword/view.jsx
@@ -1,10 +1,9 @@
// @flow
import React, { useState } from 'react';
-import { useHistory } from 'react-router';
import { FormField, Form } from 'component/common/form';
import Button from 'component/button';
import ErrorText from 'component/common/error-text';
-import SettingsRow from 'component/settingsRow';
+import Card from 'component/common/card';
import * as PAGES from 'constants/pages';
type Props = {
@@ -20,11 +19,8 @@ export default function SettingAccountPassword(props: Props) {
const { user, doToast, doUserPasswordSet, passwordSetSuccess, passwordSetError, doClearPasswordEntry } = props;
const [oldPassword, setOldPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
+ const [isAddingPassword, setIsAddingPassword] = useState(false);
const hasPassword = user && user.password_set;
- const { goBack } = useHistory();
-
- const title = hasPassword ? __('Update Your Password') : __('Add A Password');
- const subtitle = hasPassword ? '' : __('You do not currently have a password set.');
function handleSubmit() {
doUserPasswordSet(newPassword, oldPassword);
@@ -32,7 +28,7 @@ export default function SettingAccountPassword(props: Props) {
React.useEffect(() => {
if (passwordSetSuccess) {
- goBack();
+ setIsAddingPassword(false);
doToast({
message: __('Password updated successfully.'),
});
@@ -40,42 +36,56 @@ export default function SettingAccountPassword(props: Props) {
setOldPassword('');
setNewPassword('');
}
- }, [passwordSetSuccess, setOldPassword, setNewPassword, doClearPasswordEntry, doToast, goBack]);
+ }, [passwordSetSuccess, setOldPassword, setNewPassword, doClearPasswordEntry, doToast]);
return (
-
-
- {hasPassword && (
- setOldPassword(e.target.value)}
- />
- )}
- setNewPassword(e.target.value)}
- />
+
+
+ {hasPassword && (
+ setOldPassword(e.target.value)}
+ />
+ )}
+ setNewPassword(e.target.value)}
+ />
-
-
- {hasPassword ? (
-
- ) : (
- goBack()} />
- )}
-
-
- {passwordSetError && (
-
- {passwordSetError}
-
- )}
-
+
+
+ {hasPassword ? (
+
+ ) : (
+ setIsAddingPassword(false)} />
+ )}
+
+
+ {passwordSetError && (
+
+ {passwordSetError}
+
+ )}
+
+ ) : (
+ setIsAddingPassword(true)}
+ />
+ )
+ }
+ />
);
}
diff --git a/ui/component/settingAppearance/index.js b/ui/component/settingAppearance/index.js
deleted file mode 100644
index 33cea31fc..000000000
--- a/ui/component/settingAppearance/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { connect } from 'react-redux';
-import { SETTINGS } from 'lbry-redux';
-import { doSetClientSetting } from 'redux/actions/settings';
-import { selectLanguage, makeSelectClientSetting } from 'redux/selectors/settings';
-import { selectUserVerifiedEmail } from 'redux/selectors/user';
-import SettingAppearance from './view';
-
-const select = (state) => ({
- clock24h: makeSelectClientSetting(SETTINGS.CLOCK_24H)(state),
- searchInLanguage: makeSelectClientSetting(SETTINGS.SEARCH_IN_LANGUAGE)(state),
- isAuthenticated: selectUserVerifiedEmail(state),
- hideBalance: makeSelectClientSetting(SETTINGS.HIDE_BALANCE)(state),
- language: selectLanguage(state),
-});
-
-const perform = (dispatch) => ({
- setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
- setSearchInLanguage: (value) => dispatch(doSetClientSetting(SETTINGS.SEARCH_IN_LANGUAGE, value)),
-});
-
-export default connect(select, perform)(SettingAppearance);
diff --git a/ui/component/settingAppearance/view.jsx b/ui/component/settingAppearance/view.jsx
deleted file mode 100644
index 436e390b5..000000000
--- a/ui/component/settingAppearance/view.jsx
+++ /dev/null
@@ -1,88 +0,0 @@
-// @flow
-import { SETTINGS_GRP } from 'constants/settings';
-import React from 'react';
-import { SETTINGS } from 'lbry-redux';
-import Card from 'component/common/card';
-import { FormField } from 'component/common/form';
-import HomepageSelector from 'component/homepageSelector';
-import SettingLanguage from 'component/settingLanguage';
-import SettingsRow from 'component/settingsRow';
-import ThemeSelector from 'component/themeSelector';
-// $FlowFixMe
-import homepages from 'homepages';
-
-type Props = {
- clock24h: boolean,
- searchInLanguage: boolean,
- isAuthenticated: boolean,
- hideBalance: boolean,
- setClientSetting: (string, boolean | string | number) => void,
- setSearchInLanguage: (boolean) => void,
-};
-
-export default function SettingAppearance(props: Props) {
- const { clock24h, searchInLanguage, isAuthenticated, hideBalance, setClientSetting, setSearchInLanguage } = props;
-
- return (
- <>
-
-
{__('Appearance')}
-
-
- {homepages && Object.keys(homepages).length > 1 && (
-
-
-
- )}
-
-
-
-
-
-
- setSearchInLanguage(!searchInLanguage)}
- />
-
-
-
-
-
-
-
- setClientSetting(SETTINGS.CLOCK_24H, !clock24h)}
- checked={clock24h}
- />
-
-
- {(isAuthenticated || !IS_WEB) && (
-
- setClientSetting(SETTINGS.HIDE_BALANCE, !hideBalance)}
- checked={hideBalance}
- />
-
- )}
- >
- }
- />
- >
- );
-}
-
-// prettier-ignore
-const HELP = {
- LANGUAGE: 'Multi-language support is brand new and incomplete. Switching your language may have unintended consequences, like glossolalia.',
-};
diff --git a/ui/component/settingAutoLaunch/view.jsx b/ui/component/settingAutoLaunch/view.jsx
index f5c9cc169..4effdabf7 100644
--- a/ui/component/settingAutoLaunch/view.jsx
+++ b/ui/component/settingAutoLaunch/view.jsx
@@ -6,28 +6,25 @@ import { FormField } from 'component/common/form';
type Props = {
autoLaunch: string,
showToast: ({}) => void,
- setAutoLaunch: (boolean) => void,
- noLabels?: boolean,
+ setAutoLaunch: boolean => void,
};
function SettingAutoLaunch(props: Props) {
- const { autoLaunch, setAutoLaunch, noLabels } = props;
+ const { autoLaunch, setAutoLaunch } = props;
return (
{
+ onChange={e => {
setAutoLaunch(e.target.checked);
}}
checked={autoLaunch}
- label={noLabels ? '' : __('Start minimized')}
- helper={
- noLabels
- ? ''
- : __('Improve view speed and help the LBRY network by allowing the app to cuddle up in your system tray.')
- }
+ label={__('Start minimized')}
+ helper={__(
+ 'Improve view speed and help the LBRY network by allowing the app to cuddle up in your system tray.'
+ )}
/>
);
diff --git a/ui/component/settingClosingBehavior/view.jsx b/ui/component/settingClosingBehavior/view.jsx
index 4ad423248..a8560aa57 100644
--- a/ui/component/settingClosingBehavior/view.jsx
+++ b/ui/component/settingClosingBehavior/view.jsx
@@ -5,23 +5,22 @@ import { FormField } from 'component/common/form';
type Props = {
toTrayWhenClosed: boolean,
- setToTrayWhenClosed: (boolean) => void,
- noLabels?: boolean,
+ setToTrayWhenClosed: boolean => void,
};
function SettingClosingBehavior(props: Props) {
- const { toTrayWhenClosed, setToTrayWhenClosed, noLabels } = props;
+ const { toTrayWhenClosed, setToTrayWhenClosed } = props;
return (
{
+ onChange={e => {
setToTrayWhenClosed(e.target.checked);
}}
checked={toTrayWhenClosed}
- label={noLabels ? '' : __('Leave app running in notification area when the window is closed')}
+ label={__('Leave app running in notification area when the window is closed')}
/>
);
diff --git a/ui/component/settingContent/index.js b/ui/component/settingContent/index.js
deleted file mode 100644
index 706b8562b..000000000
--- a/ui/component/settingContent/index.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { connect } from 'react-redux';
-import { selectMyChannelUrls, SETTINGS } from 'lbry-redux';
-import { doOpenModal } from 'redux/actions/app';
-import { doSetPlayingUri } from 'redux/actions/content';
-import { doSetClientSetting } from 'redux/actions/settings';
-import { selectShowMatureContent, selectLanguage, makeSelectClientSetting } from 'redux/selectors/settings';
-import { selectUserVerifiedEmail } from 'redux/selectors/user';
-
-import SettingContent from './view';
-
-const select = (state) => ({
- isAuthenticated: selectUserVerifiedEmail(state),
- floatingPlayer: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state),
- autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY)(state),
- hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state),
- showNsfw: selectShowMatureContent(state),
- myChannelUrls: selectMyChannelUrls(state),
- instantPurchaseEnabled: makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED)(state),
- instantPurchaseMax: makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_MAX)(state),
- enablePublishPreview: makeSelectClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW)(state),
- language: selectLanguage(state),
-});
-
-const perform = (dispatch) => ({
- setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
- clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
- openModal: (id, params) => dispatch(doOpenModal(id, params)),
-});
-
-export default connect(select, perform)(SettingContent);
diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx
deleted file mode 100644
index 11e770df7..000000000
--- a/ui/component/settingContent/view.jsx
+++ /dev/null
@@ -1,217 +0,0 @@
-// @flow
-import * as ICONS from 'constants/icons';
-import * as PAGES from 'constants/pages';
-import React from 'react';
-import { SETTINGS } from 'lbry-redux';
-import { Lbryio } from 'lbryinc';
-import { SIMPLE_SITE } from 'config';
-import * as MODALS from 'constants/modal_types';
-import { SETTINGS_GRP } from 'constants/settings';
-import Button from 'component/button';
-import Card from 'component/common/card';
-import { FormField, FormFieldPrice } from 'component/common/form';
-import MaxPurchasePrice from 'component/maxPurchasePrice';
-import SettingsRow from 'component/settingsRow';
-
-type Price = {
- currency: string,
- amount: number,
-};
-
-type Props = {
- // --- select ---
- isAuthenticated: boolean,
- floatingPlayer: boolean,
- autoplay: boolean,
- hideReposts: ?boolean,
- showNsfw: boolean,
- myChannelUrls: ?Array,
- instantPurchaseEnabled: boolean,
- instantPurchaseMax: Price,
- enablePublishPreview: boolean,
- // --- perform ---
- setClientSetting: (string, boolean | string | number) => void,
- clearPlayingUri: () => void,
- openModal: (string) => void,
-};
-
-export default function SettingContent(props: Props) {
- const {
- isAuthenticated,
- floatingPlayer,
- autoplay,
- hideReposts,
- showNsfw,
- myChannelUrls,
- instantPurchaseEnabled,
- instantPurchaseMax,
- enablePublishPreview,
- setClientSetting,
- clearPlayingUri,
- openModal,
- } = props;
-
- return (
- <>
-
-
{__('Content settings')}
-
-
-
- {
- setClientSetting(SETTINGS.FLOATING_PLAYER, !floatingPlayer);
- clearPlayingUri();
- }}
- checked={floatingPlayer}
- />
-
-
-
- setClientSetting(SETTINGS.AUTOPLAY, !autoplay)}
- checked={autoplay}
- />
-
-
- {!SIMPLE_SITE && (
- <>
-
- {
- if (isAuthenticated) {
- let param = e.target.checked ? { add: 'noreposts' } : { remove: 'noreposts' };
- Lbryio.call('user_tag', 'edit', param);
- }
- setClientSetting(SETTINGS.HIDE_REPOSTS, !hideReposts);
- }}
- />
-
-
- {/*
-
- setClientSetting(SETTINGS.SHOW_ANONYMOUS, !showAnonymous)}
- checked={showAnonymous}
- />
-
- */}
-
-
-
- !IS_WEB || showNsfw
- ? setClientSetting(SETTINGS.SHOW_MATURE, !showNsfw)
- : openModal(MODALS.CONFIRM_AGE)
- }
- />
-
- >
- )}
-
- {(isAuthenticated || !IS_WEB) && (
- <>
-
-
-
-
-
-
-
-
- {myChannelUrls && myChannelUrls.length > 0 && (
-
-
-
- )}
- >
- )}
-
-
- setClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW, !enablePublishPreview)}
- />
-
-
- {/* @if TARGET='app' */}
-
-
-
- {/* @endif */}
-
-
- setClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, false)}
- />
- setClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, true)}
- />
- {instantPurchaseEnabled && (
- setClientSetting(SETTINGS.INSTANT_PURCHASE_MAX, newValue)}
- price={instantPurchaseMax}
- />
- )}
-
- >
- }
- />
- >
- );
-}
-
-// prettier-ignore
-const HELP = {
- FLOATING_PLAYER: 'Keep content playing in the corner when navigating to a different page.',
- AUTOPLAY: 'Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.',
- HIDE_REPOSTS: 'You will not see reposts by people you follow or receive email notifying about them.',
- SHOW_MATURE: 'Mature content may include nudity, intense sexuality, profanity, or other adult content. By displaying mature content, you are affirming you are of legal age to view mature content in your country or jurisdiction. ',
- MAX_PURCHASE_PRICE: 'This will prevent you from purchasing any content over a certain cost, as a safety measure.',
- ONLY_CONFIRM_OVER_AMOUNT: '', // [feel redundant. Disable for now] "When this option is chosen, LBRY won't ask you to confirm purchases or tips below your chosen amount.",
- PUBLISH_PREVIEW: 'Show preview and confirmation dialog before publishing content.',
-};
diff --git a/ui/component/settingLanguage/index.js b/ui/component/settingLanguage/index.js
index 34ee83fd5..5a3d60abe 100644
--- a/ui/component/settingLanguage/index.js
+++ b/ui/component/settingLanguage/index.js
@@ -1,14 +1,17 @@
import { connect } from 'react-redux';
-import { doSetLanguage } from 'redux/actions/settings';
-import { selectLanguage } from 'redux/selectors/settings';
+import { SETTINGS } from 'lbry-redux';
+import { doSetLanguage, doSetClientSetting } from 'redux/actions/settings';
+import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings';
import SettingLanguage from './view';
-const select = (state) => ({
+const select = state => ({
language: selectLanguage(state),
+ searchInLanguage: makeSelectClientSetting(SETTINGS.SEARCH_IN_LANGUAGE)(state),
});
-const perform = (dispatch) => ({
- setLanguage: (value) => dispatch(doSetLanguage(value)),
+const perform = dispatch => ({
+ setLanguage: value => dispatch(doSetLanguage(value)),
+ setSearchInLanguage: value => dispatch(doSetClientSetting(SETTINGS.SEARCH_IN_LANGUAGE, value)),
});
export default connect(select, perform)(SettingLanguage);
diff --git a/ui/component/settingLanguage/view.jsx b/ui/component/settingLanguage/view.jsx
index 515970d6e..cb58a7f19 100644
--- a/ui/component/settingLanguage/view.jsx
+++ b/ui/component/settingLanguage/view.jsx
@@ -10,10 +10,12 @@ import { getDefaultLanguage, sortLanguageMap } from 'util/default-languages';
type Props = {
language: string,
setLanguage: (string) => void,
+ searchInLanguage: boolean,
+ setSearchInLanguage: (boolean) => void,
};
function SettingLanguage(props: Props) {
- const { language, setLanguage } = props;
+ const { language, setLanguage, searchInLanguage, setSearchInLanguage } = props;
const [previousLanguage, setPreviousLanguage] = useState(null);
if (previousLanguage && language !== previousLanguage) {
@@ -35,13 +37,15 @@ function SettingLanguage(props: Props) {
return (
- {previousLanguage && }
-
{sortLanguageMap(SUPPORTED_LANGUAGES).map(([langKey, langName]) => (
@@ -49,6 +53,14 @@ function SettingLanguage(props: Props) {
))}
+ {previousLanguage && }
+ setSearchInLanguage(!searchInLanguage)}
+ />
);
}
diff --git a/ui/component/settingSystem/view.jsx b/ui/component/settingSystem/view.jsx
deleted file mode 100644
index 529dfb1ee..000000000
--- a/ui/component/settingSystem/view.jsx
+++ /dev/null
@@ -1,410 +0,0 @@
-// @flow
-import { ALERT } from 'constants/icons';
-import { SETTINGS_GRP } from 'constants/settings';
-import React from 'react';
-import Button from 'component/button';
-import Card from 'component/common/card';
-import { FormField } from 'component/common/form';
-import FileSelector from 'component/common/file-selector';
-import I18nMessage from 'component/i18nMessage';
-import SettingAutoLaunch from 'component/settingAutoLaunch';
-import SettingClosingBehavior from 'component/settingClosingBehavior';
-import SettingCommentsServer from 'component/settingCommentsServer';
-import SettingsRow from 'component/settingsRow';
-import SettingWalletServer from 'component/settingWalletServer';
-import Spinner from 'component/spinner';
-import { getPasswordFromCookie } from 'util/saved-passwords';
-
-// @if TARGET='app'
-const IS_MAC = process.platform === 'darwin';
-// @endif
-
-type Price = {
- currency: string,
- amount: number,
-};
-
-type SetDaemonSettingArg = boolean | string | number | Price;
-
-type DaemonSettings = {
- download_dir: string,
- share_usage_data: boolean,
- max_key_fee?: Price,
- max_connections_per_download?: number,
- save_files: boolean,
- save_blobs: boolean,
- ffmpeg_path: string,
-};
-
-type Props = {
- // --- select ---
- daemonSettings: DaemonSettings,
- ffmpegStatus: { available: boolean, which: string },
- findingFFmpeg: boolean,
- walletEncrypted: boolean,
- isAuthenticated: boolean,
- allowAnalytics: boolean,
- // --- perform ---
- setDaemonSetting: (string, ?SetDaemonSettingArg) => void,
- clearDaemonSetting: (string) => void,
- clearCache: () => Promise,
- findFFmpeg: () => void,
- encryptWallet: () => void,
- decryptWallet: () => void,
- updateWalletStatus: () => void,
- confirmForgetPassword: ({}) => void,
- toggle3PAnalytics: (boolean) => void,
-};
-
-export default function SettingSystem(props: Props) {
- const {
- daemonSettings,
- ffmpegStatus,
- findingFFmpeg,
- walletEncrypted,
- isAuthenticated,
- allowAnalytics,
- setDaemonSetting,
- clearDaemonSetting,
- clearCache,
- findFFmpeg,
- encryptWallet,
- decryptWallet,
- updateWalletStatus,
- confirmForgetPassword,
- toggle3PAnalytics,
- } = props;
-
- const [clearingCache, setClearingCache] = React.useState(false);
- const [storedPassword, setStoredPassword] = React.useState(false);
-
- // @if TARGET='app'
- const { available: ffmpegAvailable, which: ffmpegPath } = ffmpegStatus;
- // @endif
-
- function onChangeEncryptWallet() {
- if (walletEncrypted) {
- decryptWallet();
- } else {
- encryptWallet();
- }
- }
-
- function onConfirmForgetPassword() {
- confirmForgetPassword({ callback: () => setStoredPassword(false) });
- }
-
- // Update ffmpeg variables
- React.useEffect(() => {
- // @if TARGET='app'
- const { available } = ffmpegStatus;
- const { ffmpeg_path: ffmpegPath } = daemonSettings;
- if (!available) {
- if (ffmpegPath) {
- clearDaemonSetting('ffmpeg_path');
- }
- findFFmpeg();
- }
- // @endif
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
-
- // Update storedPassword state
- React.useEffect(() => {
- if (isAuthenticated || !IS_WEB) {
- updateWalletStatus();
- getPasswordFromCookie().then((p) => {
- if (typeof p === 'string') {
- setStoredPassword(true);
- }
- });
- }
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
-
- return (
- <>
-
-
{__('System')}
-
-
- {/* @if TARGET='app' */}
-
- {
- setDaemonSetting('download_dir', newDirectory.path);
- }}
- />
-
- {/* @endif */}
-
- {/* @if TARGET='app' */}
-
- setDaemonSetting('save_files', !daemonSettings.save_files)}
- checked={daemonSettings.save_files}
- />
-
-
- {__("If disabled, LBRY will be very sad and you won't be helping improve the network.")}{' '}
- .
-
- }
- >
- setDaemonSetting('save_blobs', !daemonSettings.save_blobs)}
- checked={daemonSettings.save_blobs}
- />
-
- {/* @endif */}
-
- {/* @if TARGET='app' */}
-
- {__(
- `This is information like error logging, performance tracking, and usage statistics. It includes your IP address and basic system details, but no other identifying information (unless you sign in to lbry.tv)`
- )}{' '}
-
-
- }
- multirow
- >
- setDaemonSetting('share_usage_data', !daemonSettings.share_usage_data)}
- checked={daemonSettings.share_usage_data}
- label={{__('Allow the app to share data to LBRY.inc')} }
- helper={
- isAuthenticated
- ? __('Internal sharing is required while signed in.')
- : __('Internal sharing is required to participate in rewards programs.')
- }
- disabled={isAuthenticated && daemonSettings.share_usage_data}
- />
- toggle3PAnalytics(e.target.checked)}
- checked={allowAnalytics}
- label={__('Allow the app to access third party analytics platforms')}
- helper={__('We use detailed analytics to improve all aspects of the LBRY experience.')}
- />
-
- {/* @endif */}
-
- {/* @if TARGET='app' */}
- {/* Auto launch in a hidden state doesn't work on mac https://github.com/Teamwork/node-auto-launch/issues/81 */}
- {!IS_MAC && (
-
-
-
- )}
- {/* @endif */}
-
- {/* @if TARGET='app' */}
-
-
-
- {/* @endif */}
-
- {/* @if TARGET='app' */}
-
- {__('Automatic transcoding')}
- {findingFFmpeg && }
-
- }
- >
- {
- // $FlowFixMe
- setDaemonSetting('ffmpeg_path', newDirectory.path);
- findFFmpeg();
- }}
- disabled={Boolean(ffmpegPath)}
- />
-
- {ffmpegAvailable ? (
-
- ),
- }}
- >
- FFmpeg is correctly configured. %learn_more%
-
- ) : (
- findFFmpeg()}
- disabled={findingFFmpeg}
- />
- ),
- learn_more: (
-
- ),
- }}
- >
- FFmpeg could not be found. Navigate to it or Install, Then %check_again% or quit and restart the
- app. %learn_more%
-
- )}
-
-
- {/* @endif */}
-
- {/* @if TARGET='app' */}
-
-
- ),
- }}
- >
- Wallet encryption is currently unavailable until it's supported for synced accounts. It will be
- added back soon. %learn_more%.
-
- {/* {__('Secure your local wallet data with a custom password.')}{' '}
- {__('Lost passwords cannot be recovered.')}
- . */}
-
- }
- >
- onChangeEncryptWallet()}
- checked={walletEncrypted}
- />
-
-
- {walletEncrypted && storedPassword && (
-
-
-
- )}
- {/* @endif */}
-
- {/* @if TARGET='app' */}
-
- {/* Disabling below until we get downloads to work with shared subscriptions code */}
- {/*
- setClientSetting(SETTINGS.AUTO_DOWNLOAD, !autoDownload)}
- checked={autoDownload}
- label={__('Automatically download new content from my subscriptions')}
- helper={__(
- "The latest file from each of your subscriptions will be downloaded for quick access as soon as it's published."
- )}
- />
- */}
-
-
- setDaemonSetting('max_connections_per_download', e.target.value)}
- value={daemonSettings.max_connections_per_download}
- >
- {[1, 2, 4, 6, 10, 20].map((connectionOption) => (
-
- {connectionOption}
-
- ))}
-
-
-
-
-
-
-
-
-
-
-
- {/* @endif */}
-
-
- {
- setClearingCache(true);
- clearCache();
- }}
- disabled={clearingCache}
- />
-
- >
- }
- />
- >
- );
-}
diff --git a/ui/component/settingUnauthenticated/index.js b/ui/component/settingUnauthenticated/index.js
deleted file mode 100644
index 8476d4a40..000000000
--- a/ui/component/settingUnauthenticated/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { connect } from 'react-redux';
-import { SETTINGS } from 'lbry-redux';
-import { doSetClientSetting } from 'redux/actions/settings';
-import { selectLanguage, makeSelectClientSetting } from 'redux/selectors/settings';
-
-import SettingUnauthenticated from './view';
-
-const select = (state) => ({
- searchInLanguage: makeSelectClientSetting(SETTINGS.SEARCH_IN_LANGUAGE)(state),
- language: selectLanguage(state),
-});
-
-const perform = (dispatch) => ({
- setSearchInLanguage: (value) => dispatch(doSetClientSetting(SETTINGS.SEARCH_IN_LANGUAGE, value)),
-});
-
-export default connect(select, perform)(SettingUnauthenticated);
diff --git a/ui/component/settingUnauthenticated/view.jsx b/ui/component/settingUnauthenticated/view.jsx
deleted file mode 100644
index c47540966..000000000
--- a/ui/component/settingUnauthenticated/view.jsx
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Settings that we allow for unauthenticated users.
- */
-
-// @flow
-import React from 'react';
-import Card from 'component/common/card';
-import { FormField } from 'component/common/form';
-import HomepageSelector from 'component/homepageSelector';
-import SettingLanguage from 'component/settingLanguage';
-import SettingsRow from 'component/settingsRow';
-// $FlowFixMe
-import homepages from 'homepages';
-
-type Props = {
- searchInLanguage: boolean,
- setSearchInLanguage: (boolean) => void,
-};
-
-export default function SettingUnauthenticated(props: Props) {
- const { searchInLanguage, setSearchInLanguage } = props;
-
- return (
-
-
-
-
-
-
- setSearchInLanguage(!searchInLanguage)}
- />
-
-
- {homepages && Object.keys(homepages).length > 1 && (
-
-
-
- )}
- >
- }
- />
- );
-}
-
-// prettier-ignore
-const HELP_LANGUAGE = 'Multi-language support is brand new and incomplete. Switching your language may have unintended consequences, like glossolalia.';
diff --git a/ui/component/settingWalletServer/view.jsx b/ui/component/settingWalletServer/view.jsx
index 3f2b962d4..2d96cdf39 100644
--- a/ui/component/settingWalletServer/view.jsx
+++ b/ui/component/settingWalletServer/view.jsx
@@ -24,7 +24,7 @@ type DaemonStatus = {
type Props = {
getDaemonStatus: () => void,
- setCustomWalletServers: (any) => void,
+ setCustomWalletServers: any => void,
clearWalletServers: () => void,
customWalletServers: ServerConfig,
saveServerConfig: (Array) => void,
@@ -115,7 +115,7 @@ function SettingWalletServer(props: Props) {
name="default_wallet_servers"
checked={!advancedMode}
label={__('Use official lbry.tv wallet servers')}
- onChange={(e) => {
+ onChange={e => {
if (e.target.checked) {
doClear();
}
@@ -125,7 +125,7 @@ function SettingWalletServer(props: Props) {
type="radio"
name="custom_wallet_servers"
checked={advancedMode}
- onChange={(e) => {
+ onChange={e => {
setAdvancedMode(e.target.checked);
if (e.target.checked && customWalletServers.length) {
setCustomWalletServers(stringifyServerParam(customWalletServers));
@@ -140,7 +140,7 @@ function SettingWalletServer(props: Props) {
}}
>
Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content
- shows in trending or is blocked. %learn_more%
+ shows in trending or is blocked. %learn_more%.
@@ -150,7 +150,7 @@ function SettingWalletServer(props: Props) {
serverConfig.map((entry, index) => {
const [host, port] = entry;
const available = activeWalletServers.some(
- (s) => s.host === entry[0] && String(s.port) === entry[1] && s.availability
+ s => s.host === entry[0] && String(s.port) === entry[1] && s.availability
);
return (
diff --git a/ui/component/settingsRow/index.js b/ui/component/settingsRow/index.js
deleted file mode 100644
index a8d6ab489..000000000
--- a/ui/component/settingsRow/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import SettingsRow from './view';
-export default SettingsRow;
diff --git a/ui/component/settingsRow/view.jsx b/ui/component/settingsRow/view.jsx
deleted file mode 100644
index a59b7e52b..000000000
--- a/ui/component/settingsRow/view.jsx
+++ /dev/null
@@ -1,36 +0,0 @@
-// @flow
-import React from 'react';
-import classnames from 'classnames';
-
-type Props = {
- title: string,
- subtitle?: string,
- multirow?: boolean, // Displays the Value widget(s) below the Label instead of on the right.
- useVerticalSeparator?: boolean, // Show a separator line between Label and Value. Useful when there are multiple Values.
- children?: React$Node,
-};
-
-export default function SettingsRow(props: Props) {
- const { title, subtitle, multirow, useVerticalSeparator, children } = props;
-
- return (
-
-
-
{title}
- {subtitle &&
{subtitle}
}
-
-
- {children && children}
-
-
- );
-}
diff --git a/ui/component/settingsSideNavigation/index.js b/ui/component/settingsSideNavigation/index.js
deleted file mode 100644
index 10fc85e83..000000000
--- a/ui/component/settingsSideNavigation/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import SettingsSideNavigation from './view';
-
-export default SettingsSideNavigation;
diff --git a/ui/component/settingsSideNavigation/view.jsx b/ui/component/settingsSideNavigation/view.jsx
deleted file mode 100644
index e791e7ffb..000000000
--- a/ui/component/settingsSideNavigation/view.jsx
+++ /dev/null
@@ -1,159 +0,0 @@
-// @flow
-import * as PAGES from 'constants/pages';
-import * as ICONS from 'constants/icons';
-import { SETTINGS_GRP } from 'constants/settings';
-import type { Node } from 'react';
-import React from 'react';
-import { useHistory } from 'react-router-dom';
-import classnames from 'classnames';
-import Button from 'component/button';
-// @if TARGET='app'
-import { IS_MAC } from 'component/app/view';
-// @endif
-import { useIsMediumScreen } from 'effects/use-screensize';
-
-type SideNavLink = {
- title: string,
- link?: string,
- route?: string,
- section?: string,
- onClick?: () => any,
- icon: string,
- extra?: Node,
-};
-
-const SIDE_LINKS: Array = [
- {
- title: 'Appearance',
- section: SETTINGS_GRP.APPEARANCE,
- icon: ICONS.APPEARANCE,
- },
- {
- title: 'Account',
- section: SETTINGS_GRP.ACCOUNT,
- icon: ICONS.ACCOUNT,
- },
- {
- title: 'Content settings',
- section: SETTINGS_GRP.CONTENT,
- icon: ICONS.CONTENT,
- },
- {
- title: 'System',
- section: SETTINGS_GRP.SYSTEM,
- icon: ICONS.SETTINGS,
- },
-];
-
-export default function SettingsSideNavigation() {
- const sidebarOpen = true;
- const isMediumScreen = useIsMediumScreen();
- const isAbsolute = isMediumScreen;
- const microNavigation = !sidebarOpen || isMediumScreen;
- const { location, goBack } = useHistory();
-
- function scrollToSection(section: string) {
- const TOP_MARGIN_PX = 20;
- const element = document.getElementById(section);
- if (element) {
- window.scrollTo(0, element.offsetTop - TOP_MARGIN_PX);
- }
- }
-
- function getOnClickHandler(section) {
- if (section) {
- if (location.pathname === `/$/${PAGES.SETTINGS}`) {
- return () => scrollToSection(section);
- } else if (location.pathname.startsWith(`/$/${PAGES.SETTINGS}/`)) {
- return () => {
- goBack();
- setTimeout(() => scrollToSection(section), 5);
- };
- }
- }
-
- return undefined;
- }
-
- if (isMediumScreen) {
- // I think it's ok to hide it for now on medium/small screens given that
- // we are using a scrolling Settings Page that displays everything. If we
- // really need this, most likely we can display it as a Tab at the top
- // of the page.
- return null;
- }
-
- return (
-
-
-
-
- {SIDE_LINKS.map((linkProps) => {
- return (
-
-
- {linkProps.extra && linkProps.extra}
-
- );
- })}
-
-
-
-
- {isMediumScreen && sidebarOpen && (
- <>
-
-
-
- {SIDE_LINKS.map((linkProps) => {
- // $FlowFixMe
- const { link, route, ...passedProps } = linkProps;
- return (
-
-
- {linkProps.extra && linkProps.extra}
-
- );
- })}
-
-
-
- >
- )}
-
- );
-}
diff --git a/ui/component/syncToggle/view.jsx b/ui/component/syncToggle/view.jsx
index c795ed1b7..2a885ecf3 100644
--- a/ui/component/syncToggle/view.jsx
+++ b/ui/component/syncToggle/view.jsx
@@ -2,15 +2,14 @@
import * as MODALS from 'constants/modal_types';
import React from 'react';
import Button from 'component/button';
-import SettingsRow from 'component/settingsRow';
import { withRouter } from 'react-router';
import { FormField } from 'component/common/form';
type Props = {
- setSyncEnabled: (boolean) => void,
+ setSyncEnabled: boolean => void,
syncEnabled: boolean,
verifiedEmail: ?string,
- history: { push: (string) => void },
+ history: { push: string => void },
location: UrlLocation,
getSyncError: ?string,
disabled: boolean,
@@ -21,30 +20,23 @@ function SyncToggle(props: Props) {
const { verifiedEmail, openModal, syncEnabled, disabled } = props;
return (
-
- openModal(MODALS.SYNC_ENABLE, { mode: syncEnabled ? 'disable' : 'enable' })}
- disabled={disabled || !verifiedEmail}
- helper={
- disabled
- ? __("To enable Sync, close LBRY completely and check 'Remember Password' during wallet unlock.")
- : null
- }
- />
- {!verifiedEmail && (
+
+ {!verifiedEmail ? (
-
{__('An email address is required to sync your account.')}
+
{__('An email address is required to sync your account.')}
+ ) : (
+
openModal(MODALS.SYNC_ENABLE, { mode: syncEnabled ? 'disable' : 'enable' })}
+ disabled={disabled}
+ />
)}
-
+
);
}
diff --git a/ui/component/themeSelector/index.js b/ui/component/themeSelector/index.js
deleted file mode 100644
index 926a41546..000000000
--- a/ui/component/themeSelector/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { connect } from 'react-redux';
-import { SETTINGS } from 'lbry-redux';
-import { doSetClientSetting, doSetDarkTime } from 'redux/actions/settings';
-import { makeSelectClientSetting } from 'redux/selectors/settings';
-import ThemeSelector from './view';
-
-const select = (state) => ({
- currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state),
- themes: makeSelectClientSetting(SETTINGS.THEMES)(state),
- automaticDarkModeEnabled: makeSelectClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED)(state),
- darkModeTimes: makeSelectClientSetting(SETTINGS.DARK_MODE_TIMES)(state),
- clock24h: makeSelectClientSetting(SETTINGS.CLOCK_24H)(state),
-});
-
-const perform = (dispatch) => ({
- setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
- setDarkTime: (time, options) => dispatch(doSetDarkTime(time, options)),
-});
-
-export default connect(select, perform)(ThemeSelector);
diff --git a/ui/component/themeSelector/view.jsx b/ui/component/themeSelector/view.jsx
deleted file mode 100644
index 2f7985d16..000000000
--- a/ui/component/themeSelector/view.jsx
+++ /dev/null
@@ -1,128 +0,0 @@
-// @flow
-import React from 'react';
-import { SETTINGS } from 'lbry-redux';
-import { FormField } from 'component/common/form';
-
-type SetDaemonSettingArg = boolean | string | number;
-
-type DarkModeTimes = {
- from: { hour: string, min: string, formattedTime: string },
- to: { hour: string, min: string, formattedTime: string },
-};
-
-type OptionTimes = {
- fromTo: string,
- time: string,
-};
-
-type Props = {
- currentTheme: string,
- themes: Array,
- automaticDarkModeEnabled: boolean,
- darkModeTimes: DarkModeTimes,
- clock24h: boolean,
- setClientSetting: (string, SetDaemonSettingArg) => void,
- setDarkTime: (string, {}) => void,
-};
-
-export default function ThemeSelector(props: Props) {
- const {
- currentTheme,
- themes,
- automaticDarkModeEnabled,
- darkModeTimes,
- clock24h,
- setClientSetting,
- setDarkTime,
- } = props;
-
- const startHours = ['18', '19', '20', '21'];
- const endHours = ['5', '6', '7', '8'];
-
- function onThemeChange(event: SyntheticInputEvent<*>) {
- const { value } = event.target;
- if (value === 'dark') {
- onAutomaticDarkModeChange(false);
- }
- setClientSetting(SETTINGS.THEME, value);
- }
-
- function onAutomaticDarkModeChange(value: boolean) {
- setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, value);
- }
-
- function onChangeTime(event: SyntheticInputEvent<*>, options: OptionTimes) {
- setDarkTime(event.target.value, options);
- }
-
- function formatHour(time: string, clock24h: boolean) {
- if (clock24h) {
- return `${time}:00`;
- }
-
- const now = new Date(0, 0, 0, Number(time));
- return now.toLocaleTimeString('en-US', { hour12: true, hour: '2-digit' });
- }
-
- return (
- <>
-
-
- {themes.map((theme) => (
-
- {theme === 'light' ? __('Light') : __('Dark')}
-
- ))}
-
-
-
-
- onAutomaticDarkModeChange(!automaticDarkModeEnabled)}
- checked={automaticDarkModeEnabled}
- label={__('Automatic dark mode')}
- />
-
- {automaticDarkModeEnabled && (
-
- onChangeTime(value, { fromTo: 'from', time: 'hour' })}
- value={darkModeTimes.from.hour}
- label={__('From --[initial time]--')}
- >
- {startHours.map((time) => (
-
- {formatHour(time, clock24h)}
-
- ))}
-
-
- onChangeTime(value, { fromTo: 'to', time: 'hour' })}
- value={darkModeTimes.to.hour}
- >
- {endHours.map((time) => (
-
- {formatHour(time, clock24h)}
-
- ))}
-
-
- )}
-
- >
- );
-}
diff --git a/ui/component/txoList/view.jsx b/ui/component/txoList/view.jsx
index e07b3e6b1..3c1a574b5 100644
--- a/ui/component/txoList/view.jsx
+++ b/ui/component/txoList/view.jsx
@@ -12,6 +12,20 @@ import { toCapitalCase } from 'util/string';
import classnames from 'classnames';
import HelpLink from 'component/common/help-link';
import FileExporter from 'component/common/file-exporter';
+import WalletFiatPaymentHistory from 'component/walletFiatPaymentHistory';
+import WalletFiatAccountHistory from 'component/walletFiatAccountHistory';
+import { Lbryio } from 'lbryinc';
+import { getStripeEnvironment } from 'util/stripe';
+let stripeEnvironment = getStripeEnvironment();
+
+// constants to be used in query params
+const QUERY_NAME_CURRENCY = 'currency';
+const QUERY_NAME_TAB = 'tab';
+const QUERY_NAME_FIAT_TYPE = 'fiatType';
+// TODO: this tab will be renamed
+const DEFAULT_CURRENCY_PARAM = 'credits';
+const DEFAULT_TAB_PARAM = 'fiat-payment-history';
+const DEFAULT_FIAT_TYPE_PARAM = 'incoming';
type Props = {
search: string,
@@ -28,7 +42,7 @@ type Props = {
};
type Delta = {
- dkey: string,
+ changedParameterKey: string,
value: string,
};
@@ -45,12 +59,91 @@ function TxoList(props: Props) {
transactionsFile,
} = props;
+ const [accountTransactionResponse, setAccountTransactionResponse] = React.useState([]);
+ const [customerTransactions, setCustomerTransactions] = React.useState([]);
+
+ function getPaymentHistory() {
+ return Lbryio.call(
+ 'customer',
+ 'list',
+ {
+ environment: stripeEnvironment,
+ },
+ 'post'
+ );
+ }
+
+ function getAccountTransactions() {
+ return Lbryio.call(
+ 'account',
+ 'list',
+ {
+ environment: stripeEnvironment,
+ },
+ 'post'
+ );
+ }
+
+ // calculate account transactions section
+ React.useEffect(() => {
+ (async function() {
+ try {
+ const accountTransactionResponse = await getAccountTransactions();
+
+ // reverse so order is from most recent to latest
+ if (accountTransactionResponse && accountTransactionResponse.length) {
+ accountTransactionResponse.reverse();
+ }
+
+ // TODO: remove this once pagination is implemented
+ if (accountTransactionResponse && accountTransactionResponse.length && accountTransactionResponse.length > 25) {
+ accountTransactionResponse.length = 25;
+ }
+
+ setAccountTransactionResponse(accountTransactionResponse);
+ } catch (err) {
+ console.log(err);
+ }
+ })();
+ }, []);
+
+ // populate customer payment data
+ React.useEffect(() => {
+ (async function() {
+ try {
+ // get card payments customer has made
+ let customerTransactionResponse = await getPaymentHistory();
+ // console.log('amount of transactions');
+ // console.log(customerTransactionResponse.length);
+
+ // reverse so order is from most recent to latest
+ if (customerTransactionResponse && customerTransactionResponse.length) {
+ customerTransactionResponse.reverse();
+ }
+
+ // TODO: remove this once pagination is implemented
+ if (customerTransactionResponse && customerTransactionResponse.length && customerTransactionResponse.length > 25) {
+ customerTransactionResponse.length = 25;
+ }
+
+ setCustomerTransactions(customerTransactionResponse);
+ } catch (err) {
+ console.log(err);
+ }
+ })();
+ }, []);
+
const urlParams = new URLSearchParams(search);
const page = urlParams.get(TXO.PAGE) || String(1);
const pageSize = urlParams.get(TXO.PAGE_SIZE) || String(TXO.PAGE_SIZE_DEFAULT);
const type = urlParams.get(TXO.TYPE) || TXO.ALL;
const subtype = urlParams.get(TXO.SUB_TYPE);
const active = urlParams.get(TXO.ACTIVE) || TXO.ALL;
+ const currency = urlParams.get(QUERY_NAME_CURRENCY) || DEFAULT_CURRENCY_PARAM;
+ const fiatType = urlParams.get(QUERY_NAME_FIAT_TYPE) || DEFAULT_FIAT_TYPE_PARAM;
+ // tab used in the wallet section
+ // TODO: need to change this eventually
+ const tab = urlParams.get(QUERY_NAME_TAB) || DEFAULT_TAB_PARAM;
const currentUrlParams = {
page,
@@ -58,11 +151,15 @@ function TxoList(props: Props) {
active,
type,
subtype,
+ currency,
+ fiatType,
+ tab,
};
const hideStatus =
type === TXO.SENT || (currentUrlParams.type === TXO.RECEIVED && currentUrlParams.subtype !== TXO.TIP);
+ // this is for sdk params
const params = {};
if (currentUrlParams.type) {
if (currentUrlParams.type === TXO.ALL) {
@@ -121,7 +218,8 @@ function TxoList(props: Props) {
function updateUrl(delta: Delta) {
const newUrlParams = new URLSearchParams();
- switch (delta.dkey) {
+
+ switch (delta.changedParameterKey) {
case TXO.PAGE:
if (currentUrlParams.type) {
newUrlParams.set(TXO.TYPE, currentUrlParams.type);
@@ -133,6 +231,8 @@ function TxoList(props: Props) {
newUrlParams.set(TXO.ACTIVE, currentUrlParams.active);
}
newUrlParams.set(TXO.PAGE, delta.value);
+ newUrlParams.set(QUERY_NAME_TAB, currentUrlParams.tab);
+ newUrlParams.set(QUERY_NAME_CURRENCY, currentUrlParams.currency);
break;
case TXO.TYPE:
newUrlParams.set(TXO.TYPE, delta.value);
@@ -151,6 +251,8 @@ function TxoList(props: Props) {
}
newUrlParams.set(TXO.PAGE, String(1));
newUrlParams.set(TXO.PAGE_SIZE, currentUrlParams.pageSize);
+ newUrlParams.set(QUERY_NAME_TAB, currentUrlParams.tab);
+ newUrlParams.set(QUERY_NAME_CURRENCY, currentUrlParams.currency);
break;
case TXO.SUB_TYPE:
if (currentUrlParams.type) {
@@ -160,6 +262,8 @@ function TxoList(props: Props) {
newUrlParams.set(TXO.SUB_TYPE, delta.value);
newUrlParams.set(TXO.PAGE, String(1));
newUrlParams.set(TXO.PAGE_SIZE, currentUrlParams.pageSize);
+ newUrlParams.set(QUERY_NAME_TAB, currentUrlParams.tab);
+ newUrlParams.set(QUERY_NAME_CURRENCY, currentUrlParams.currency);
break;
case TXO.ACTIVE:
if (currentUrlParams.type) {
@@ -171,6 +275,25 @@ function TxoList(props: Props) {
newUrlParams.set(TXO.ACTIVE, delta.value);
newUrlParams.set(TXO.PAGE, String(1));
newUrlParams.set(TXO.PAGE_SIZE, currentUrlParams.pageSize);
+ newUrlParams.set(QUERY_NAME_TAB, currentUrlParams.tab);
+ newUrlParams.set(QUERY_NAME_CURRENCY, currentUrlParams.currency);
+ break;
+ // toggling the currency type (lbc/fiat)
+ case QUERY_NAME_CURRENCY:
+ newUrlParams.set(QUERY_NAME_CURRENCY, delta.value);
+ newUrlParams.set(QUERY_NAME_TAB, currentUrlParams.tab);
+ // only set fiat type (incoming|outgoing) if fiat is being used
+ if (delta.value === 'credits') {
+ newUrlParams.delete(QUERY_NAME_FIAT_TYPE);
+ } else {
+ newUrlParams.set(QUERY_NAME_FIAT_TYPE, currentUrlParams.fiatType);
+ }
+ break;
+ // toggling the fiat type (incoming/outgoing)
+ case QUERY_NAME_FIAT_TYPE:
+ newUrlParams.set(QUERY_NAME_FIAT_TYPE, delta.value);
+ newUrlParams.set(QUERY_NAME_TAB, currentUrlParams.tab);
+ newUrlParams.set(QUERY_NAME_CURRENCY, currentUrlParams.currency);
break;
}
@@ -188,63 +311,58 @@ function TxoList(props: Props) {
return (
{__(`Transactions`)}}
- titleActions={
-
- {!isFetchingTransactions && transactionsFile === null && (
-
{{__('Failed to process fetched data.')} }
- )}
-
-
fetchTransactions()}
- progressMsg={isFetchingTransactions ? __('Fetching data') : ''}
- />
+ title={
+ <>{__(`Transactions`)}
+
+
+ {/* toggle between LBC and fiat buttons */}
+
+ {/* toggle to LBC */}
+ handleChange({ changedParameterKey: QUERY_NAME_CURRENCY, value: 'credits' })}
+ className={classnames(`button-toggle`, {
+ 'button-toggle--active': currency === 'credits',
+ })}
+ label={__('Credits')}
+ />
+ {/* toggle to fiat */}
+ handleChange({ changedParameterKey: QUERY_NAME_CURRENCY, value: 'fiat' })}
+ className={classnames(`button-toggle`, {
+ 'button-toggle--active': currency === 'fiat',
+ })}
+ label={__('USD')}
+ />
+
+
- fetchTxoPage()} />
-
+ >
+
}
isBodyList
- body={
-
+ body={currency === 'credits'
+ ?
+ {/* LBC transactions section */}
-
-
-
- {__('Type')}
-
- >
- }
- value={type || 'all'}
- onChange={(e) => handleChange({ dkey: TXO.TYPE, value: e.target.value })}
- >
- {Object.values(TXO.DROPDOWN_TYPES).map((v) => {
- const stringV = String(v);
- return (
-
- {stringV && __(toCapitalCase(stringV))}
-
- );
- })}
-
-
- {(type === TXO.SENT || type === TXO.RECEIVED) && (
+
+
+ {/* LBC transaction type dropdown */}
handleChange({ dkey: TXO.SUB_TYPE, value: e.target.value })}
+ name="type"
+ label={
+ <>
+ {__('Type')}
+
+ >
+ }
+ value={type || 'all'}
+ onChange={(e) => handleChange({ changedParameterKey: TXO.TYPE, value: e.target.value, tab })}
>
- {Object.values(TXO.DROPDOWN_SUBTYPES).map((v) => {
+ {Object.values(TXO.DROPDOWN_TYPES).map((v) => {
const stringV = String(v);
return (
@@ -254,46 +372,127 @@ function TxoList(props: Props) {
})}
- )}
- {!hideStatus && (
+ {(type === TXO.SENT || type === TXO.RECEIVED) && (
+
+ handleChange({ changedParameterKey: TXO.SUB_TYPE, value: e.target.value, tab })}
+ >
+ {Object.values(TXO.DROPDOWN_SUBTYPES).map((v) => {
+ const stringV = String(v);
+ return (
+
+ {stringV && __(toCapitalCase(stringV))}
+
+ );
+ })}
+
+
+ )}
+ {!hideStatus && (
+
+
+ {__('Status')}
+
+ {/* active transactions button */}
+ handleChange({ changedParameterKey: TXO.ACTIVE, value: 'active' })}
+ className={classnames(`button-toggle`, {
+ 'button-toggle--active': active === TXO.ACTIVE,
+ })}
+ label={__('Active')}
+ />
+ {/* historical transactions button */}
+ handleChange({ changedParameterKey: TXO.ACTIVE, value: 'spent' })}
+ className={classnames(`button-toggle`, {
+ 'button-toggle--active': active === 'spent',
+ })}
+ label={__('Historical')}
+ />
+ {/* all transactions button */}
+ handleChange({ changedParameterKey: TXO.ACTIVE, value: 'all' })}
+ className={classnames(`button-toggle`, {
+ 'button-toggle--active': active === 'all',
+ })}
+ label={__('All')}
+ />
+
+
+
+ )}
+
+ {/* export and refresh buttons */}
+
+ {!isFetchingTransactions && transactionsFile === null && (
+
{{__('Failed to process fetched data.')} }
+ )}
+
+ fetchTransactions()}
+ progressMsg={isFetchingTransactions ? __('Fetching data') : ''}
+ />
+
+
fetchTxoPage()} />
+
+
+
+ {/* listing of the lbc transactions */}
+
+
+
+ :
+ {/* FIAT SECTION ( toggle buttons and transactions) */}
+
+
+
- {__('Status')}
+ {__('Type')}
+ {/* incoming transactions button */}
handleChange({ dkey: TXO.ACTIVE, value: 'active' })}
+ onClick={(e) => handleChange({ changedParameterKey: QUERY_NAME_FIAT_TYPE, value: 'incoming'})}
className={classnames(`button-toggle`, {
- 'button-toggle--active': active === TXO.ACTIVE,
+ 'button-toggle--active': fiatType === 'incoming',
})}
- label={__('Active')}
+ label={__('Incoming')}
/>
+ {/* incoming transactions button */}
handleChange({ dkey: TXO.ACTIVE, value: 'spent' })}
+ onClick={(e) => handleChange({ changedParameterKey: QUERY_NAME_FIAT_TYPE, value: 'outgoing'})}
className={classnames(`button-toggle`, {
- 'button-toggle--active': active === 'spent',
+ 'button-toggle--active': fiatType === 'outgoing',
})}
- label={__('Historical')}
- />
- handleChange({ dkey: TXO.ACTIVE, value: 'all' })}
- className={classnames(`button-toggle`, {
- 'button-toggle--active': active === 'all',
- })}
- label={__('All')}
+ label={__('Outgoing')}
/>
- )}
+
+ {/* listing of the transactions */}
+ { fiatType === 'incoming' &&
}
+ { fiatType === 'outgoing' &&
}
+ {/* TODO: have to finish pagination */}
+ {/*
*/}
-
-
}
+
/>
);
}
diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx
index a3fcc48de..73ee97457 100644
--- a/ui/component/viewers/videoViewer/internal/videojs.jsx
+++ b/ui/component/viewers/videoViewer/internal/videojs.jsx
@@ -1,6 +1,6 @@
// @flow
import React, { useEffect, useRef, useState } from 'react';
-// import { SIMPLE_SITE } from 'config';
+import { SIMPLE_SITE } from 'config';
import Button from 'component/button';
import * as ICONS from 'constants/icons';
import classnames from 'classnames';
@@ -14,8 +14,7 @@ import recsys from './plugins/videojs-recsys/plugin';
import qualityLevels from 'videojs-contrib-quality-levels';
import isUserTyping from 'util/detect-typing';
// @if TARGET='web'
-// Disabled for now.
-// import './plugins/videojs-aniview/plugin';
+import './plugins/videojs-aniview/plugin';
// @endif
const isDev = process.env.NODE_ENV !== 'production';
@@ -57,7 +56,7 @@ type Props = {
adUrl: ?string,
claimId: ?string,
userId: ?number,
- // allowPreRoll: ?boolean,
+ allowPreRoll: ?boolean,
shareTelemetry: boolean,
};
@@ -195,7 +194,7 @@ export default React.memo
(function VideoJs(props: Props) {
adUrl,
claimId,
userId,
- // allowPreRoll,
+ allowPreRoll,
shareTelemetry,
} = props;
@@ -588,10 +587,9 @@ export default React.memo(function VideoJs(props: Props) {
// otherwise a race condition occurs if we place this in the onReady call back
// allow if isDev because otherwise you'll never see ads when basing to master
// @if TARGET='web'
- // DISABLED FOR NOW
- // if ((allowPreRoll && SIMPLE_SITE) || isDev) {
- // vjs.aniview();
- // }
+ if ((allowPreRoll && SIMPLE_SITE) || isDev) {
+ vjs.aniview();
+ }
// @endif
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
diff --git a/ui/component/walletBalance/view.jsx b/ui/component/walletBalance/view.jsx
index 6746d5c36..5288b63d5 100644
--- a/ui/component/walletBalance/view.jsx
+++ b/ui/component/walletBalance/view.jsx
@@ -10,6 +10,7 @@ import Card from 'component/common/card';
import LbcSymbol from 'component/common/lbc-symbol';
import I18nMessage from 'component/i18nMessage';
import { formatNumberWithCommas } from 'util/number';
+import WalletFiatBalance from 'component/walletFiatBalance';
type Props = {
balance: number,
@@ -63,124 +64,139 @@ const WalletBalance = (props: Props) => {
}, [doFetchUtxoCounts, balance, detailsExpanded]);
return (
- }
- subtitle={
- totalLocked > 0 ? (
- }}>
- Your total balance. All of this is yours, but some %lbc% is in use on channels and content right now.
-
- ) : (
- {__('Your total balance.')}
- )
- }
- actions={
- <>
-
- }}>
- %lbc_amount% immediately spendable
-
-
-
-
- ,
- }}
- >
- %lbc_amount% boosting content
-
- setDetailsExpanded(!detailsExpanded)}
- />
-
- {detailsExpanded && (
-
-
-
- {__('...earned from others')}
- ({__('Unlock to spend')})
-
-
-
- {Boolean(tipsBalance) && (
- doOpenModal(MODALS.MASS_TIP_UNLOCK)}
- />
- )}
-
-
-
-
-
- {__('...on initial publishes')}
- ({__('Delete or edit past content to spend')})
-
-
-
-
-
-
- {__('...supporting content')}
- ({__('Delete supports to spend')})
-
-
-
-
-
-
- )}
-
- {/* @if TARGET='app' */}
- {hasSynced ? (
-
- {__('A backup of your wallet is synced with lbry.tv.')}
-
-
- ) : (
-
- {__('Your wallet is not currently synced with lbry.tv. You are in control of backing up your wallet.')}
-
-
- )}
- {/* @endif */}
-
-
-
-
-
- {(otherCount > WALLET_CONSOLIDATE_UTXOS || consolidateIsPending || consolidatingUtxos) && (
-
- doUtxoConsolidate()}
- disabled={operationPending}
- label={
- consolidateIsPending || consolidatingUtxos ? __('Consolidating...') : __('Consolidate Now')
- }
- />
- ),
- help: ,
- }}
- >
- Your wallet has a lot of change lying around. Consolidating will speed up your transactions. This could
- take some time. %now%%help%
+
+
+
}
+ subtitle={
+ totalLocked > 0 ? (
+
}}>
+ Your total balance. All of this is yours, but some %lbc% is in use on channels and content right now.
-
- )}
- >
- }
- />
+ ) : (
+
{__('Your total balance.')}
+ )
+ }
+ actions={
+ <>
+
+ }}>
+ %lbc_amount% immediately spendable
+
+
+
+
+ ,
+ }}
+ >
+ %lbc_amount% boosting content
+
+ setDetailsExpanded(!detailsExpanded)}
+ />
+
+ {detailsExpanded && (
+
+
+
+ {__('...earned from others')}
+ ({__('Unlock to spend')})
+
+
+
+ {Boolean(tipsBalance) && (
+ doOpenModal(MODALS.MASS_TIP_UNLOCK)}
+ />
+ )}
+
+
+
+
+
+ {__('...on initial publishes')}
+ ({__('Delete or edit past content to spend')})
+
+
+
+
+
+
+ {__('...supporting content')}
+ ({__('Delete supports to spend')})
+
+
+
+
+
+
+ )}
+
+ {/* @if TARGET='app' */}
+ {hasSynced ? (
+
+ {__('A backup of your wallet is synced with lbry.tv.')}
+
+
+ ) : (
+
+ {__(
+ 'Your wallet is not currently synced with lbry.tv. You are in control of backing up your wallet.'
+ )}
+
+
+ )}
+ {/* @endif */}
+
+
+
+
+
+ {(otherCount > WALLET_CONSOLIDATE_UTXOS || consolidateIsPending || consolidatingUtxos) && (
+
+ doUtxoConsolidate()}
+ disabled={operationPending}
+ label={
+ consolidateIsPending || consolidatingUtxos ? __('Consolidating...') : __('Consolidate Now')
+ }
+ />
+ ),
+ help: ,
+ }}
+ >
+ Your wallet has a lot of change lying around. Consolidating will speed up your transactions. This
+ could take some time. %now%%help%
+
+
+ )}
+ >
+ }
+ />
+
+
+ {/* fiat balance card */}
+
+
+
);
};
diff --git a/ui/component/walletFiatAccountHistory/view.jsx b/ui/component/walletFiatAccountHistory/view.jsx
index 49b1ff299..7e9b688c9 100644
--- a/ui/component/walletFiatAccountHistory/view.jsx
+++ b/ui/component/walletFiatAccountHistory/view.jsx
@@ -1,7 +1,6 @@
// @flow
import React from 'react';
import Button from 'component/button';
-import Card from 'component/common/card';
import moment from 'moment';
type Props = {
@@ -21,67 +20,60 @@ const WalletBalance = (props: Props) => {
}
// if there are more than 10 transactions, limit it to 10 for the frontend
- if (accountTransactions && accountTransactions.length > 10) {
- accountTransactions.length = 10;
- }
+ // if (accountTransactions && accountTransactions.length > 10) {
+ // accountTransactions.length = 10;
+ // }
return (
- <>
-
-
-
-
- {__('Date')}
- {<>{__('Receiving Channel Name')}>}
- {__('Tip Location')}
- {__('Amount (USD)')}
- {__('Processing Fee')}
- {__('Odysee Fee')}
- {__('Received Amount')}
-
-
-
- {accountTransactions &&
- accountTransactions.map((transaction) => (
-
- {moment(transaction.created_at).format('LLL')}
-
-
-
-
-
-
- ${transaction.tipped_amount / 100}
- ${transaction.transaction_fee / 100}
- ${transaction.application_fee / 100}
- ${transaction.received_amount / 100}
-
- ))}
-
-
- {!accountTransactions &&
No Transactions
}
-
- >
- )}
- />
- >
+
+
+
+
+ {__('Date')}
+ {<>{__('Receiving Channel Name')}>}
+ {__('Tip Location')}
+ {__('Amount (USD)')}
+ {__('Processing Fee')}
+ {__('Odysee Fee')}
+ {__('Received Amount')}
+
+
+
+ {accountTransactions &&
+ accountTransactions.map((transaction) => (
+
+ {moment(transaction.created_at).format('LLL')}
+
+
+
+
+
+
+ ${transaction.tipped_amount / 100}
+ ${transaction.transaction_fee / 100}
+ ${transaction.application_fee / 100}
+ ${transaction.received_amount / 100}
+
+ ))}
+
+
+ {!accountTransactions &&
No Transactions
}
+
+
);
};
diff --git a/ui/component/walletFiatBalance/view.jsx b/ui/component/walletFiatBalance/view.jsx
index 9c71623ba..a4ef1bb28 100644
--- a/ui/component/walletFiatBalance/view.jsx
+++ b/ui/component/walletFiatBalance/view.jsx
@@ -6,84 +6,64 @@ import Button from 'component/button';
import Card from 'component/common/card';
import Icon from 'component/common/icon';
import I18nMessage from 'component/i18nMessage';
+import { Lbryio } from 'lbryinc';
+import { getStripeEnvironment } from 'util/stripe';
+let stripeEnvironment = getStripeEnvironment();
-type Props = {
- accountDetails: any,
-};
+const WalletBalance = () => {
+ const [accountStatusResponse, setAccountStatusResponse] = React.useState();
-const WalletBalance = (props: Props) => {
- const {
- accountDetails,
- } = props;
+ function getAccountStatus() {
+ return Lbryio.call(
+ 'account',
+ 'status',
+ {
+ environment: stripeEnvironment,
+ },
+ 'post'
+ );
+ }
+
+ // calculate account transactions section
+ React.useEffect(() => {
+ (async function () {
+ try {
+ if (!stripeEnvironment) {
+ return;
+ }
+ const response = await getAccountStatus();
+
+ setAccountStatusResponse(response);
+ } catch (err) {
+ console.log(err);
+ }
+ })();
+ }, [stripeEnvironment]);
return (
<>{ {(accountDetails && ((accountDetails.total_received_unpaid - accountDetails.total_paid_out) / 100)) || 0} USD>}
- subtitle={accountDetails && accountDetails.total_received_unpaid > 0 &&
+ title={<> {(accountStatusResponse && ((accountStatusResponse.total_received_unpaid - accountStatusResponse.total_paid_out) / 100)) || 0} USD>}
+ subtitle={accountStatusResponse && accountStatusResponse.total_received_unpaid > 0 ? (
This is your pending balance that will be automatically sent to your bank account
-
+ ) : (
+
+ When you begin to receive tips your balance will be updated here
+ )
}
actions={
<>
- ${(accountDetails && (accountDetails.total_received_unpaid / 100)) || 0} Total Received Tips
+ ${(accountStatusResponse && (accountStatusResponse.total_received_unpaid / 100)) || 0} Total Received Tips
- ${(accountDetails && (accountDetails.total_paid_out / 100)) || 0} Withdrawn
- {/* setDetailsExpanded(!detailsExpanded)} */}
- {/* /> */}
+ ${(accountStatusResponse && (accountStatusResponse.total_paid_out / 100)) || 0} Withdrawn
- {/* view more section */}
- {/* commenting out because not implemented, but could be used in the future */}
- {/* {detailsExpanded && ( */}
- {/* */}
- {/*
*/}
- {/* */}
- {/* {__('Earned from uploads')} */}
- {/* /!* ({__('Earned from channel page')}) *!/ */}
- {/* */}
- {/* */}
- {/* */}
- {/* {Boolean(1) && ( */}
- {/* */}
- {/* )} */}
- {/* */}
- {/* */}
- {/* */}
-
- {/* */}
- {/* {__('Earned from channel page')} */}
- {/* /!* ({__('Delete or edit past content to spend')}) *!/ */}
- {/* */}
- {/* */}
- {/* */}
- {/* */}
-
- {/* /!* *!/ */}
- {/* /!* {__('...supporting content')} *!/ */}
- {/* /!* ({__('Delete supports to spend')}) *!/ */}
- {/* /!* *!/ */}
- {/* /!* *!/ */}
- {/* /!* *!/ */}
- {/* /!* *!/ */}
- {/* */}
- {/*
*/}
- {/* )} */}
-
- {/* */}
-
+
+
>
}
diff --git a/ui/component/walletFiatPaymentHistory/view.jsx b/ui/component/walletFiatPaymentHistory/view.jsx
index 45d55bde7..2113947c0 100644
--- a/ui/component/walletFiatPaymentHistory/view.jsx
+++ b/ui/component/walletFiatPaymentHistory/view.jsx
@@ -1,7 +1,6 @@
// @flow
import React from 'react';
import Button from 'component/button';
-import Card from 'component/common/card';
import { Lbryio } from 'lbryinc';
import moment from 'moment';
import { getStripeEnvironment } from 'util/stripe';
@@ -16,10 +15,6 @@ const WalletBalance = (props: Props) => {
// receive transactions from parent component
const { transactions: accountTransactions } = props;
- // const [accountStatusResponse, setAccountStatusResponse] = React.useState();
-
- // const [subscriptions, setSubscriptions] = React.useState();
-
const [lastFour, setLastFour] = React.useState();
function getCustomerStatus() {
@@ -35,78 +30,76 @@ const WalletBalance = (props: Props) => {
// TODO: this is actually incorrect, last4 should be populated based on the transaction not the current customer details
React.useEffect(() => {
- (async function () {
- const customerStatusResponse = await getCustomerStatus();
+ (async function() {
+ const customerStatusResponse = await getCustomerStatus();
- const lastFour =
- customerStatusResponse.PaymentMethods &&
- customerStatusResponse.PaymentMethods.length &&
- customerStatusResponse.PaymentMethods[0].card.last4;
+ const lastFour = customerStatusResponse.PaymentMethods && customerStatusResponse.PaymentMethods.length && customerStatusResponse.PaymentMethods[0].card.last4;
- setLastFour(lastFour);
+ setLastFour(lastFour);
})();
}, []);
return (
<>
-
-
-
-
-
- {__('Date')}
- {<>{__('Receiving Channel Name')}>}
- {__('Tip Location')}
- {__('Amount (USD)')}
- {__('Card Last 4')}
- {__('Anonymous')}
-
-
-
- {accountTransactions &&
- accountTransactions.map((transaction) => (
-
- {moment(transaction.created_at).format('LLL')}
-
-
-
-
-
-
- ${transaction.tipped_amount / 100}
- {lastFour}
- {transaction.private_tip ? 'Yes' : 'No'}
-
- ))}
-
-
- {(!accountTransactions || accountTransactions.length === 0) && (
-
- No Transactions
-
- )}
-
- >
- }
- />
- >
+
+
+
+ {/* table header */}
+
+
+ {__('Date')}
+ {<>{__('Receiving Channel Name')}>}
+ {__('Tip Location')}
+ {__('Amount (USD)')}
+ {__('Card Last 4')}
+ {__('Anonymous')}
+
+
+ {/* list data for transactions */}
+
+ {accountTransactions &&
+ accountTransactions.map((transaction) => (
+
+ {/* date */}
+ {moment(transaction.created_at).format('LLL')}
+ {/* receiving channel name */}
+
+
+
+ {/* link to content or channel */}
+
+
+
+ {/* how much tipped */}
+ ${transaction.tipped_amount / 100}
+ {/* TODO: this is incorrect need it per transactions not per user */}
+ {/* last four of credit card */}
+ {lastFour}
+ {/* whether tip is anonymous or not */}
+ {transaction.private_tip ? 'Yes' : 'No'}
+
+ ))}
+
+
+ {/* show some markup if there's no transactions */}
+ {(!accountTransactions || accountTransactions.length === 0) &&
No Transactions
}
+
+
+ >
);
};
diff --git a/ui/component/walletSendTip/view.jsx b/ui/component/walletSendTip/view.jsx
index 87b6b25e3..2167f2e62 100644
--- a/ui/component/walletSendTip/view.jsx
+++ b/ui/component/walletSendTip/view.jsx
@@ -150,7 +150,7 @@ function WalletSendTip(props: Props) {
const noBalance = balance === 0;
const tipAmount = useCustomTip ? customTipAmount : presetTipAmount;
- const [activeTab, setActiveTab] = React.useState(TAB_BOOST);
+ const [activeTab, setActiveTab] = React.useState(claimIsMine ? TAB_BOOST : TAB_LBC);
function getClaimTypeText() {
if (claim.value_type === 'stream') {
diff --git a/ui/constants/icons.js b/ui/constants/icons.js
index 6734cde59..cfe7d9ff9 100644
--- a/ui/constants/icons.js
+++ b/ui/constants/icons.js
@@ -163,8 +163,6 @@ export const STACK = 'stack';
export const TIME = 'time';
export const GLOBE = 'globe';
export const RSS = 'rss';
-export const APPEARANCE = 'Appearance';
-export const CONTENT = 'Content';
export const STAR = 'star';
export const MUSIC = 'MusicCategory';
export const BADGE_MOD = 'BadgeMod';
diff --git a/ui/constants/pages.js b/ui/constants/pages.js
index eb1d836ec..7a2bf87f7 100644
--- a/ui/constants/pages.js
+++ b/ui/constants/pages.js
@@ -41,9 +41,9 @@ exports.SETTINGS = 'settings';
exports.SETTINGS_STRIPE_CARD = 'settings/card';
exports.SETTINGS_STRIPE_ACCOUNT = 'settings/tip_account';
exports.SETTINGS_NOTIFICATIONS = 'settings/notifications';
+exports.SETTINGS_ADVANCED = 'settings/advanced';
exports.SETTINGS_BLOCKED_MUTED = 'settings/block_and_mute';
exports.SETTINGS_CREATOR = 'settings/creator';
-exports.SETTINGS_UPDATE_PWD = 'settings/update_password';
exports.SHOW = 'show';
exports.ACCOUNT = 'account';
exports.SEARCH = 'search';
diff --git a/ui/constants/settings.js b/ui/constants/settings.js
index aadb632a0..ca0e48c31 100644
--- a/ui/constants/settings.js
+++ b/ui/constants/settings.js
@@ -26,10 +26,3 @@ export const ENABLE_SYNC = 'enable_sync';
export const TO_TRAY_WHEN_CLOSED = 'to_tray_when_closed';
export const ENABLE_PUBLISH_PREVIEW = 'enable-publish-preview';
export const DESKTOP_WINDOW_ZOOM = 'desktop_window_zoom';
-
-export const SETTINGS_GRP = {
- APPEARANCE: 'appearance',
- ACCOUNT: 'account',
- CONTENT: 'content',
- SYSTEM: 'system',
-};
diff --git a/ui/page/listBlocked/view.jsx b/ui/page/listBlocked/view.jsx
index 85f355947..45f84d850 100644
--- a/ui/page/listBlocked/view.jsx
+++ b/ui/page/listBlocked/view.jsx
@@ -229,12 +229,7 @@ function ListBlocked(props: Props) {
}, [stringifiedPersonalList, justPersonalBlocked, setLocalPersonalList]);
return (
-
+
{fetchingModerationBlockList && (
diff --git a/ui/page/passwordUpdate/index.js b/ui/page/passwordUpdate/index.js
deleted file mode 100644
index 40e233027..000000000
--- a/ui/page/passwordUpdate/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import PasswordUpdate from './view';
-
-export default PasswordUpdate;
diff --git a/ui/page/passwordUpdate/view.jsx b/ui/page/passwordUpdate/view.jsx
deleted file mode 100644
index 380f30095..000000000
--- a/ui/page/passwordUpdate/view.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-// @flow
-import React from 'react';
-import Card from 'component/common/card';
-import Page from 'component/page';
-import SettingAccountPassword from 'component/settingAccountPassword';
-
-export default function PasswordUpdate() {
- return (
-
- } />
-
- );
-}
diff --git a/ui/page/settings/index.js b/ui/page/settings/index.js
index 35df01630..c9292b3cf 100644
--- a/ui/page/settings/index.js
+++ b/ui/page/settings/index.js
@@ -1,17 +1,57 @@
import { connect } from 'react-redux';
-import { doEnterSettingsPage, doExitSettingsPage } from 'redux/actions/settings';
-import { selectDaemonSettings, selectLanguage } from 'redux/selectors/settings';
-import { selectUserVerifiedEmail } from 'redux/selectors/user';
-
+import { doClearCache, doNotifyForgetPassword, doToggle3PAnalytics, doOpenModal } from 'redux/actions/app';
+import { selectAllowAnalytics } from 'redux/selectors/app';
+import {
+ doSetDaemonSetting,
+ doClearDaemonSetting,
+ doSetClientSetting,
+ doSetDarkTime,
+ doEnterSettingsPage,
+ doExitSettingsPage,
+} from 'redux/actions/settings';
+import { doSetPlayingUri } from 'redux/actions/content';
+import {
+ makeSelectClientSetting,
+ selectDaemonSettings,
+ selectLanguage,
+ selectShowMatureContent,
+} from 'redux/selectors/settings';
+import { doWalletStatus, selectMyChannelUrls, selectWalletIsEncrypted, SETTINGS } from 'lbry-redux';
import SettingsPage from './view';
+import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
const select = (state) => ({
daemonSettings: selectDaemonSettings(state),
+ allowAnalytics: selectAllowAnalytics(state),
isAuthenticated: selectUserVerifiedEmail(state),
+ showNsfw: selectShowMatureContent(state),
+ currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state),
+ themes: makeSelectClientSetting(SETTINGS.THEMES)(state),
+ automaticDarkModeEnabled: makeSelectClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED)(state),
+ clock24h: makeSelectClientSetting(SETTINGS.CLOCK_24H)(state),
+ autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY)(state),
+ walletEncrypted: selectWalletIsEncrypted(state),
+ autoDownload: makeSelectClientSetting(SETTINGS.AUTO_DOWNLOAD)(state),
+ hideBalance: makeSelectClientSetting(SETTINGS.HIDE_BALANCE)(state),
+ floatingPlayer: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state),
+ hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state),
+ darkModeTimes: makeSelectClientSetting(SETTINGS.DARK_MODE_TIMES)(state),
language: selectLanguage(state),
+ myChannelUrls: selectMyChannelUrls(state),
+ user: selectUser(state),
});
const perform = (dispatch) => ({
+ setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)),
+ clearDaemonSetting: (key) => dispatch(doClearDaemonSetting(key)),
+ toggle3PAnalytics: (allow) => dispatch(doToggle3PAnalytics(allow)),
+ clearCache: () => dispatch(doClearCache()),
+ setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
+ updateWalletStatus: () => dispatch(doWalletStatus()),
+ confirmForgetPassword: (modalProps) => dispatch(doNotifyForgetPassword(modalProps)),
+ clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
+ setDarkTime: (time, options) => dispatch(doSetDarkTime(time, options)),
+ openModal: (id, params) => dispatch(doOpenModal(id, params)),
enterSettings: () => dispatch(doEnterSettingsPage()),
exitSettings: () => dispatch(doExitSettingsPage()),
});
diff --git a/ui/page/settings/view.jsx b/ui/page/settings/view.jsx
index dfd2278f7..60d29d385 100644
--- a/ui/page/settings/view.jsx
+++ b/ui/page/settings/view.jsx
@@ -1,16 +1,43 @@
// @flow
import * as PAGES from 'constants/pages';
+import * as MODALS from 'constants/modal_types';
import * as ICONS from 'constants/icons';
import * as React from 'react';
-import classnames from 'classnames';
+import { SETTINGS } from 'lbry-redux';
+import { FormField } from 'component/common/form';
import Button from 'component/button';
import Page from 'component/page';
-import SettingAccount from 'component/settingAccount';
-import SettingAppearance from 'component/settingAppearance';
-import SettingContent from 'component/settingContent';
-import SettingSystem from 'component/settingSystem';
-import SettingUnauthenticated from 'component/settingUnauthenticated';
+import SettingLanguage from 'component/settingLanguage';
+import FileSelector from 'component/common/file-selector';
+import SyncToggle from 'component/syncToggle';
+import HomepageSelector from 'component/homepageSelector';
+import Card from 'component/common/card';
+import SettingAccountPassword from 'component/settingAccountPassword';
+import classnames from 'classnames';
+import { getPasswordFromCookie } from 'util/saved-passwords';
+import { SIMPLE_SITE } from 'config';
+// $FlowFixMe
+import homepages from 'homepages';
+import { Lbryio } from 'lbryinc';
import Yrbl from 'component/yrbl';
+import { getStripeEnvironment } from 'util/stripe';
+
+type Price = {
+ currency: string,
+ amount: number,
+};
+
+type SetDaemonSettingArg = boolean | string | number;
+
+type DarkModeTimes = {
+ from: { hour: string, min: string, formattedTime: string },
+ to: { hour: string, min: string, formattedTime: string },
+};
+
+type OptionTimes = {
+ fromTo: string,
+ time: string,
+};
type DaemonSettings = {
download_dir: string,
@@ -18,15 +45,69 @@ type DaemonSettings = {
};
type Props = {
+ setDaemonSetting: (string, ?SetDaemonSettingArg) => void,
+ clearDaemonSetting: (string) => void,
+ setClientSetting: (string, SetDaemonSettingArg) => void,
+ toggle3PAnalytics: (boolean) => void,
+ clearCache: () => Promise
,
daemonSettings: DaemonSettings,
+ allowAnalytics: boolean,
+ showNsfw: boolean,
isAuthenticated: boolean,
+ instantPurchaseEnabled: boolean,
+ instantPurchaseMax: Price,
+ currentTheme: string,
+ themes: Array,
+ automaticDarkModeEnabled: boolean,
+ clock24h: boolean,
+ autoplay: boolean,
+ updateWalletStatus: () => void,
+ walletEncrypted: boolean,
+ confirmForgetPassword: ({}) => void,
+ floatingPlayer: boolean,
+ hideReposts: ?boolean,
+ clearPlayingUri: () => void,
+ darkModeTimes: DarkModeTimes,
+ setDarkTime: (string, {}) => void,
+ openModal: (string) => void,
+ language?: string,
enterSettings: () => void,
exitSettings: () => void,
+ myChannelUrls: ?Array,
+ user: User,
};
-class SettingsPage extends React.PureComponent {
+type State = {
+ clearingCache: boolean,
+ storedPassword: boolean,
+};
+
+class SettingsPage extends React.PureComponent {
+ constructor(props: Props) {
+ super(props);
+
+ this.state = {
+ clearingCache: false,
+ storedPassword: false,
+ };
+
+ (this: any).onThemeChange = this.onThemeChange.bind(this);
+ (this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this);
+ (this: any).onChangeTime = this.onChangeTime.bind(this);
+ (this: any).onConfirmForgetPassword = this.onConfirmForgetPassword.bind(this);
+ }
+
componentDidMount() {
- const { enterSettings } = this.props;
+ const { isAuthenticated, enterSettings } = this.props;
+
+ if (isAuthenticated || !IS_WEB) {
+ this.props.updateWalletStatus();
+ getPasswordFromCookie().then((p) => {
+ if (typeof p === 'string') {
+ this.setState({ storedPassword: true });
+ }
+ });
+ }
enterSettings();
}
@@ -35,34 +116,117 @@ class SettingsPage extends React.PureComponent {
exitSettings();
}
+ onThemeChange(event: SyntheticInputEvent<*>) {
+ const { value } = event.target;
+
+ if (value === 'dark') {
+ this.onAutomaticDarkModeChange(false);
+ }
+
+ this.props.setClientSetting(SETTINGS.THEME, value);
+ }
+
+ onAutomaticDarkModeChange(value: boolean) {
+ this.props.setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, value);
+ }
+
+ onClock24hChange(value: boolean) {
+ this.props.setClientSetting(SETTINGS.CLOCK_24H, value);
+ }
+
+ onConfirmForgetPassword() {
+ const { confirmForgetPassword } = this.props;
+ confirmForgetPassword({
+ callback: () => {
+ this.setState({ storedPassword: false });
+ },
+ });
+ }
+
+ onChangeTime(event: SyntheticInputEvent<*>, options: OptionTimes) {
+ const { value } = event.target;
+
+ this.props.setDarkTime(value, options);
+ }
+
+ formatHour(time: string, clock24h: boolean) {
+ if (clock24h) {
+ return `${time}:00`;
+ }
+
+ const now = new Date(0, 0, 0, Number(time));
+
+ const hour = now.toLocaleTimeString('en-US', { hour12: true, hour: '2-digit' });
+
+ return hour;
+ }
+
+ setDaemonSetting(name: string, value: ?SetDaemonSettingArg): void {
+ this.props.setDaemonSetting(name, value);
+ }
+
+ clearDaemonSetting(name: string): void {
+ this.props.clearDaemonSetting(name);
+ }
+
render() {
- const { daemonSettings, isAuthenticated } = this.props;
+ const {
+ daemonSettings,
+ allowAnalytics,
+ showNsfw,
+ isAuthenticated,
+ currentTheme,
+ themes,
+ automaticDarkModeEnabled,
+ clock24h,
+ autoplay,
+ walletEncrypted,
+ // autoDownload,
+ setDaemonSetting,
+ setClientSetting,
+ toggle3PAnalytics,
+ floatingPlayer,
+ hideReposts,
+ clearPlayingUri,
+ darkModeTimes,
+ clearCache,
+ openModal,
+ myChannelUrls,
+ user,
+ } = this.props;
+ const { storedPassword } = this.state;
const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0;
+ const startHours = ['18', '19', '20', '21'];
+ const endHours = ['5', '6', '7', '8'];
return (
+ } />
+ {homepages && Object.keys(homepages).length > 1 && (
+ } />
+ )}
+
{!isAuthenticated && IS_WEB && (
- <>
-
-
-
-
-
- }
- />
-
- >
+
+
+
+
+ }
+ />
+
)}
{!IS_WEB && noDaemonSettings ? (
@@ -71,10 +235,341 @@ class SettingsPage extends React.PureComponent
{
) : (
-
-
-
-
+ {isAuthenticated &&
}
+ {/* @if TARGET='app' */}
+
+ {
+ setDaemonSetting('download_dir', newDirectory.path);
+ }}
+ />
+ {__('LBRY downloads will be saved here.')}
+
+ }
+ />
+ }
+ />
+ {/* @endif */}
+
+
+
+
+ {themes.map((theme) => (
+
+ {theme === 'light' ? __('Light') : __('Dark')}
+
+ ))}
+
+
+
+ this.onAutomaticDarkModeChange(!automaticDarkModeEnabled)}
+ checked={automaticDarkModeEnabled}
+ label={__('Automatic dark mode')}
+ />
+ {automaticDarkModeEnabled && (
+
+ this.onChangeTime(value, { fromTo: 'from', time: 'hour' })}
+ value={darkModeTimes.from.hour}
+ label={__('From --[initial time]--')}
+ >
+ {startHours.map((time) => (
+
+ {this.formatHour(time, clock24h)}
+
+ ))}
+
+ this.onChangeTime(value, { fromTo: 'to', time: 'hour' })}
+ value={darkModeTimes.to.hour}
+ >
+ {endHours.map((time) => (
+
+ {this.formatHour(time, clock24h)}
+
+ ))}
+
+
+ )}
+
+
+ this.onClock24hChange(!clock24h)}
+ checked={clock24h}
+ label={__('24-hour clock')}
+ />
+
+
+ }
+ />
+
+
+ {
+ setClientSetting(SETTINGS.FLOATING_PLAYER, !floatingPlayer);
+ clearPlayingUri();
+ }}
+ checked={floatingPlayer}
+ label={__('Floating video player')}
+ helper={__('Keep content playing in the corner when navigating to a different page.')}
+ />
+
+ setClientSetting(SETTINGS.AUTOPLAY, !autoplay)}
+ checked={autoplay}
+ label={__('Autoplay media files')}
+ helper={__(
+ 'Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.'
+ )}
+ />
+ {!SIMPLE_SITE && (
+ <>
+ {
+ if (isAuthenticated) {
+ let param = e.target.checked ? { add: 'noreposts' } : { remove: 'noreposts' };
+ Lbryio.call('user_tag', 'edit', param);
+ }
+
+ setClientSetting(SETTINGS.HIDE_REPOSTS, !hideReposts);
+ }}
+ checked={hideReposts}
+ label={__('Hide reposts')}
+ helper={__(
+ 'You will not see reposts by people you follow or receive email notifying about them.'
+ )}
+ />
+
+ {/*
+ setClientSetting(SETTINGS.SHOW_ANONYMOUS, !showAnonymous)}
+ checked={showAnonymous}
+ label={__('Show anonymous content')}
+ helper={__('Anonymous content is published without a channel.')}
+ />
+ */}
+
+
+ !IS_WEB || showNsfw
+ ? setClientSetting(SETTINGS.SHOW_MATURE, !showNsfw)
+ : openModal(MODALS.CONFIRM_AGE)
+ }
+ checked={showNsfw}
+ label={__('Show mature content')}
+ helper={__(
+ 'Mature content may include nudity, intense sexuality, profanity, or other adult content. By displaying mature content, you are affirming you are of legal age to view mature content in your country or jurisdiction. '
+ )}
+ />
+ >
+ )}
+
+ }
+ />
+
+ {/* @if TARGET='app' */}
+
+ {__(
+ `This is information like error logging, performance tracking, and usage statistics. It includes your IP address and basic system details, but no other identifying information (unless you sign in to lbry.tv)`
+ )}{' '}
+
+
+ }
+ actions={
+ <>
+ setDaemonSetting('share_usage_data', !daemonSettings.share_usage_data)}
+ checked={daemonSettings.share_usage_data}
+ label={{__('Allow the app to share data to LBRY.inc')} }
+ helper={
+ isAuthenticated
+ ? __('Internal sharing is required while signed in.')
+ : __('Internal sharing is required to participate in rewards programs.')
+ }
+ disabled={isAuthenticated && daemonSettings.share_usage_data}
+ />
+ toggle3PAnalytics(e.target.checked)}
+ checked={allowAnalytics}
+ label={__('Allow the app to access third party analytics platforms')}
+ helper={__('We use detailed analytics to improve all aspects of the LBRY experience.')}
+ />
+ >
+ }
+ />
+ {/* @endif */}
+
+ {/* @if TARGET='web' */}
+ {user && getStripeEnvironment() && (
+
+
+
+ }
+ />
+ )}
+ {/* @endif */}
+
+ {/* @if TARGET='web' */}
+ {isAuthenticated && getStripeEnvironment() && (
+
+
+
+ }
+ />
+ )}
+ {/* @endif */}
+
+ {(isAuthenticated || !IS_WEB) && (
+ <>
+
+
+
+ }
+ />
+
+
+
+
+ }
+ />
+
+ {myChannelUrls && myChannelUrls.length > 0 && (
+
+
+
+ }
+ />
+ )}
+
+
+
+
+ }
+ />
+ >
+ )}
+
+
+ {__(
+ 'This will clear the application cache, and might fix issues you are having. Your wallet will not be affected. '
+ )}
+
+ }
+ actions={
+
+ }
+ />
)}
diff --git a/ui/component/settingSystem/index.js b/ui/page/settingsAdvanced/index.js
similarity index 55%
rename from ui/component/settingSystem/index.js
rename to ui/page/settingsAdvanced/index.js
index 53155e49d..c42fac57f 100644
--- a/ui/component/settingSystem/index.js
+++ b/ui/page/settingsAdvanced/index.js
@@ -1,44 +1,51 @@
import { connect } from 'react-redux';
-import { doWalletStatus, selectWalletIsEncrypted } from 'lbry-redux';
-import {
- doClearCache,
- doNotifyDecryptWallet,
- doNotifyEncryptWallet,
- doNotifyForgetPassword,
- doToggle3PAnalytics,
-} from 'redux/actions/app';
-import { doSetDaemonSetting, doClearDaemonSetting, doFindFFmpeg } from 'redux/actions/settings';
+import { doClearCache, doNotifyEncryptWallet, doNotifyDecryptWallet, doNotifyForgetPassword } from 'redux/actions/app';
import { selectAllowAnalytics } from 'redux/selectors/app';
import {
+ doSetDaemonSetting,
+ doClearDaemonSetting,
+ doSetClientSetting,
+ doFindFFmpeg,
+ doEnterSettingsPage,
+ doExitSettingsPage,
+} from 'redux/actions/settings';
+import {
+ makeSelectClientSetting,
+ selectLanguage,
selectDaemonSettings,
selectFfmpegStatus,
selectFindingFFmpeg,
- selectLanguage,
} from 'redux/selectors/settings';
+import { doWalletStatus, selectWalletIsEncrypted, SETTINGS } from 'lbry-redux';
+import SettingsAdvancedPage from './view';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
-import SettingSystem from './view';
-
const select = (state) => ({
daemonSettings: selectDaemonSettings(state),
+ allowAnalytics: selectAllowAnalytics(state),
+ isAuthenticated: selectUserVerifiedEmail(state),
+ instantPurchaseEnabled: makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED)(state),
+ instantPurchaseMax: makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_MAX)(state),
+ walletEncrypted: selectWalletIsEncrypted(state),
+ hideBalance: makeSelectClientSetting(SETTINGS.HIDE_BALANCE)(state),
ffmpegStatus: selectFfmpegStatus(state),
findingFFmpeg: selectFindingFFmpeg(state),
- walletEncrypted: selectWalletIsEncrypted(state),
- isAuthenticated: selectUserVerifiedEmail(state),
- allowAnalytics: selectAllowAnalytics(state),
language: selectLanguage(state),
+ syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
});
const perform = (dispatch) => ({
setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)),
clearDaemonSetting: (key) => dispatch(doClearDaemonSetting(key)),
clearCache: () => dispatch(doClearCache()),
- findFFmpeg: () => dispatch(doFindFFmpeg()),
+ setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
encryptWallet: () => dispatch(doNotifyEncryptWallet()),
decryptWallet: () => dispatch(doNotifyDecryptWallet()),
updateWalletStatus: () => dispatch(doWalletStatus()),
confirmForgetPassword: (modalProps) => dispatch(doNotifyForgetPassword(modalProps)),
- toggle3PAnalytics: (allow) => dispatch(doToggle3PAnalytics(allow)),
+ findFFmpeg: () => dispatch(doFindFFmpeg()),
+ enterSettings: () => dispatch(doEnterSettingsPage()),
+ exitSettings: () => dispatch(doExitSettingsPage()),
});
-export default connect(select, perform)(SettingSystem);
+export default connect(select, perform)(SettingsAdvancedPage);
diff --git a/ui/page/settingsAdvanced/view.jsx b/ui/page/settingsAdvanced/view.jsx
new file mode 100644
index 000000000..4807eaa9e
--- /dev/null
+++ b/ui/page/settingsAdvanced/view.jsx
@@ -0,0 +1,529 @@
+// @flow
+import * as React from 'react';
+
+import { FormField, FormFieldPrice } from 'component/common/form';
+import Button from 'component/button';
+import I18nMessage from 'component/i18nMessage';
+import Page from 'component/page';
+import SettingCommentsServer from 'component/settingCommentsServer';
+import SettingWalletServer from 'component/settingWalletServer';
+import SettingAutoLaunch from 'component/settingAutoLaunch';
+import SettingClosingBehavior from 'component/settingClosingBehavior';
+import FileSelector from 'component/common/file-selector';
+import { SETTINGS } from 'lbry-redux';
+import Card from 'component/common/card';
+import { getPasswordFromCookie } from 'util/saved-passwords';
+import Spinner from 'component/spinner';
+import PublishSettings from 'component/publishSettings';
+
+// @if TARGET='app'
+const IS_MAC = process.platform === 'darwin';
+// @endif
+
+type Price = {
+ currency: string,
+ amount: number,
+};
+
+type SetDaemonSettingArg = boolean | string | number | Price;
+
+type DaemonSettings = {
+ download_dir: string,
+ share_usage_data: boolean,
+ max_key_fee?: Price,
+ max_connections_per_download?: number,
+ save_files: boolean,
+ save_blobs: boolean,
+ ffmpeg_path: string,
+};
+
+type Props = {
+ setDaemonSetting: (string, ?SetDaemonSettingArg) => void,
+ clearDaemonSetting: (string) => void,
+ setClientSetting: (string, SetDaemonSettingArg) => void,
+ daemonSettings: DaemonSettings,
+ isAuthenticated: boolean,
+ instantPurchaseEnabled: boolean,
+ instantPurchaseMax: Price,
+ encryptWallet: () => void,
+ decryptWallet: () => void,
+ updateWalletStatus: () => void,
+ walletEncrypted: boolean,
+ hideBalance: boolean,
+ confirmForgetPassword: ({}) => void,
+ ffmpegStatus: { available: boolean, which: string },
+ findingFFmpeg: boolean,
+ findFFmpeg: () => void,
+ language?: string,
+ syncEnabled: boolean,
+ enterSettings: () => void,
+ exitSettings: () => void,
+};
+
+type State = {
+ clearingCache: boolean,
+ storedPassword: boolean,
+};
+
+class SettingsAdvancedPage extends React.PureComponent {
+ constructor(props: Props) {
+ super(props);
+
+ this.state = {
+ clearingCache: false,
+ storedPassword: false,
+ };
+
+ (this: any).onKeyFeeChange = this.onKeyFeeChange.bind(this);
+ (this: any).onMaxConnectionsChange = this.onMaxConnectionsChange.bind(this);
+ (this: any).onKeyFeeDisableChange = this.onKeyFeeDisableChange.bind(this);
+ (this: any).onInstantPurchaseMaxChange = this.onInstantPurchaseMaxChange.bind(this);
+ (this: any).onThemeChange = this.onThemeChange.bind(this);
+ (this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this);
+ (this: any).onConfirmForgetPassword = this.onConfirmForgetPassword.bind(this);
+ }
+
+ componentDidMount() {
+ const { isAuthenticated, ffmpegStatus, daemonSettings, findFFmpeg, enterSettings } = this.props;
+
+ // @if TARGET='app'
+ const { available } = ffmpegStatus;
+ const { ffmpeg_path: ffmpegPath } = daemonSettings;
+ if (!available) {
+ if (ffmpegPath) {
+ this.clearDaemonSetting('ffmpeg_path');
+ }
+ findFFmpeg();
+ }
+ // @endif
+
+ if (isAuthenticated || !IS_WEB) {
+ this.props.updateWalletStatus();
+ getPasswordFromCookie().then((p) => {
+ if (typeof p === 'string') {
+ this.setState({ storedPassword: true });
+ }
+ });
+ }
+ enterSettings();
+ }
+
+ componentWillUnmount() {
+ const { exitSettings } = this.props;
+ exitSettings();
+ }
+
+ onFFmpegFolder(path: string) {
+ this.setDaemonSetting('ffmpeg_path', path);
+ this.findFFmpeg();
+ }
+
+ onKeyFeeChange(newValue: Price) {
+ this.setDaemonSetting('max_key_fee', newValue);
+ }
+
+ onMaxConnectionsChange(event: SyntheticInputEvent<*>) {
+ const { value } = event.target;
+ this.setDaemonSetting('max_connections_per_download', value);
+ }
+
+ onKeyFeeDisableChange(isDisabled: boolean) {
+ if (isDisabled) this.setDaemonSetting('max_key_fee');
+ }
+
+ onThemeChange(event: SyntheticInputEvent<*>) {
+ const { value } = event.target;
+
+ if (value === 'dark') {
+ this.onAutomaticDarkModeChange(false);
+ }
+
+ this.props.setClientSetting(SETTINGS.THEME, value);
+ }
+
+ onAutomaticDarkModeChange(value: boolean) {
+ this.props.setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, value);
+ }
+
+ onInstantPurchaseEnabledChange(enabled: boolean) {
+ this.props.setClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, enabled);
+ }
+
+ onInstantPurchaseMaxChange(newValue: Price) {
+ this.props.setClientSetting(SETTINGS.INSTANT_PURCHASE_MAX, newValue);
+ }
+
+ onChangeEncryptWallet() {
+ const { decryptWallet, walletEncrypted, encryptWallet } = this.props;
+ if (walletEncrypted) {
+ decryptWallet();
+ } else {
+ encryptWallet();
+ }
+ }
+
+ onConfirmForgetPassword() {
+ const { confirmForgetPassword } = this.props;
+ confirmForgetPassword({
+ callback: () => {
+ this.setState({ storedPassword: false });
+ },
+ });
+ }
+
+ setDaemonSetting(name: string, value: ?SetDaemonSettingArg): void {
+ this.props.setDaemonSetting(name, value);
+ }
+
+ clearDaemonSetting(name: string): void {
+ this.props.clearDaemonSetting(name);
+ }
+
+ findFFmpeg(): void {
+ this.props.findFFmpeg();
+ }
+
+ render() {
+ const {
+ daemonSettings,
+ ffmpegStatus,
+ instantPurchaseEnabled,
+ instantPurchaseMax,
+ isAuthenticated,
+ walletEncrypted,
+ setDaemonSetting,
+ setClientSetting,
+ hideBalance,
+ findingFFmpeg,
+ language,
+ } = this.props;
+
+ const { storedPassword } = this.state;
+ const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0;
+ const defaultMaxKeyFee = { currency: 'USD', amount: 50 };
+ const disableMaxKeyFee = !(daemonSettings && daemonSettings.max_key_fee);
+ const connectionOptions = [1, 2, 4, 6, 10, 20];
+ // @if TARGET='app'
+ const { available: ffmpegAvailable, which: ffmpegPath } = ffmpegStatus;
+ // @endif
+
+ return (
+
+ {!IS_WEB && noDaemonSettings ? (
+
+ {__('Failed to load settings.')}
+
+ ) : (
+
+ {/* @if TARGET='app' */}
+
+ setDaemonSetting('save_files', !daemonSettings.save_files)}
+ checked={daemonSettings.save_files}
+ label={__('Save all viewed content to your downloads directory')}
+ helper={__(
+ 'Paid content and some file types are saved by default. Changing this setting will not affect previously downloaded content.'
+ )}
+ />
+
+ setDaemonSetting('save_blobs', !daemonSettings.save_blobs)}
+ checked={daemonSettings.save_blobs}
+ label={__('Save hosting data to help the LBRY network')}
+ helper={
+
+ {__("If disabled, LBRY will be very sad and you won't be helping improve the network.")}{' '}
+ .
+
+ }
+ />
+
+ }
+ />
+
+
+ {
+ this.onKeyFeeDisableChange(true);
+ }}
+ />
+ {
+ this.onKeyFeeDisableChange(false);
+ this.onKeyFeeChange(defaultMaxKeyFee);
+ }}
+ label={__('Choose limit')}
+ />
+
+ {!disableMaxKeyFee && (
+
+ )}
+
+
+ {__('This will prevent you from purchasing any content over a certain cost, as a safety measure.')}
+
+
+ }
+ />
+ {/* @endif */}
+
+
+ {
+ this.onInstantPurchaseEnabledChange(false);
+ }}
+ />
+ {
+ this.onInstantPurchaseEnabledChange(true);
+ }}
+ />
+
+ {instantPurchaseEnabled && (
+
+ )}
+
+
+ {__(
+ "When this option is chosen, LBRY won't ask you to confirm purchases or tips below your chosen amount."
+ )}
+
+
+ }
+ />
+
+ {(isAuthenticated || !IS_WEB) && (
+
+ {/* @if TARGET='app' */}
+ this.onChangeEncryptWallet()}
+ checked={walletEncrypted}
+ label={__('Encrypt my wallet with a custom password')}
+ helper={
+
+
+ ),
+ }}
+ >
+ Wallet encryption is currently unavailable until it's supported for synced accounts. It will
+ be added back soon. %learn_more%.
+
+ {/* {__('Secure your local wallet data with a custom password.')}{' '}
+ {__('Lost passwords cannot be recovered.')}
+ . */}
+
+ }
+ />
+
+ {walletEncrypted && storedPassword && (
+ {__('Automatically unlock your wallet on startup')}}
+ />
+ )}
+ {/* @endif */}
+
+ setClientSetting(SETTINGS.HIDE_BALANCE, !hideBalance)}
+ checked={hideBalance}
+ label={__('Hide wallet balance in header')}
+ />
+
+ }
+ />
+ )}
+
+ {/* @if TARGET='app' */}
+
+ {__('Automatic transcoding')}
+ {findingFFmpeg && }
+
+ }
+ actions={
+
+ {
+ // $FlowFixMe
+ this.onFFmpegFolder(newDirectory.path);
+ }}
+ disabled={Boolean(ffmpegPath)}
+ />
+
+ {ffmpegAvailable ? (
+
+ ),
+ }}
+ >
+ FFmpeg is correctly configured. %learn_more%
+
+ ) : (
+ this.findFFmpeg()}
+ disabled={findingFFmpeg}
+ />
+ ),
+ learn_more: (
+
+ ),
+ }}
+ >
+ FFmpeg could not be found. Navigate to it or Install, Then %check_again% or quit and restart the
+ app. %learn_more%
+
+ )}
+
+
+ }
+ />
+ {/* @endif */}
+ {!IS_WEB && (
+
+ {/* @if TARGET='app' */}
+ {/*
+ Disabling below until we get downloads to work with shared subscriptions code
+ setClientSetting(SETTINGS.AUTO_DOWNLOAD, !autoDownload)}
+ checked={autoDownload}
+ label={__('Automatically download new content from my subscriptions')}
+ helper={__(
+ "The latest file from each of your subscriptions will be downloaded for quick access as soon as it's published."
+ )}
+ /> */}
+
+
+ {connectionOptions.map((connectionOption) => (
+
+ {connectionOption}
+
+ ))}
+
+
+
+ {/* @endif */}
+
+ }
+ />
+ )}
+
+ {/* @if TARGET='app' */}
+ } />
+ {/* @endif */}
+
+ } />
+
+ {/* @if TARGET='app' */}
+ {/* Auto launch in a hidden state doesn't work on mac https://github.com/Teamwork/node-auto-launch/issues/81 */}
+ {!IS_MAC && } />}
+ } />
+ {/* @endif */}
+
+ )}
+
+ );
+ }
+}
+
+export default SettingsAdvancedPage;
diff --git a/ui/page/settingsCreator/view.jsx b/ui/page/settingsCreator/view.jsx
index a067d6478..dd27a77e0 100644
--- a/ui/page/settingsCreator/view.jsx
+++ b/ui/page/settingsCreator/view.jsx
@@ -1,15 +1,12 @@
// @flow
-import * as ICONS from 'constants/icons';
import * as React from 'react';
import Card from 'component/common/card';
import TagsSearch from 'component/tagsSearch';
import Page from 'component/page';
import Button from 'component/button';
import ChannelSelector from 'component/channelSelector';
-import SettingsRow from 'component/settingsRow';
import Spinner from 'component/spinner';
import { FormField } from 'component/common/form-components/form-field';
-import Icon from 'component/common/icon';
import LbcSymbol from 'component/common/lbc-symbol';
import I18nMessage from 'component/i18nMessage';
import { isNameValid, parseURI } from 'lbry-redux';
@@ -287,213 +284,194 @@ export default function SettingsCreatorPage(props: Props) {
-
-
-
- {isBusy && (
-
-
-
- )}
-
- {isDisabled && (
+
+ {isBusy && (
+
+
+
+ )}
+ {isDisabled && (
+
+ )}
+ {!isBusy && !isDisabled && (
+ <>
+ setSettings({ comments_enabled: !commentsEnabled })}
+ />
+ {
+ const value = parseInt(e.target.value);
+ setSlowModeMin(value);
+ pushSlowModeMinDebounced(value, activeChannelClaim);
+ }}
+ onBlur={() => setLastUpdated(Date.now())}
+ />
+ >
+ }
/>
- )}
-
- {!isBusy && !isDisabled && (
- <>
-
-
- setSettings({ comments_enabled: !commentsEnabled })}
- />
-
-
-
- {
- const value = parseInt(e.target.value);
- setSlowModeMin(value);
- pushSlowModeMinDebounced(value, activeChannelClaim);
- }}
- onBlur={() => setLastUpdated(Date.now())}
- />
-
-
- }}>Minimum %lbc% tip amount for comments
+
+
+
+ }
+ />
+
+ }}>Minimum %lbc% tip amount for comments
+ }
+ helper={__(
+ 'Enabling a minimum amount to comment will force all comments, including livestreams, to have tips associated with them. This can help prevent spam.'
+ )}
+ className="form-field--price-amount"
+ max={LBC_MAX}
+ min={LBC_MIN}
+ step={LBC_STEP}
+ type="number"
+ placeholder="1"
+ value={minTip}
+ onChange={(e) => {
+ const newMinTip = parseFloat(e.target.value);
+ setMinTip(newMinTip);
+ pushMinTipDebounced(newMinTip, activeChannelClaim);
+ if (newMinTip !== 0 && minSuper !== 0) {
+ setMinSuper(0);
+ pushMinSuperDebounced(0, activeChannelClaim);
}
- subtitle={__(HELP.MIN_TIP)}
- >
- {
- const newMinTip = parseFloat(e.target.value);
- setMinTip(newMinTip);
- pushMinTipDebounced(newMinTip, activeChannelClaim);
- if (newMinTip !== 0 && minSuper !== 0) {
- setMinSuper(0);
- pushMinSuperDebounced(0, activeChannelClaim);
- }
- }}
- onBlur={() => setLastUpdated(Date.now())}
- />
-
-
- }}>Minimum %lbc% tip amount for hyperchats
- }
- subtitle={
- <>
- {__(HELP.MIN_SUPER)}
- {minTip !== 0 && (
-
- {__(HELP.MIN_SUPER_OFF)}
-
- )}
- >
- }
- >
- {
- const newMinSuper = parseFloat(e.target.value);
- setMinSuper(newMinSuper);
- pushMinSuperDebounced(newMinSuper, activeChannelClaim);
- }}
- onBlur={() => setLastUpdated(Date.now())}
- />
-
-
-
-
-
-
-
-
-
-
-
-
- {__('Search channel')}
-
- >
- }
- placeholder={__('Enter a @username or URL')}
- value={moderatorSearchTerm}
- onChange={(e) => setModeratorSearchTerm(e.target.value)}
- error={moderatorSearchError}
- />
- {moderatorSearchClaimUri && (
-
- {
- return (
- handleChannelSearchSelect(claim)}
- />
- );
- }}
- />
-
+ }}
+ onBlur={() => setLastUpdated(Date.now())}
+ />
+ }}>Minimum %lbc% tip amount for hyperchats
+ }
+ helper={
+ <>
+ {__(
+ 'Enabling a minimum amount to hyperchat will force all TIPPED comments to have this value in order to be shown. This still allows regular comments to be posted.'
)}
-
-
- >
- }
- />
- >
- )}
-
+ {minTip !== 0 && (
+
+ {__('(This settings is not applicable if all comments require a tip.)')}
+
+ )}
+ >
+ }
+ className="form-field--price-amount"
+ min={0}
+ step="any"
+ type="number"
+ placeholder="1"
+ value={minSuper}
+ disabled={minTip !== 0}
+ onChange={(e) => {
+ const newMinSuper = parseFloat(e.target.value);
+ setMinSuper(newMinSuper);
+ pushMinSuperDebounced(newMinSuper, activeChannelClaim);
+ }}
+ onBlur={() => setLastUpdated(Date.now())}
+ />
+ >
+ }
+ />
+
+ setModeratorSearchTerm(e.target.value)}
+ error={moderatorSearchError}
+ />
+ {moderatorSearchClaimUri && (
+
+ {
+ return (
+ handleChannelSearchSelect(claim)}
+ />
+ );
+ }}
+ />
+
+ )}
+
+
+ }
+ />
+ >
+ )}
);
}
-
-// prettier-ignore
-const HELP = {
- SLOW_MODE: 'Minimum time gap in seconds between comments (affects livestream chat as well).',
- MIN_TIP: 'Enabling a minimum amount to comment will force all comments, including livestreams, to have tips associated with them. This can help prevent spam.',
- MIN_SUPER: 'Enabling a minimum amount to hyperchat will force all TIPPED comments to have this value in order to be shown. This still allows regular comments to be posted.',
- MIN_SUPER_OFF: '(This settings is not applicable if all comments require a tip.)',
- BLOCKED_WORDS: 'Comments and livestream chat containing these words will be blocked.',
- MODERATORS: 'Moderators can block channels on your behalf. Blocked channels will appear in your "Blocked and Muted" list.',
- MODERATOR_SEARCH: 'Enter a channel name or URL to add as a moderator.\nExamples:\n - @channel\n - @channel#3\n - https://odysee.com/@Odysee:8\n - lbry://@Odysee#8',
-};
diff --git a/ui/page/settingsNotifications/view.jsx b/ui/page/settingsNotifications/view.jsx
index 6d5053034..fa167cf86 100644
--- a/ui/page/settingsNotifications/view.jsx
+++ b/ui/page/settingsNotifications/view.jsx
@@ -6,7 +6,6 @@ import * as React from 'react';
import Page from 'component/page';
import { FormField } from 'component/common/form';
import Card from 'component/common/card';
-import SettingsRow from 'component/settingsRow';
import { Lbryio } from 'lbryinc';
import { useHistory } from 'react-router';
import { Redirect } from 'react-router-dom';
@@ -34,12 +33,12 @@ export default function NotificationSettingsPage(props: Props) {
React.useEffect(() => {
Lbryio.call('tag', 'list', lbryIoParams)
.then(setTags)
- .catch((e) => {
+ .catch(e => {
setError(true);
});
Lbryio.call('user_email', 'status', lbryIoParams)
- .then((res) => {
+ .then(res => {
const enabledEmails =
res.emails &&
Object.keys(res.emails).reduce((acc, email) => {
@@ -50,7 +49,7 @@ export default function NotificationSettingsPage(props: Props) {
setTagMap(res.tags);
setEnabledEmails(enabledEmails);
})
- .catch((e) => {
+ .catch(e => {
setError(true);
});
}, []);
@@ -74,7 +73,7 @@ export default function NotificationSettingsPage(props: Props) {
})
.then(() => {
const newEnabledEmails = enabledEmails
- ? enabledEmails.map((userEmail) => {
+ ? enabledEmails.map(userEmail => {
if (email === userEmail.email) {
return { email, isEnabled: newIsEnabled };
}
@@ -85,7 +84,7 @@ export default function NotificationSettingsPage(props: Props) {
setEnabledEmails(newEnabledEmails);
})
- .catch((e) => {
+ .catch(e => {
setError(true);
});
}
@@ -95,13 +94,7 @@ export default function NotificationSettingsPage(props: Props) {
}
return (
-
+
{error ? (
{/* @if TARGET='app' */}
-
-
{__('App notifications')}
-
{__('Notification settings for the desktop app.')}
-
- setClientSetting(SETTINGS.OS_NOTIFICATIONS_ENABLED, !osNotificationsEnabled)}
- checked={osNotificationsEnabled}
- />
-
+ title={__('App notifications')}
+ subtitle={__('Notification settings for the desktop app.')}
+ actions={
+ setClientSetting(SETTINGS.OS_NOTIFICATIONS_ENABLED, !osNotificationsEnabled)}
+ checked={osNotificationsEnabled}
+ label={__('Show Desktop Notifications')}
+ helper={__('Get notified when an upload or channel is confirmed.')}
+ />
}
/>
+
{/* @endif */}
{enabledEmails && enabledEmails.length > 0 && (
- <>
-
-
- {enabledEmails.length === 1 ? __('Your email') : __('Receiving addresses')}
-
-
- {__('Uncheck your email below if you want to stop receiving messages.')}
-
-
-
- {enabledEmails.map(({ email, isEnabled }) => (
-
- handleChangeEmail(email, !isEnabled)}
- checked={isEnabled}
- />
-
- ))}
- >
- }
- />
- >
+
+ {enabledEmails.map(({ email, isEnabled }) => (
+ handleChangeEmail(email, !isEnabled)}
+ checked={isEnabled}
+ label={email}
+ />
+ ))}
+ >
+ }
+ />
)}
{tags && tags.length > 0 && (
- <>
-
-
{__('Email preferences')}
-
- {__("Opt out of any topics you don't want to receive email about.")}
-
-
-
- {tags.map((tag) => {
- const isEnabled = tagMap[tag.name];
- return (
-
- handleChangeTag(tag.name, !isEnabled)}
- checked={isEnabled}
- />
-
- );
- })}
- >
- }
- />
- >
+
+ {tags.map(tag => {
+ const isEnabled = tagMap[tag.name];
+ return (
+ handleChangeTag(tag.name, !isEnabled)}
+ checked={isEnabled}
+ label={__(tag.description)}
+ />
+ );
+ })}
+ >
+ }
+ />
)}
)}
diff --git a/ui/page/settingsStripeAccount/view.jsx b/ui/page/settingsStripeAccount/view.jsx
index fc63e9e42..c0a73b7d8 100644
--- a/ui/page/settingsStripeAccount/view.jsx
+++ b/ui/page/settingsStripeAccount/view.jsx
@@ -194,13 +194,7 @@ class StripeAccountConnection extends React.Component {
} = this.state;
return (
-
+
{__('Connect a bank account')}}
isBodyList
@@ -281,7 +275,8 @@ class StripeAccountConnection extends React.Component {
)}
}
- actions={
+ // only show additional buttons if its for additional verification or to show transaction page
+ actions={(stillRequiringVerification || accountConfirmed) &&
<>
{stillRequiringVerification && (
{
className="stripe__complete-verification-button"
/>
)}
-
+ {accountConfirmed && (
+
+ )}
>
}
/>
diff --git a/ui/page/settingsStripeCard/view.jsx b/ui/page/settingsStripeCard/view.jsx
index 3b101d012..aba7e166e 100644
--- a/ui/page/settingsStripeCard/view.jsx
+++ b/ui/page/settingsStripeCard/view.jsx
@@ -354,13 +354,7 @@ class SettingsStripeCard extends React.Component {
const { currentFlowStage, pageTitle, userCardDetails, paymentMethodId } = this.state;
return (
-
+
{scriptFailedToLoad && (
{__('There was an error connecting to Stripe. Please try again later.')}
@@ -426,7 +420,7 @@ class SettingsStripeCard extends React.Component
{
button="primary"
label={__('View Transactions')}
icon={ICONS.SETTINGS}
- navigate={`/$/${PAGES.WALLET}?tab=fiat-account-history`}
+ navigate={`/$/${PAGES.WALLET}?fiatType=outgoing&tab=fiat-payment-history¤cy=fiat`}
/>
}
/>
diff --git a/ui/page/wallet/view.jsx b/ui/page/wallet/view.jsx
index d056e74d9..cd667949a 100644
--- a/ui/page/wallet/view.jsx
+++ b/ui/page/wallet/view.jsx
@@ -2,18 +2,12 @@
import React from 'react';
import { useHistory } from 'react-router';
import WalletBalance from 'component/walletBalance';
-import WalletFiatBalance from 'component/walletFiatBalance';
-import WalletFiatPaymentBalance from 'component/walletFiatPaymentBalance';
-import WalletFiatAccountHistory from 'component/walletFiatAccountHistory';
-import WalletFiatPaymentHistory from 'component/walletFiatPaymentHistory';
import TxoList from 'component/txoList';
import Page from 'component/page';
import * as PAGES from 'constants/pages';
import Spinner from 'component/spinner';
import YrblWalletEmpty from 'component/yrblWalletEmpty';
-import { Lbryio } from 'lbryinc';
import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs';
-import { getStripeEnvironment } from 'util/stripe';
const TAB_QUERY = 'tab';
@@ -23,8 +17,6 @@ const TABS = {
PAYMENT_HISTORY: 'fiat-payment-history',
};
-let stripeEnvironment = getStripeEnvironment();
-
type Props = {
history: { action: string, push: (string) => void, replace: (string) => void },
location: { search: string, pathname: string },
@@ -73,84 +65,6 @@ const WalletPage = (props: Props) => {
push(url);
}
- const [accountStatusResponse, setAccountStatusResponse] = React.useState();
- const [accountTransactionResponse, setAccountTransactionResponse] = React.useState([]);
- const [customerTransactions, setCustomerTransactions] = React.useState([]);
-
- function getPaymentHistory() {
- return Lbryio.call(
- 'customer',
- 'list',
- {
- environment: stripeEnvironment,
- },
- 'post'
- );
- }
-
- function getAccountStatus() {
- return Lbryio.call(
- 'account',
- 'status',
- {
- environment: stripeEnvironment,
- },
- 'post'
- );
- }
-
- function getAccountTransactionsa() {
- return Lbryio.call(
- 'account',
- 'list',
- {
- environment: stripeEnvironment,
- },
- 'post'
- );
- }
-
- // calculate account transactions section
- React.useEffect(() => {
- (async function () {
- try {
- if (!stripeEnvironment) {
- return;
- }
- const response = await getAccountStatus();
-
- setAccountStatusResponse(response);
-
- // TODO: some weird naming clash hence getAccountTransactionsa
- const getAccountTransactions = await getAccountTransactionsa();
-
- setAccountTransactionResponse(getAccountTransactions);
- } catch (err) {
- console.log(err);
- }
- })();
- }, [stripeEnvironment]);
-
- // populate customer payment data
- React.useEffect(() => {
- (async function () {
- try {
- // get card payments customer has made
- if (!stripeEnvironment) {
- return;
- }
- let customerTransactionResponse = await getPaymentHistory();
- if (customerTransactionResponse && customerTransactionResponse.length) {
- customerTransactionResponse.reverse();
- }
-
- setCustomerTransactions(customerTransactionResponse);
- } catch (err) {
- console.log(err);
- }
- })();
- }, [stripeEnvironment]);
-
// @endif
const { totalBalance } = props;
@@ -159,80 +73,67 @@ const WalletPage = (props: Props) => {
return (
<>
- {stripeEnvironment && (
-
-
-
- {__('LBRY Credits')}
- {__('Account History')}
- {__('Payment History')}
-
-
-
-
-
- {/* if the transactions are loading */}
- {loading && (
-
-
-
- )}
- {/* when the transactions are finished loading */}
- {!loading && (
- <>
- {showIntro ? (
-
- ) : (
-
-
-
-
- )}
- >
- )}
-
+ {/* @if TARGET='web' */}
+
+
+
+ {__('Balance')}
+ {__('Transactions')}
+
+
+ {/* balances for lbc and fiat */}
+
+
+
+ {/* transactions panel */}
+
+
+
+ {/* if the transactions are loading */}
+ {loading && (
+
+
+
+ )}
+ {/* when the transactions are finished loading */}
+ {!loading && (
+ <>
+ {showIntro ? (
+
+ ) : (
+
+
+
+ )}
+ >
+ )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
- {!stripeEnvironment && (
-
- {loading && (
-
-
-
- )}
- {!loading && (
- <>
- {showIntro ? (
-
- ) : (
-
-
-
-
- )}
- >
- )}
-
- )}
+
+
+
+
+
+ {/* @endif */}
+ {/* @if TARGET='app' */}
+
+ {loading && (
+
+
+
+ )}
+ {!loading && (
+ <>
+ {showIntro ? (
+
+ ) : (
+
+
+
+ )}
+ >
+ )}
+
+ {/* @endif */}
>
);
};
diff --git a/ui/scss/component/_livestream.scss b/ui/scss/component/_livestream.scss
index d2c0961a8..4654cb9a4 100644
--- a/ui/scss/component/_livestream.scss
+++ b/ui/scss/component/_livestream.scss
@@ -1,5 +1,4 @@
$discussion-header__height: 3rem;
-$recent-msg-button__height: 2rem;
.livestream {
flex: 1;
@@ -142,19 +141,6 @@ $recent-msg-button__height: 2rem;
top: var(--spacing-xs);
}
-.livestream__comments__scroll-to-recent {
- margin-top: -$recent-msg-button__height;
- align-self: center;
- margin-bottom: var(--spacing-xs);
- font-size: var(--font-xsmall);
- padding: var(--spacing-xxs) var(--spacing-s);
- opacity: 0.9;
-
- &:hover {
- opacity: 1;
- }
-}
-
.livestream__comment-create {
padding: var(--spacing-s);
border-top: 1px solid var(--color-border);
diff --git a/ui/scss/component/_main.scss b/ui/scss/component/_main.scss
index 102237112..e4814d29a 100644
--- a/ui/scss/component/_main.scss
+++ b/ui/scss/component/_main.scss
@@ -221,24 +221,6 @@
}
}
-.main--settings-page {
- width: 100%;
- max-width: 70rem;
- margin-left: auto;
- margin-right: auto;
- margin-top: var(--spacing-m);
- padding: 0 var(--spacing-m);
-
- .card__subtitle {
- margin: 0 0 var(--spacing-s) 0;
- font-size: var(--font-small);
- }
-
- .button--inverse {
- color: var(--color-primary);
- }
-}
-
.main--markdown {
flex-direction: column;
}
diff --git a/ui/scss/component/_txo-list.scss b/ui/scss/component/_txo-list.scss
index 58d38adf5..0f41612e6 100644
--- a/ui/scss/component/_txo-list.scss
+++ b/ui/scss/component/_txo-list.scss
@@ -10,3 +10,21 @@
display: block;
}
}
+
+.txo__table_header {
+ width: 124px;
+ display: inline-block;
+}
+
+// displaying fiat transactions (incoming/outgoing) in wallet
+.wallet__fiat-transactions {
+ text-align: center;
+ margin-top: 13px;
+ margin-bottom: 9px;
+ font-size: 13px;
+ color: rgb(171, 171, 171);
+}
+
+.txo__radios_container, .txo__radios, .txo__radios_fieldset {
+ display: inline !important;
+}
diff --git a/ui/scss/component/section.scss b/ui/scss/component/section.scss
index a45b88a7e..2c6fd46f8 100644
--- a/ui/scss/component/section.scss
+++ b/ui/scss/component/section.scss
@@ -140,7 +140,7 @@
margin-right: var(--spacing-s);
}
- @media (max-width: $breakpoint-medium) {
+ @media (max-width: $breakpoint-small) {
flex-wrap: wrap;
> * {
@@ -203,91 +203,3 @@
margin-right: 10px;
}
}
-
-.settings__row {
- &:first-child,
- &:only-child {
- border-top: none;
- }
-}
-
-.settings__row--title {
- min-width: 100%;
- align-self: flex-start;
-
- @media (min-width: $breakpoint-small) {
- min-width: 60%;
- max-width: 60%;
- }
-}
-
-.settings__row--subtitle {
- @extend .section__subtitle;
- font-size: var(--font-small);
- margin-top: calc(var(--spacing-xxs) / 2);
-}
-
-.settings__row--value {
- width: 100%;
-
- fieldset-section:not(:only-child) {
- margin-top: var(--spacing-s);
- }
-
- fieldset-section.radio {
- margin-top: var(--spacing-s);
- }
-
- fieldset-group {
- margin-top: var(--spacing-m);
- }
-
- .tags--remove {
- margin-bottom: 0;
- }
-
- .tags__input-wrapper {
- .tag__input {
- height: unset;
- max-width: unset;
- }
- }
-
- .form-field--price-amount {
- max-width: unset;
- }
-
- @media (min-width: $breakpoint-medium) {
- width: 40%;
- margin-left: var(--spacing-m);
- padding-left: var(--spacing-m);
-
- .button,
- .checkbox {
- &:only-child {
- float: right;
- }
- }
-
- input {
- align-self: flex-end;
- }
- }
-}
-
-.settings__row--value--multirow {
- @media (min-width: $breakpoint-medium) {
- width: 80%;
- margin-top: var(--spacing-l);
-
- input {
- align-self: flex-start;
- }
- }
-}
-
-.settings__row--value--vertical-separator {
- @media (min-width: $breakpoint-medium) {
- border-left: 1px solid var(--color-border);
- }
-}
diff --git a/web/scss/themes/odysee/dark.scss b/web/scss/themes/odysee/dark.scss
index ae5d31e53..6cae5e194 100644
--- a/web/scss/themes/odysee/dark.scss
+++ b/web/scss/themes/odysee/dark.scss
@@ -26,6 +26,12 @@
--color-help-warning-text: var(--color-white-alt);
--color-help-warning-bg: #fbbf2450;
+ // Tags (words)
+ --color-tag-words: var(--color-text);
+ --color-tag-words-bg: var(--color-gray-5);
+ --color-tag-words-hover: var(--color-white);
+ --color-tag-words-bg-hover: var(--color-gray-4);
+
// Header
--color-header-button: #38274c;
--color-header-background: #231830;
diff --git a/web/scss/themes/odysee/init/_base-theme.scss b/web/scss/themes/odysee/init/_base-theme.scss
index f03b4a055..76096b53c 100644
--- a/web/scss/themes/odysee/init/_base-theme.scss
+++ b/web/scss/themes/odysee/init/_base-theme.scss
@@ -115,10 +115,10 @@
--color-tag-bg-hover: var(--color-button-primary-bg);
// Tags (words)
- --color-tag-words: var(--color-primary);
- --color-tag-words-bg: var(--color-primary-alt);
- --color-tag-words-hover: var(--color-primary);
- --color-tag-words-bg-hover: var(--color-primary-alt-3);
+ --color-tag-words: var(--color-gray-5);
+ --color-tag-words-bg: var(--color-button-alt-bg);
+ --color-tag-words-hover: var(--color-button-alt-text);
+ --color-tag-words-bg-hover: var(--color-button-alt-bg-hover);
// Menu
--color-menu-background: var(--color-header-background);