Fixes/Changes for 0.27.0 (#2176)

* add Invite to the left nav

* fix: #2154 - only set latest content if we are on page 1 of a channel

* lower priority for channel/date on home page

* add gerbil to 'all caught up' subscription view

* fix: spacing on items in home page scrollable list

* color improvements on homepage for titles/help message

* fix: stroke width for svg inside button

* fix: grid layout on large screens

* i give up - related on the right side always

* fix: hidden claims message spacing

* general spacing improvements

* fix: nsfw file page background

* remove comment
This commit is contained in:
Sean Yesmunt 2019-01-11 11:34:36 -05:00 committed by GitHub
parent e185cdc1d6
commit bed9b1f95f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 255 additions and 236 deletions

View file

@ -155,7 +155,7 @@ class CategoryList extends PureComponent<Props, State> {
if (currentCardVisible && previousCard) {
const scrollTarget = previousCard.offsetLeft;
this.handleScroll(scrollTarget);
this.handleScroll(scrollTarget - cards[0].offsetLeft);
break;
}

View file

@ -99,7 +99,9 @@ class FileCard extends React.PureComponent<Props> {
const handleContextMenu = event => {
event.preventDefault();
event.stopPropagation();
openCopyLinkMenu(convertToShareLink(claim.permanent_url), event);
if (claim) {
openCopyLinkMenu(convertToShareLink(claim.permanent_url), event);
}
};
// We should be able to tab through cards
@ -119,11 +121,13 @@ class FileCard extends React.PureComponent<Props> {
<div className="media__title">
<TruncatedText text={title} lines={2} />
</div>
<div className="media__subtitle">
{pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />}
</div>
<div className="media__date">
<DateTime timeAgo block={height} />
<div className="media__subtext">
<div className="media__subtitle">
{pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />}
</div>
<div className="media__date">
<DateTime timeAgo block={height} />
</div>
</div>
<div className="media__properties">
<FilePrice hideFree uri={uri} />

View file

@ -1,7 +1,7 @@
// @flow
import React from 'react';
import Button from 'component/button';
import { FormField } from 'component/common/form';
import { FormField, FormRow } from 'component/common/form';
import type { Claim } from 'types/claim';
type Props = {
@ -74,48 +74,43 @@ class WalletSendTip extends React.PureComponent<Props, State> {
const { tipAmount, tipError } = this.state;
return (
<section className="card__content">
<FormField
autoFocus
label={
(tipAmount &&
tipAmount !== 0 &&
`Tip ${tipAmount.toFixed(8).replace(/\.?0+$/, '')} LBC`) ||
__('Amount')
}
postfix={__('LBC')}
className="input--price-amount"
error={tipError}
min="0"
step="any"
type="number"
placeholder="1.23"
onChange={event => this.handleSupportPriceChange(event)}
helper={
<p>
{__(`This will appear as a tip for "${title}".`)}{' '}
<Button label={__('Learn more')} button="link" href="https://lbry.io/faq/tipping" />
</p>
}
/>
<React.Fragment>
<FormRow>
<FormField
autoFocus
label={
(tipAmount &&
tipAmount !== 0 &&
`Tip ${tipAmount.toFixed(8).replace(/\.?0+$/, '')} LBC`) ||
__('Amount')
}
postfix={__('LBC')}
className="input--price-amount"
error={tipError}
min="0"
step="any"
type="number"
placeholder="1.23"
onChange={event => this.handleSupportPriceChange(event)}
helper={
<p>
{__(`This will appear as a tip for "${title}".`)}{' '}
<Button label={__('Learn more')} button="link" href="https://lbry.io/faq/tipping" />
</p>
}
/>
</FormRow>
<div className="card__content">
<div className="card__actions">
<Button
button="primary"
label={__('Send')}
disabled={isPending || tipError}
onClick={this.handleSendButtonClicked}
/>
<Button
button="link"
label={__('Cancel')}
onClick={onCancel}
navigateParams={{ uri }}
/>
</div>
<div className="card__actions">
<Button
button="primary"
label={__('Send')}
disabled={isPending || tipError}
onClick={this.handleSendButtonClicked}
/>
<Button button="link" label={__('Cancel')} onClick={onCancel} navigateParams={{ uri }} />
</div>
</section>
</React.Fragment>
);
}
}

View file

@ -72,7 +72,7 @@ export class Modal extends React.PureComponent<ModalProps> {
<h1 className="card__title">{title}</h1>
</header>
)}
<div className="card__content">{children}</div>
{children}
{type === 'custom' ? null : ( // custom modals define their own buttons
<div className="card__actions">
<Button

View file

@ -1,7 +1,7 @@
// @flow
import React from 'react';
import { Modal } from 'modal/modal';
import { FormField } from 'component/common/form';
import { FormField, FormRow } from 'component/common/form';
type Props = {
upload: (string, boolean) => void,
@ -25,16 +25,21 @@ class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
return (
<Modal
isOpen
title={__('Upload Thumbnail')}
contentLabel={__('Confirm Thumbnail Upload')}
type="confirm"
confirmButtonLabel={__('Upload')}
onConfirmed={() => this.upload()}
onAborted={closeModal}
>
<section className="card__content">
<p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p>
<blockquote>{path}</blockquote>
<header className="card__header">
<h2 className="card__title">{__('More Ways To Get LBRY Credits')}</h2>
<p className="card__subtitle">
{__('Are you sure you want to upload this thumbnail to spee.ch')}?
</p>
</header>
<blockquote>{path}</blockquote>
<FormRow>
<FormField
type="checkbox"
name="content_is_mature"
@ -42,7 +47,7 @@ class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
checked={nsfw}
onChange={event => updatePublishForm({ nsfw: event.target.checked })}
/>
</section>
</FormRow>
</Modal>
);
}

View file

@ -60,20 +60,21 @@ class ModalRemoveFile extends React.PureComponent<Props, State> {
return (
<Modal
isOpen
title={__('Remove File')}
contentLabel={__('Confirm File Remove')}
type="confirm"
confirmButtonLabel={__('Remove')}
onConfirmed={() => deleteFile(outpoint, deleteChecked, abandonClaimChecked)}
onAborted={closeModal}
>
<section className="card__content">
<p>
<header className="card__header">
<h2 className="card__title">{__('Remove File')}</h2>
<p className="card__subtitle">
{__("Are you sure you'd like to remove")} <cite>{`"${title}"`}</cite>{' '}
{__('from the LBRY app?')}
</p>
<FormRow padded>
</header>
<section className="card__content">
<FormRow>
<FormField
prefix={__('Also delete this file from my computer')}
type="checkbox"

View file

@ -15,16 +15,13 @@ const GetCreditsPage = () => (
*/}
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('More ways to get LBRY Credits')}</h2>
</header>
<div className="card__content">
<p>
<h2 className="card__title">{__('More Ways To Get LBRY Credits')}</h2>
<p className="card__subtitle">
{
'LBRY credits can be purchased on exchanges, earned for contributions, for mining, and more.'
}
</p>
</div>
</header>
<div className="card__content">
<div className="card__actions">

View file

@ -36,15 +36,6 @@ export default (props: Props) => {
} = props;
return (
<Fragment>
<HiddenNsfwClaims
uris={subscriptions.reduce((arr, { name, claim_id: claimId }) => {
if (name && claimId) {
arr.push(`lbry://${name}#${claimId}`);
}
return arr;
}, [])}
/>
{hasSubscriptions && (
<section className="card card--section">
<div className="card__content card--space-between">
@ -75,6 +66,15 @@ export default (props: Props) => {
</section>
)}
<HiddenNsfwClaims
uris={subscriptions.reduce((arr, { name, claim_id: claimId }) => {
if (name && claimId) {
arr.push(`lbry://${name}#${claimId}`);
}
return arr;
}, [])}
/>
{!hasSubscriptions && (
<Fragment>
<div className="yrbl-wrap">
@ -96,8 +96,8 @@ export default (props: Props) => {
<div className="card__content">
{viewMode === VIEW_ALL && (
<Fragment>
<div className="card__title card__title--flex">
{__('Your subscriptions')}
<div className="card__title--flex">
<h2 className="card__title">{__('Your subscriptions')}</h2>
{unreadSubscriptions.length > 0 && <MarkAsRead />}
</div>
<FileList hideFilter sortByHeight fileInfos={subscriptions} />
@ -131,9 +131,16 @@ export default (props: Props) => {
})
) : (
<Fragment>
<div className="page__empty">
<h3 className="card__title">{__('All caught up!')}</h3>
<p className="card__subtitle">{__('You might like the channels below.')}</p>
<div className="yrbl-wrap">
<img
alt="Friendly gerbil"
className="subscriptions__gerbil"
src={Native.imagePath('gerbil-happy.png')}
/>
<div className="card__content">
<h2 className="card__title">{__('All caught up!')}</h2>
<p className="card__subtitle">{__('You might like the channels below.')}</p>
</div>
</div>
<SuggestedSubscriptions />
</Fragment>

View file

@ -286,19 +286,23 @@ export function doPurchaseUri(uri, specificCostInfo, shouldRecordViewEvent) {
};
}
export function doFetchClaimsByChannel(uri, page, pageSize) {
export function doFetchClaimsByChannel(
uri: string,
page: number = 1,
pageSize: number = PAGE_SIZE
) {
return dispatch => {
dispatch({
type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED,
data: { uri, page },
});
Lbry.claim_list_by_channel({ uri, page: page || 1, page_size: pageSize || PAGE_SIZE }).then(
result => {
const claimResult = result[uri] || {};
const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult;
Lbry.claim_list_by_channel({ uri, page, page_size: pageSize }).then(result => {
const claimResult = result[uri] || {};
const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult;
if (claimsInChannel && claimsInChannel.length) {
if (claimsInChannel && claimsInChannel.length) {
if (page === 1) {
const latest = claimsInChannel[0];
dispatch(
setSubscriptionLatest(
@ -316,17 +320,17 @@ export function doFetchClaimsByChannel(uri, page, pageSize) {
)
);
}
dispatch({
type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED,
data: {
uri,
claims: claimsInChannel || [],
page: returnedPage || undefined,
},
});
}
);
dispatch({
type: ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED,
data: {
uri,
claims: claimsInChannel || [],
page: returnedPage || undefined,
},
});
});
};
}

View file

@ -4,26 +4,20 @@ import * as icons from 'constants/icons';
export const selectState = state => state.app || {};
export const selectPlatform = createSelector(
selectState,
state => state.platform
);
export const selectPlatform = createSelector(selectState, state => state.platform);
export const selectUpdateUrl = createSelector(
selectPlatform,
platform => {
switch (platform) {
case 'darwin':
return 'https://lbry.io/get/lbry.dmg';
case 'linux':
return 'https://lbry.io/get/lbry.deb';
case 'win32':
return 'https://lbry.io/get/lbry.exe';
default:
throw Error('Unknown platform');
}
export const selectUpdateUrl = createSelector(selectPlatform, platform => {
switch (platform) {
case 'darwin':
return 'https://lbry.io/get/lbry.dmg';
case 'linux':
return 'https://lbry.io/get/lbry.deb';
case 'win32':
return 'https://lbry.io/get/lbry.exe';
default:
throw Error('Unknown platform');
}
);
});
export const selectHasClickedComment = createSelector(
selectState,
@ -54,30 +48,18 @@ export const selectUpgradeFilename = createSelector(
}
);
export const selectDownloadProgress = createSelector(
selectState,
state => state.downloadProgress
);
export const selectDownloadProgress = createSelector(selectState, state => state.downloadProgress);
export const selectDownloadComplete = createSelector(
selectState,
state => state.upgradeDownloadCompleted
);
export const selectIsUpgradeSkipped = createSelector(
selectState,
state => state.isUpgradeSkipped
);
export const selectIsUpgradeSkipped = createSelector(selectState, state => state.isUpgradeSkipped);
export const selectUpgradeDownloadPath = createSelector(
selectState,
state => state.downloadPath
);
export const selectUpgradeDownloadPath = createSelector(selectState, state => state.downloadPath);
export const selectUpgradeDownloadItem = createSelector(
selectState,
state => state.downloadItem
);
export const selectUpgradeDownloadItem = createSelector(selectState, state => state.downloadItem);
export const selectAutoUpdateDownloaded = createSelector(
selectState,
@ -94,35 +76,23 @@ export const selectDaemonVersionMatched = createSelector(
state => state.daemonVersionMatched
);
export const selectSnackBar = createSelector(
selectState,
state => state.snackBar || {}
);
export const selectSnackBar = createSelector(selectState, state => state.snackBar || {});
export const selectSnackBarSnacks = createSelector(
selectSnackBar,
snackBar => snackBar.snacks || []
);
export const selectBadgeNumber = createSelector(
selectState,
state => state.badgeNumber
);
export const selectBadgeNumber = createSelector(selectState, state => state.badgeNumber);
export const selectCurrentLanguage = createSelector(
selectState,
() => app.i18n.getLocale() || 'en'
);
export const selectVolume = createSelector(
selectState,
state => state.volume
);
export const selectVolume = createSelector(selectState, state => state.volume);
export const selectUpgradeTimer = createSelector(
selectState,
state => state.checkUpgradeTimer
);
export const selectUpgradeTimer = createSelector(selectState, state => state.checkUpgradeTimer);
export const selectNavLinks = createSelector(
selectCurrentPage,
@ -134,7 +104,6 @@ export const selectNavLinks = createSelector(
page === 'getcredits' ||
page === 'rewards' ||
page === 'history' ||
page === 'invite' ||
page === 'backup';
const isMyLbryPage = page =>
@ -198,11 +167,6 @@ export const selectNavLinks = createSelector(
path: '/rewards',
active: currentPage === 'rewards',
},
{
label: 'Invites',
path: '/invite',
active: currentPage === 'invite',
},
{
label: 'Backup',
path: '/backup',
@ -258,6 +222,12 @@ export const selectNavLinks = createSelector(
path: isCurrentlyMyLbryPage ? '/downloaded' : getActiveSublink('myLbry'),
active: isMyLbryPage(currentPage),
},
{
label: 'Invite',
// icon: TBD when we add icons back to the side nav
path: '/invite',
active: currentPage === 'invite',
},
{
label: 'Publish',
icon: icons.UPLOAD,
@ -283,15 +253,13 @@ export const selectNavLinks = createSelector(
}
);
export const selectModal = createSelector(
selectState,
state => {
if (!state.modal) {
return null;
}
export const selectModal = createSelector(selectState, state => {
if (!state.modal) {
return null;
}
return {
id: state.modal,
modalProps: state.modalProps,
}
})
};
});

View file

@ -3,11 +3,11 @@
position: relative;
svg {
stroke-width: 2;
stroke-width: 1.5;
width: 1.2rem;
height: 1.2rem;
position: relative;
top: 0.2rem;
top: 0.1rem;
}
.btn__label {

View file

@ -44,6 +44,8 @@
// A C T I O N S
.card__actions {
font-size: 1.15rem;
> *:not(:last-child) {
margin-right: var(--spacing-vertical-large);
}
@ -193,6 +195,7 @@
display: flex;
align-items: center;
.card__title + .btn,
.btn:not(:first-of-type) {
margin-left: var(--spacing-vertical-medium);
}

View file

@ -19,7 +19,6 @@
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: cover;
max-width: calc(var(--file-max-width) * (16 / 9));
margin: auto;
&:not(.card__media--nsfw) {
@ -38,14 +37,7 @@
.content__embedded {
@include thumbnail;
background-color: #000;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: var(--spacing-vertical-large);
position: relative;
width: 100%;
max-height: var(--file-max-width);
video {
width: 100%;
@ -70,7 +62,8 @@
width: 100%;
}
.content__empty--nsfw {
.content__empty--nsfw,
.card__media--nsfw {
background-color: $lbry-grape-3;
}
@ -93,14 +86,10 @@
.content__view {
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: #000;
align-items: center;
display: flex;
justify-content: center;
position: absolute;
iframe {
width: 100%;

View file

@ -127,7 +127,7 @@
}
.btn__label {
line-height: 1.8;
line-height: 1.4;
padding-left: 0.5rem;
}

View file

@ -14,22 +14,28 @@
}
.main--file-page {
max-width: 1787px;
display: grid;
grid-template-areas:
'content content'
'info related'
'content related'
'info related';
grid-gap: var(--spacing-vertical-large);
grid-template-rows: auto 1fr;
grid-template-columns: 1fr auto;
@media (min-width: 1470px) {
grid-template-areas:
'content related'
'info related'
'info related';
grid-template-rows: 0fr 1fr;
}
// TODO: Get responsive grid working, to many issues with different thumbnails messing stuff up on small screens with the file taking up the full width
// I will conquer this one day
// grid-template-areas:
// 'content content'
// 'info related';
//
// @media (min-width: 1470px) {
//
// }
.grid-area--content {
grid-area: content;
max-width: var(--file-max-width);
}
.grid-area--info {
grid-area: info;

View file

@ -213,6 +213,40 @@
@include placeholder;
}
// M E D I A
// S U B T E X T
//
// Wrapper around low level media information (date, channel)
//
.media__subtext {
color: rgba($lbry-black, 0.8);
html[data-theme='dark'] & {
color: rgba($lbry-white, 0.7);
}
}
// M E D I A
// S U B T I T L E
.media__subtitle {
font-size: 1rem;
position: relative;
}
.media__subtitle--large {
display: block;
> button {
display: block;
}
}
.media__subtitle__channel {
font-size: 1.25rem;
font-weight: 600;
}
// M E D I A
// I N F O
@ -255,7 +289,7 @@
// M E S S A G E
.media__message {
font-size: 0.9rem;
font-size: 1.1rem;
padding: var(--spacing-vertical-medium);
white-space: normal;
}
@ -264,6 +298,31 @@
background-color: $lbry-yellow-3;
margin: var(--spacing-vertical-medium) var(--spacing-vertical-large);
.btn--link {
// The normal colors we use for .btn--link are too light for the warning background
// This just darkens them a bit and adds an border-bottom so they are easier to see.
$altered-color: mix($lbry-teal-5, $lbry-black, 80%);
$altered-hover-color: mix($lbry-teal-5, $lbry-black, 60%);
&:not(.btn--disabled) {
color: $altered-color;
border-bottom: 1px solid $altered-color;
&:hover {
color: $altered-hover-color;
}
html[data-theme='dark'] & {
color: $altered-color;
border-bottom: 1px solid $altered-color;
&:hover {
color: $altered-hover-color;
}
}
}
}
html[data-theme='dark'] & {
background-color: $lbry-yellow-4;
color: $lbry-black;
@ -317,27 +376,6 @@
@include placeholder;
}
// M E D I A
// S U B T I T L E
.media__subtitle {
font-size: 1rem;
position: relative;
}
.media__subtitle--large {
display: block;
> button {
display: block;
}
}
.media__subtitle__channel {
font-size: 1.25rem;
font-weight: 600;
}
// M E D I A
// T E X T
@ -464,11 +502,10 @@
.media-group--list-recommended {
border-left: 1px solid $lbry-gray-1;
float: right;
min-height: 50vh;
overflow: hidden;
padding-left: var(--spacing-vertical-large);
width: 30rem;
padding-left: var(--spacing-vertical-large);
html[data-theme='dark'] & {
border-color: rgba($lbry-gray-5, 0.2);
@ -517,6 +554,10 @@
.channel-info__actions {
color: $lbry-white;
}
.media__subtext {
color: mix($lbry-cyan-5, $lbry-white, 20%);
}
}
&:not(:first-of-type):not(:last-of-type) {
@ -527,25 +568,16 @@
}
}
&:not(:first-of-type) {
.media-group__header-title {
background-image: linear-gradient(to right, $lbry-black 80%, transparent 100%);
}
.channel-info__actions {
color: initial;
}
}
.media-group__header {
flex-direction: row;
padding-left: var(--spacing-vertical-large);
}
.media-group__header-title {
color: transparent;
// color: transparent; // TODO: Add this back for lbryweb, it helps with long titles but was causing issues. A better solution is needed. - Sean
// !exist unprefixed, needs SVG for LBRY web
-webkit-background-clip: text;
background-image: linear-gradient(to right, $lbry-white 80%, transparent 100%);
html[data-theme='dark'] & {
background-image: linear-gradient(
@ -642,6 +674,16 @@
padding-top: var(--spacing-vertical-medium);
}
// Handles the margin on the right side of the last item
// Overflow: hidden makes doesn't care if the margin is off the screen, just the content
// Using padding shrinks the last item
&::after {
content: '';
display: inline-block;
width: var(--spacing-vertical-large);
height: 1px;
}
.media-card {
cursor: pointer;
display: inline-block;
@ -655,12 +697,6 @@
margin-left: var(--spacing-vertical-large);
}
&:last-of-type {
// We can't use margin or padding because overlfow: hidden ignores those
// border-right ensures the last item in the scrollable list has some space to the right
border-right: var(--spacing-vertical-large) solid transparent;
}
// May be needed for mobile design
// @media (max-width: 600px) {
// width: calc((100% / 3) - 3rem);

View file

@ -25,9 +25,6 @@
background-color: $lbry-white;
border: 1px solid $lbry-gray-3;
border-radius: 4px;
display: flex;
flex-direction: column;
justify-content: center;
line-height: 1.55;
max-width: var(--modal-width);
overflow: auto;

View file

@ -10,15 +10,14 @@
width: calc(100% + 4rem);
}
.yrbl-wrap {
align-items: center;
display: flex;
justify-content: center;
vertical-align: middle;
margin-bottom: var(--spacing-vertical-large);
img {
height: 500px;
height: 300px;
}
}

View file

@ -147,15 +147,20 @@ input {
}
}
.card {
.help {
margin-bottom: 0;
margin-top: var(--spacing-vertical-large);
}
}
.help {
background-color: rgba($lbry-blue-1, 0.1);
border-radius: 0.5rem;
color: $lbry-gray-5;
display: block;
margin-bottom: 1rem;
padding: 1rem;
position: relative;
top: 1rem;
margin-bottom: var(--spacing-vertical-large);
html[data-theme='dark'] & {
color: inherit;

View file

@ -18,7 +18,10 @@ $large-breakpoint: 1921px;
--spacing-vertical-medium: calc(2rem / 2);
--spacing-vertical-large: 2rem;
--file-max-width: 700px;
--file-max-width: 1400px;
// --file-max-height: calc(var(--file-max-height) * 9 / 16);
--file-max-height: 788px;
--video-aspect-ratio: 56.25%; // 9 x 16
// Text