diff --git a/static/app-strings.json b/static/app-strings.json index 6e93c4912..0e1d72689 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2247,5 +2247,7 @@ "This support is priced in $USD.": "This support is priced in $USD.", "The current exchange rate for the submitted LBC amount is ~ $%exchange_amount%.": "The current exchange rate for the submitted LBC amount is ~ $%exchange_amount%.", "Amount of $%input_amount% LBC in USB is lower than price of $%price_amount%": "Amount of $%input_amount% LBC in USB is lower than price of $%price_amount%", + "Hosting for content you have downloaded": "Hosting for content you have downloaded", + "Hosting content selected by the network": "Hosting content selected by the network", "--end--": "--end--" } diff --git a/ui/component/common/header-menu-link.jsx b/ui/component/common/header-menu-link.jsx new file mode 100644 index 000000000..c5c14d385 --- /dev/null +++ b/ui/component/common/header-menu-link.jsx @@ -0,0 +1,22 @@ +// @flow +import React from 'react'; +import { Link } from 'react-router-dom'; +import { MenuLink } from '@reach/menu-button'; +import Icon from 'component/common/icon'; + +type Props = { + icon: string, + name: string, + page: string, +}; + +export default function HeaderMenuLink(props: Props) { + const { icon, name, page } = props; + + return ( + + + {name} + + ); +} diff --git a/ui/component/header/index.js b/ui/component/header/index.js index a320ff346..34835dbd5 100644 --- a/ui/component/header/index.js +++ b/ui/component/header/index.js @@ -1,42 +1,31 @@ -import * as MODALS from 'constants/modal_types'; -import * as SETTINGS from 'constants/settings'; import { connect } from 'react-redux'; -import { selectTotalBalance, selectBalance } from 'redux/selectors/wallet'; -import { formatCredits } from 'util/format-credits'; -import { selectGetSyncErrorMessage } from 'redux/selectors/sync'; -import { selectUserVerifiedEmail, selectUserEmail, selectEmailToVerify, selectUser } from 'redux/selectors/user'; import { doClearEmailEntry, doClearPasswordEntry } from 'redux/actions/user'; -import { doSetClientSetting } from 'redux/actions/settings'; -import { doSignOut, doOpenModal } from 'redux/actions/app'; -import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; -import { selectHasNavigated, selectActiveChannelClaim } from 'redux/selectors/app'; +import { doSignOut } from 'redux/actions/app'; +import { formatCredits } from 'util/format-credits'; +import { selectClientSetting } from 'redux/selectors/settings'; +import { selectGetSyncErrorMessage } from 'redux/selectors/sync'; +import { selectHasNavigated } from 'redux/selectors/app'; +import { selectTotalBalance, selectBalance } from 'redux/selectors/wallet'; +import { selectUserVerifiedEmail, selectEmailToVerify, selectUser } from 'redux/selectors/user'; +import * as SETTINGS from 'constants/settings'; import Header from './view'; -import { selectMyChannelClaims } from 'redux/selectors/claims'; const select = (state) => ({ - language: selectLanguage(state), - balance: selectBalance(state), - roundedSpendableBalance: formatCredits(selectBalance(state), 2, true), - roundedBalance: formatCredits(selectTotalBalance(state), 2, true), - currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state), - automaticDarkModeEnabled: makeSelectClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED)(state), - hideBalance: makeSelectClientSetting(SETTINGS.HIDE_BALANCE)(state), authenticated: selectUserVerifiedEmail(state), - email: selectUserEmail(state), - syncError: selectGetSyncErrorMessage(state), + balance: selectBalance(state), emailToVerify: selectEmailToVerify(state), hasNavigated: selectHasNavigated(state), + hideBalance: selectClientSetting(state, SETTINGS.HIDE_BALANCE), + roundedBalance: formatCredits(selectTotalBalance(state), 2, true), + roundedSpendableBalance: formatCredits(selectBalance(state), 2, true), + syncError: selectGetSyncErrorMessage(state), user: selectUser(state), - activeChannelClaim: selectActiveChannelClaim(state), - myChannels: selectMyChannelClaims(state), }); const perform = (dispatch) => ({ - setClientSetting: (key, value, push) => dispatch(doSetClientSetting(key, value, push)), - signOut: () => dispatch(doSignOut()), - openSignOutModal: () => dispatch(doOpenModal(MODALS.SIGN_OUT)), clearEmailEntry: () => dispatch(doClearEmailEntry()), clearPasswordEntry: () => dispatch(doClearPasswordEntry()), + signOut: () => dispatch(doSignOut()), }); export default connect(select, perform)(Header); diff --git a/ui/component/header/view.jsx b/ui/component/header/view.jsx index 9026ded84..fe919a4f6 100644 --- a/ui/component/header/view.jsx +++ b/ui/component/header/view.jsx @@ -1,46 +1,22 @@ // @flow -import { ENABLE_UI_NOTIFICATIONS } from 'config'; -import * as ICONS from 'constants/icons'; -import * as SETTINGS from 'constants/settings'; -import * as PAGES from 'constants/pages'; -import React from 'react'; -import { withRouter } from 'react-router'; -import classnames from 'classnames'; -import Button from 'component/button'; -import WunderBar from 'component/wunderbar'; -import Icon from 'component/common/icon'; -import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; -import NavigationButton from 'component/navigationButton'; import { useIsMobile } from 'effects/use-screensize'; -import NotificationBubble from 'component/notificationBubble'; -import NotificationHeaderButton from 'component/notificationHeaderButton'; -import ChannelThumbnail from 'component/channelThumbnail'; -import SkipNavigationButton from 'component/skipNavigationButton'; +import { withRouter } from 'react-router'; +import * as ICONS from 'constants/icons'; +import * as PAGES from 'constants/pages'; +import Button from 'component/button'; +import classnames from 'classnames'; +import HeaderMenuButtons from 'component/headerMenuButtons'; +import HeaderProfileMenuButton from 'component/headerProfileMenuButton'; import Logo from 'component/logo'; +import NotificationBubble from 'component/notificationBubble'; +import React from 'react'; +import SkipNavigationButton from 'component/skipNavigationButton'; +import WunderBar from 'component/wunderbar'; import * as remote from '@electron/remote'; import { IS_MAC } from 'component/app/view'; +import NavigationButton from 'component/navigationButton'; type Props = { - user: ?User, - balance: string, - balance: number, - roundedBalance: string, - roundedSpendableBalance: string, - history: { - entities: {}[], - goBack: () => void, - goForward: () => void, - index: number, - length: number, - location: { pathname: string }, - push: (string) => void, - replace: (string) => void, - }, - currentTheme: string, - automaticDarkModeEnabled: boolean, - setClientSetting: (string, boolean | string, ?boolean) => void, - hideBalance: boolean, - email: ?string, authenticated: boolean, authHeader: boolean, backout: { @@ -49,147 +25,128 @@ type Props = { title: string, simpleTitle: string, // Just use the same value as `title` if `title` is already short (~< 10 chars), unless you have a better idea for title overlfow on mobile }, - syncError: ?string, + balance: number, emailToVerify?: string, - signOut: () => void, - openSignOutModal: () => void, + hasNavigated: boolean, + hideBalance: boolean, + hideCancel: boolean, + history: { + goBack: () => void, + location: { pathname: string }, + push: (string) => void, + replace: (string) => void, + }, + isAbsoluteSideNavHidden: boolean, + roundedBalance: string, + roundedSpendableBalance: string, + sidebarOpen: boolean, + syncError: ?string, clearEmailEntry: () => void, clearPasswordEntry: () => void, - hasNavigated: boolean, - sidebarOpen: boolean, setSidebarOpen: (boolean) => void, - isAbsoluteSideNavHidden: boolean, - hideCancel: boolean, - activeChannelClaim: ?ChannelClaim, - myChannels: ?Array, + signOut: () => void, }; const Header = (props: Props) => { const { - balance, - roundedBalance, - roundedSpendableBalance, - history, - setClientSetting, - currentTheme, - automaticDarkModeEnabled, - hideBalance, - email, authenticated, authHeader, - signOut, + backout, + balance, + emailToVerify, + hideBalance, + hideCancel, + history, + isAbsoluteSideNavHidden, + roundedBalance, + roundedSpendableBalance, + sidebarOpen, syncError, - openSignOutModal, clearEmailEntry, clearPasswordEntry, - emailToVerify, - backout, - sidebarOpen, setSidebarOpen, - isAbsoluteSideNavHidden, - hideCancel, - user, - activeChannelClaim, - myChannels, + signOut, } = props; + + const { + location: { pathname }, + goBack, + push, + } = history; + const isMobile = useIsMobile(); + // on the verify page don't let anyone escape other than by closing the tab to keep session data consistent - const isVerifyPage = history.location.pathname.includes(PAGES.AUTH_VERIFY); - const isSignUpPage = history.location.pathname.includes(PAGES.AUTH); - const isSignInPage = history.location.pathname.includes(PAGES.AUTH_SIGNIN); - const isPwdResetPage = history.location.pathname.includes(PAGES.AUTH_PASSWORD_RESET); - const hasBackout = Boolean(backout); + const isVerifyPage = pathname.includes(PAGES.AUTH_VERIFY); + const isSignUpPage = pathname.includes(PAGES.AUTH); + const isSignInPage = pathname.includes(PAGES.AUTH_SIGNIN); + const isPwdResetPage = pathname.includes(PAGES.AUTH_PASSWORD_RESET); + + // For pages that allow for "backing out", shows a backout option instead of the Home logo + const canBackout = Boolean(backout); const { backLabel, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {}; - const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui); - const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url; - const hasChannels = myChannels && myChannels.length > 0; // Sign out if they click the "x" when they are on the password prompt - const authHeaderAction = syncError ? { onClick: signOut } : { navigate: '/' }; - const homeButtonNavigationProps = isVerifyPage ? {} : authHeader ? authHeaderAction : { navigate: '/' }; - const closeButtonNavigationProps = { - onClick: () => { - clearEmailEntry(); - clearPasswordEntry(); + const authHeaderAction = syncError && { onClick: signOut }; + const homeButtonNavigationProps = (isVerifyPage && {}) || (authHeader && authHeaderAction) || { navigate: '/' }; + const sidebarLabel = sidebarOpen + ? __('Close sidebar - hide channels you are following.') + : __('Expand sidebar - view channels you are following.'); - if (syncError) { - signOut(); - } + const onBackout = React.useCallback( + (e: any) => { + const { hasNavigated } = props; + const { replace } = history; - if (isSignInPage && !emailToVerify) { - history.goBack(); - } else if (isSignUpPage) { - history.goBack(); - } else if (isPwdResetPage) { - history.goBack(); - } else { - history.push('/'); + window.removeEventListener('popstate', onBackout); + + if (e.type !== 'popstate') { + // if not initiated by pop (back button) + if (hasNavigated && !backNavDefault) { + goBack(); + } else { + replace(backNavDefault || `/`); + } } }, - }; - - function onBackout(e) { - const { history, hasNavigated } = props; - const { goBack, replace } = history; - - window.removeEventListener('popstate', onBackout); - - if (e.type !== 'popstate') { - // if not initiated by pop (back button) - if (hasNavigated && !backNavDefault) { - goBack(); - } else { - replace(backNavDefault || `/`); - } - } - } + [backNavDefault, goBack, history, props] + ); React.useEffect(() => { - if (hasBackout) { + if (canBackout) { window.addEventListener('popstate', onBackout); return () => window.removeEventListener('popstate', onBackout); } - }, [hasBackout]); + }, [canBackout, onBackout]); - function handleThemeToggle() { - if (automaticDarkModeEnabled) { - setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false); - } + const userButtons = (className: string) => ( +
+
); return (
{ @@ -198,38 +155,33 @@ const Header = (props: Props) => { // @endif >
- {!authHeader && backout ? ( + {!authHeader && canBackout ? (
-
) : ( <>
+ {!authHeader && ( )} +
)} {/* @endif */} - - {!authHeader && } - - + +
)} - {!authHeader && !backout ? ( -
- - - { - e.stopPropagation(); - }} - // @endif - > - {activeChannelUrl ? ( - - ) : ( - - )} - - - history.push(`/$/${PAGES.UPLOADS}`)}> - - {__('Uploads')} - - history.push(`/$/${PAGES.CHANNELS}`)}> - - {__('Channels')} - - {hasChannels && authenticated && ( - history.push(`/$/${PAGES.CREATOR_DASHBOARD}`)}> - - {__('Creator Analytics')} - - )} - {authenticated ? ( - -
- - {__('Sign Out')} -
- {email} -
- ) : ( - <> - history.push(`/$/${PAGES.AUTH_SIGNIN}`)}> - - {__('Cloud Connect')} - - - )} -
-
-
- ) : ( - !isVerifyPage && - !hideCancel && ( -
- {/* Add an empty span here so we can use the same style as above */} - {/* This pushes the close button to the right side */} - + {!authHeader && !canBackout + ? userButtons('header__navigation-item menu__title mobile-hidden') + : !isVerifyPage && + !hideCancel && ( +
+ {/* Add an empty span here so we can use the same style as above */} + {/* This pushes the close button to the right side */} + -
- ) - )} +
+ )} )} @@ -357,77 +250,4 @@ const Header = (props: Props) => { ); }; -type HeaderMenuButtonProps = { - authenticated: boolean, - notificationsEnabled: boolean, - history: { push: (string) => void }, - handleThemeToggle: (string) => void, - currentTheme: string, -}; - -function HeaderMenuButtons(props: HeaderMenuButtonProps) { - const { notificationsEnabled, history, handleThemeToggle, currentTheme } = props; - - return ( -
- - { - e.stopPropagation(); - }} - // @endif - > - - - - - history.push(`/$/${PAGES.UPLOAD}`)}> - - {__('Upload')} - - history.push(`/$/${PAGES.CHANNEL_NEW}`)}> - - {__('New Channel')} - - - - - {notificationsEnabled && } - - - { - e.stopPropagation(); - }} - // @endif - > - - - - history.push(`/$/${PAGES.SETTINGS}`)}> - - {__('Settings')} - - history.push(`/$/${PAGES.HELP}`)}> - - {__('Help')} - - - - {currentTheme === 'light' ? __('Dark') : __('Light')} - - - -
- ); -} - export default withRouter(Header); diff --git a/ui/component/headerMenuButtons/index.js b/ui/component/headerMenuButtons/index.js new file mode 100644 index 000000000..dab91821b --- /dev/null +++ b/ui/component/headerMenuButtons/index.js @@ -0,0 +1,24 @@ +import { connect } from 'react-redux'; +import { doSetClientSetting } from 'redux/actions/settings'; +import { selectActiveChannelStakedLevel } from 'redux/selectors/app'; +import { selectClientSetting } from 'redux/selectors/settings'; +import * as SETTINGS from 'constants/settings'; +import HeaderMenuButtons from './view'; +import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user'; + +const select = (state) => ({ + activeChannelStakedLevel: selectActiveChannelStakedLevel(state), + authenticated: selectUserVerifiedEmail(state), + automaticDarkModeEnabled: selectClientSetting(state, SETTINGS.AUTOMATIC_DARK_MODE_ENABLED), + currentTheme: selectClientSetting(state, SETTINGS.THEME), + user: selectUser(state), +}); + +const perform = (dispatch) => ({ + handleThemeToggle: (automaticDarkModeEnabled, currentTheme) => { + if (automaticDarkModeEnabled) dispatch(doSetClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false)); + dispatch(doSetClientSetting(SETTINGS.THEME, currentTheme === 'dark' ? 'light' : 'dark', true)); + }, +}); + +export default connect(select, perform)(HeaderMenuButtons); diff --git a/ui/component/headerMenuButtons/view.jsx b/ui/component/headerMenuButtons/view.jsx new file mode 100644 index 000000000..d315feb64 --- /dev/null +++ b/ui/component/headerMenuButtons/view.jsx @@ -0,0 +1,64 @@ +// @flow +import { ENABLE_UI_NOTIFICATIONS } from 'config'; +import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; +import * as ICONS from 'constants/icons'; +import * as PAGES from 'constants/pages'; +import HeaderMenuLink from 'component/common/header-menu-link'; +import Icon from 'component/common/icon'; +import NotificationHeaderButton from 'component/notificationHeaderButton'; +import React from 'react'; + +type HeaderMenuButtonProps = { + authenticated: boolean, + automaticDarkModeEnabled: boolean, + currentTheme: string, + user: ?User, + handleThemeToggle: (boolean, string) => void, +}; + +export default function HeaderMenuButtons(props: HeaderMenuButtonProps) { + const { automaticDarkModeEnabled, currentTheme, user, handleThemeToggle } = props; + + const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui); + + return ( +
+ + + + + + + + + + + + {notificationsEnabled && } + + + + + + + + + + + handleThemeToggle(automaticDarkModeEnabled, currentTheme)}> + + {currentTheme === 'light' ? __('Dark') : __('Light')} + + + +
+ ); +} diff --git a/ui/component/headerProfileMenuButton/index.js b/ui/component/headerProfileMenuButton/index.js new file mode 100644 index 000000000..fd0afb821 --- /dev/null +++ b/ui/component/headerProfileMenuButton/index.js @@ -0,0 +1,18 @@ +import { connect } from 'react-redux'; +import { doOpenModal } from 'redux/actions/app'; +import { selectActiveChannelClaim } from 'redux/selectors/app'; +import { selectUserEmail, selectUserVerifiedEmail } from 'redux/selectors/user'; +import * as MODALS from 'constants/modal_types'; +import HeaderProfileMenuButton from './view'; + +const select = (state) => ({ + activeChannelClaim: selectActiveChannelClaim(state), + email: selectUserEmail(state), + authenticated: selectUserVerifiedEmail(state), +}); + +const perform = (dispatch) => ({ + openSignOutModal: () => dispatch(doOpenModal(MODALS.SIGN_OUT)), +}); + +export default connect(select, perform)(HeaderProfileMenuButton); diff --git a/ui/component/headerProfileMenuButton/view.jsx b/ui/component/headerProfileMenuButton/view.jsx new file mode 100644 index 000000000..1e35de7ac --- /dev/null +++ b/ui/component/headerProfileMenuButton/view.jsx @@ -0,0 +1,61 @@ +// @flow +import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; +import * as ICONS from 'constants/icons'; +import * as PAGES from 'constants/pages'; +import ChannelThumbnail from 'component/channelThumbnail'; +import classnames from 'classnames'; +import HeaderMenuLink from 'component/common/header-menu-link'; +import Icon from 'component/common/icon'; +import React from 'react'; + +type HeaderMenuButtonProps = { + activeChannelClaim: ?ChannelClaim, + email: ?string, + authenticated: boolean, + openSignOutModal: () => void, +}; + +export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) { + const { activeChannelClaim, email, openSignOutModal, authenticated } = props; + + const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url; + + return ( +
+ + + {activeChannelUrl ? ( + + ) : ( + + )} + + + + + + + + {authenticated ? ( + +
+ + {__('Sign Out')} +
+ {email} +
+ ) : ( + + )} +
+
+
+ ); +} diff --git a/ui/modal/modalRouter/view.jsx b/ui/modal/modalRouter/view.jsx index 353d39e22..7ce9ba59d 100644 --- a/ui/modal/modalRouter/view.jsx +++ b/ui/modal/modalRouter/view.jsx @@ -72,6 +72,100 @@ import ModalWalletUnlock from 'modal/modalWalletUnlock'; import ModalYoutubeWelcome from 'modal/modalYoutubeWelcome'; +function getModal(id) { + switch (id) { + case MODALS.UPGRADE: + return ModalUpgrade; + case MODALS.DOWNLOADING: + return ModalDownloading; + case MODALS.AUTO_GENERATE_THUMBNAIL: + return ModalAutoGenerateThumbnail; + case MODALS.AUTO_UPDATE_DOWNLOADED: + return ModalAutoUpdateDownloaded; + case MODALS.ERROR: + return ModalError; + case MODALS.FILE_TIMEOUT: + return ModalFileTimeout; + case MODALS.FIRST_REWARD: + return ModalFirstReward; + case MODALS.TRANSACTION_FAILED: + return ModalTransactionFailed; + case MODALS.CONFIRM_FILE_REMOVE: + return ModalRemoveFile; + case MODALS.AFFIRM_PURCHASE: + return ModalAffirmPurchase; + case MODALS.CONFIRM_CLAIM_REVOKE: + return ModalRevokeClaim; + case MODALS.PHONE_COLLECTION: + return ModalPhoneCollection; + case MODALS.FIRST_SUBSCRIPTION: + return ModalFirstSubscription; + case MODALS.SEND_TIP: + return ModalSendTip; + case MODALS.REPOST: + return ModalRepost; + case MODALS.SOCIAL_SHARE: + return ModalSocialShare; + case MODALS.PUBLISH: + return ModalPublish; + case MODALS.PUBLISH_PREVIEW: + return ModalPublishPreview; + case MODALS.CONFIRM_EXTERNAL_RESOURCE: + return ModalOpenExternalResource; + case MODALS.CONFIRM_TRANSACTION: + return ModalConfirmTransaction; + case MODALS.CONFIRM_THUMBNAIL_UPLOAD: + return ModalConfirmThumbnailUpload; + case MODALS.WALLET_ENCRYPT: + return ModalWalletEncrypt; + case MODALS.WALLET_DECRYPT: + return ModalWalletDecrypt; + case MODALS.WALLET_UNLOCK: + return ModalWalletUnlock; + case MODALS.WALLET_PASSWORD_UNSAVE: + return ModalPasswordUnsave; + case MODALS.REWARD_GENERATED_CODE: + return ModalRewardCode; + case MODALS.COMMENT_ACKNOWEDGEMENT: + return ModalCommentAcknowledgement; + case MODALS.YOUTUBE_WELCOME: + return ModalYoutubeWelcome; + case MODALS.SET_REFERRER: + return ModalSetReferrer; + case MODALS.SIGN_OUT: + return ModalSignOut; + case MODALS.CONFIRM_AGE: + return ModalConfirmAge; + case MODALS.FILE_SELECTION: + return ModalFileSelection; + case MODALS.LIQUIDATE_SUPPORTS: + return ModalSupportsLiquidate; + case MODALS.IMAGE_UPLOAD: + return ModalImageUpload; + case MODALS.SYNC_ENABLE: + return ModalSyncEnable; + case MODALS.MOBILE_SEARCH: + return ModalMobileSearch; + case MODALS.VIEW_IMAGE: + return ModalViewImage; + case MODALS.MASS_TIP_UNLOCK: + return ModalMassTipsUnlock; + case MODALS.CONFIRM_REMOVE_BTC_SWAP_ADDRESS: + return ModalRemoveBtcSwapAddress; + case MODALS.BLOCK_CHANNEL: + return ModalBlockChannel; + case MODALS.COLLECTION_ADD: + return ModalClaimCollectionAdd; + case MODALS.COLLECTION_DELETE: + return ModalDeleteCollection; + case MODALS.CONFIRM_REMOVE_CARD: + return ModalRemoveCard; + case MODALS.CONFIRM_REMOVE_COMMENT: + return ModalRemoveComment; + default: + return null; + } +} type Props = { modal: { id: string, modalProps: {} }, error: { message: string }, @@ -94,102 +188,6 @@ function ModalRouter(props: Props) { if (!modal) { return null; } - - function getModal(id) { - switch (id) { - case MODALS.UPGRADE: - return ModalUpgrade; - case MODALS.DOWNLOADING: - return ModalDownloading; - case MODALS.AUTO_GENERATE_THUMBNAIL: - return ModalAutoGenerateThumbnail; - case MODALS.AUTO_UPDATE_DOWNLOADED: - return ModalAutoUpdateDownloaded; - case MODALS.ERROR: - return ModalError; - case MODALS.FILE_TIMEOUT: - return ModalFileTimeout; - case MODALS.FIRST_REWARD: - return ModalFirstReward; - case MODALS.TRANSACTION_FAILED: - return ModalTransactionFailed; - case MODALS.CONFIRM_FILE_REMOVE: - return ModalRemoveFile; - case MODALS.AFFIRM_PURCHASE: - return ModalAffirmPurchase; - case MODALS.CONFIRM_CLAIM_REVOKE: - return ModalRevokeClaim; - case MODALS.PHONE_COLLECTION: - return ModalPhoneCollection; - case MODALS.FIRST_SUBSCRIPTION: - return ModalFirstSubscription; - case MODALS.SEND_TIP: - return ModalSendTip; - case MODALS.REPOST: - return ModalRepost; - case MODALS.SOCIAL_SHARE: - return ModalSocialShare; - case MODALS.PUBLISH: - return ModalPublish; - case MODALS.PUBLISH_PREVIEW: - return ModalPublishPreview; - case MODALS.CONFIRM_EXTERNAL_RESOURCE: - return ModalOpenExternalResource; - case MODALS.CONFIRM_TRANSACTION: - return ModalConfirmTransaction; - case MODALS.CONFIRM_THUMBNAIL_UPLOAD: - return ModalConfirmThumbnailUpload; - case MODALS.WALLET_ENCRYPT: - return ModalWalletEncrypt; - case MODALS.WALLET_DECRYPT: - return ModalWalletDecrypt; - case MODALS.WALLET_UNLOCK: - return ModalWalletUnlock; - case MODALS.WALLET_PASSWORD_UNSAVE: - return ModalPasswordUnsave; - case MODALS.REWARD_GENERATED_CODE: - return ModalRewardCode; - case MODALS.COMMENT_ACKNOWEDGEMENT: - return ModalCommentAcknowledgement; - case MODALS.YOUTUBE_WELCOME: - return ModalYoutubeWelcome; - case MODALS.SET_REFERRER: - return ModalSetReferrer; - case MODALS.SIGN_OUT: - return ModalSignOut; - case MODALS.CONFIRM_AGE: - return ModalConfirmAge; - case MODALS.FILE_SELECTION: - return ModalFileSelection; - case MODALS.LIQUIDATE_SUPPORTS: - return ModalSupportsLiquidate; - case MODALS.IMAGE_UPLOAD: - return ModalImageUpload; - case MODALS.SYNC_ENABLE: - return ModalSyncEnable; - case MODALS.MOBILE_SEARCH: - return ModalMobileSearch; - case MODALS.VIEW_IMAGE: - return ModalViewImage; - case MODALS.MASS_TIP_UNLOCK: - return ModalMassTipsUnlock; - case MODALS.CONFIRM_REMOVE_BTC_SWAP_ADDRESS: - return ModalRemoveBtcSwapAddress; - case MODALS.BLOCK_CHANNEL: - return ModalBlockChannel; - case MODALS.COLLECTION_ADD: - return ModalClaimCollectionAdd; - case MODALS.COLLECTION_DELETE: - return ModalDeleteCollection; - case MODALS.CONFIRM_REMOVE_CARD: - return ModalRemoveCard; - case MODALS.CONFIRM_REMOVE_COMMENT: - return ModalRemoveComment; - default: - return null; - } - } - const { id, modalProps } = modal; const SelectedModal = getModal(id); diff --git a/ui/redux/selectors/settings.js b/ui/redux/selectors/settings.js index 0cf497fba..5b759cc5d 100644 --- a/ui/redux/selectors/settings.js +++ b/ui/redux/selectors/settings.js @@ -20,6 +20,11 @@ export const selectClientSettings = createSelector(selectState, (state) => state export const selectLoadedLanguages = createSelector(selectState, (state) => state.loadedLanguages || {}); +export const selectClientSetting = (state, setting) => { + const clientSettings = selectClientSettings(state); + return clientSettings ? clientSettings[setting] : undefined; +}; + export const makeSelectClientSetting = (setting) => createSelector(selectClientSettings, (settings) => (settings ? settings[setting] : undefined)); diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss index 0c2044388..906ec911d 100644 --- a/ui/scss/component/_header.scss +++ b/ui/scss/component/_header.scss @@ -61,7 +61,6 @@ } .header__menu { - margin-left: auto; display: flex; justify-content: space-between; align-items: center;