Merge 'relase' into 'master' (#2289)
* v0.29.0-rc.1 * bump daemon * v0.29.0-rc.2 * bump lbry/components * v0.29.0-rc.3 * fix: remember if search options were open * fix: scrollable list on subscriptions * fix: icon alignment on file page * fix: button color in publish form * fix: select option color for windows/linux * fix: don't break app when navigating to abaondoned claims * fix: thumbnail size on related content * maint: rc4 with UI fixes * fix: ... buttons ... again * fix: file percentage on pending downloads Changed to DidMount (did update seemed to trigger the file list too many times) - this will show the percentage if it's not completed and currently downloading. Typical cases are if a person refreshed or navigated away/back. This way if a download is stuck, a user will see the percentage and can try to delete/redownload (we should add a start/stop feature later on). * fix: name input text wrapping * change: use select drop down for search results * add search analytics * v0.29.0-rc.5 * v0.29.0-rc.6 * fix: name input alignment * fix: metadata * bump sdk * v0.29.0-rc.7 * fix: line-height * v0.29.0-rc.8 * v0.29.0
This commit is contained in:
parent
f0389221f2
commit
7577586ea9
23 changed files with 272 additions and 140 deletions
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "LBRY",
|
"name": "LBRY",
|
||||||
"version": "0.29.0-rc.0",
|
"version": "0.29.0",
|
||||||
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"lbry"
|
"lbry"
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
"postinstall": "electron-builder install-app-deps && node build/downloadDaemon.js"
|
"postinstall": "electron-builder install-app-deps && node build/downloadDaemon.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lbry/components": "^2.2.1",
|
"@lbry/components": "^2.2.4",
|
||||||
"@types/three": "^0.93.1",
|
"@types/three": "^0.93.1",
|
||||||
"bluebird": "^3.5.1",
|
"bluebird": "^3.5.1",
|
||||||
"breakdance": "^3.0.1",
|
"breakdance": "^3.0.1",
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
"yarn": "^1.3"
|
"yarn": "^1.3"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.32.0",
|
"lbrynetDaemonVersion": "0.32.2",
|
||||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
||||||
"lbrynetDaemonDir": "static/daemon",
|
"lbrynetDaemonDir": "static/daemon",
|
||||||
"lbrynetDaemonFileName": "lbrynet"
|
"lbrynetDaemonFileName": "lbrynet"
|
||||||
|
|
|
@ -80,6 +80,10 @@ const analytics: Analytics = {
|
||||||
Lbryio.call('event', 'publish');
|
Lbryio.call('event', 'publish');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
apiSearchFeedback: (query, vote) => {
|
||||||
|
// We don't need to worry about analytics enabled here because users manually click on the button to provide feedback
|
||||||
|
Lbryio.call('feedback', 'search', { query, vote });
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default analytics;
|
export default analytics;
|
||||||
|
|
|
@ -57,23 +57,23 @@ class CategoryList extends PureComponent<Props, State> {
|
||||||
fetchChannel(categoryLink);
|
fetchChannel(categoryLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const scrollWrapper = this.scrollWrapper.current;
|
||||||
|
if (scrollWrapper) {
|
||||||
|
scrollWrapper.addEventListener('scroll', throttle(this.handleArrowButtonsOnScroll, 500));
|
||||||
|
|
||||||
if (!urisInList) {
|
if (!urisInList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lazyLoad) {
|
if (lazyLoad) {
|
||||||
const scrollWrapper = this.scrollWrapper.current;
|
if (window.innerHeight > scrollWrapper.offsetTop) {
|
||||||
if (scrollWrapper) {
|
|
||||||
scrollWrapper.addEventListener('scroll', throttle(this.handleArrowButtonsOnScroll, 500));
|
|
||||||
|
|
||||||
if (urisInList && window.innerHeight > scrollWrapper.offsetTop) {
|
|
||||||
resolveUris(urisInList);
|
resolveUris(urisInList);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
resolveUris(urisInList);
|
resolveUris(urisInList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props) {
|
componentDidUpdate(prevProps: Props) {
|
||||||
const { scrollY: previousScrollY } = prevProps.currentPageAttributes;
|
const { scrollY: previousScrollY } = prevProps.currentPageAttributes;
|
||||||
|
|
|
@ -168,11 +168,9 @@ export class FormField extends React.PureComponent<Props> {
|
||||||
input = (
|
input = (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<fieldset-section>
|
<fieldset-section>
|
||||||
{(label || errorMessage) && (
|
|
||||||
<label htmlFor={name}>
|
<label htmlFor={name}>
|
||||||
{errorMessage ? <span className="error-text">{errorMessage}</span> : label}
|
{errorMessage ? <span className="error-text">{errorMessage}</span> : label}
|
||||||
</label>
|
</label>
|
||||||
)}
|
|
||||||
{prefix && (
|
{prefix && (
|
||||||
<label className="form-field--inline-prefix" htmlFor={name}>
|
<label className="form-field--inline-prefix" htmlFor={name}>
|
||||||
{prefix}
|
{prefix}
|
||||||
|
|
|
@ -7,7 +7,7 @@ type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
subtitle: string | React.Node,
|
subtitle: string | React.Node,
|
||||||
type: string,
|
type: string,
|
||||||
className: ?string,
|
className?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const yrblTypes = {
|
const yrblTypes = {
|
||||||
|
@ -30,7 +30,7 @@ export default class extends React.PureComponent<Props> {
|
||||||
<img alt="Friendly gerbil" className="yrbl" src={Native.imagePath(image)} />
|
<img alt="Friendly gerbil" className="yrbl" src={Native.imagePath(image)} />
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<h2 className="card__title">{title}</h2>
|
<h2 className="card__title">{title}</h2>
|
||||||
<p className="card__subtitle">{subtitle}</p>
|
<div className="card__subtitle">{subtitle}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,6 +16,7 @@ type Props = {
|
||||||
outpoint: number,
|
outpoint: number,
|
||||||
download_path: string,
|
download_path: string,
|
||||||
completed: boolean,
|
completed: boolean,
|
||||||
|
status: string,
|
||||||
},
|
},
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
costInfo: ?{},
|
costInfo: ?{},
|
||||||
|
@ -26,15 +27,16 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileDownloadLink extends React.PureComponent<Props> {
|
class FileDownloadLink extends React.PureComponent<Props> {
|
||||||
componentWillUpdate() {
|
componentDidMount() {
|
||||||
const { downloading, fileInfo, uri, restartDownload } = this.props;
|
const { fileInfo, uri, restartDownload } = this.props;
|
||||||
if (
|
if (
|
||||||
!downloading &&
|
|
||||||
fileInfo &&
|
fileInfo &&
|
||||||
!fileInfo.completed &&
|
!fileInfo.completed &&
|
||||||
|
fileInfo.status === 'running' &&
|
||||||
fileInfo.written_bytes !== false &&
|
fileInfo.written_bytes !== false &&
|
||||||
fileInfo.written_bytes < fileInfo.total_bytes
|
fileInfo.written_bytes < fileInfo.total_bytes
|
||||||
) {
|
) {
|
||||||
|
// This calls file list to show the percentage
|
||||||
restartDownload(uri, fileInfo.outpoint);
|
restartDownload(uri, fileInfo.outpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,68 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.playMedia();
|
||||||
|
|
||||||
|
// Temp hack to force the video to play if the metadataloaded event was never fired
|
||||||
|
// Will be removed with the new video player
|
||||||
|
setTimeout(() => {
|
||||||
|
const { hasMetadata } = this.state;
|
||||||
|
if (!hasMetadata) {
|
||||||
|
this.refreshMetadata();
|
||||||
|
this.playMedia();
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(next) {
|
||||||
|
const el = this.media.children[0];
|
||||||
|
if (!this.props.paused && next.paused && !el.paused) el.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
const { contentType, downloadCompleted } = this.props;
|
||||||
|
const { startedPlaying, fileSource } = this.state;
|
||||||
|
|
||||||
|
if (this.playableType() && !startedPlaying && downloadCompleted) {
|
||||||
|
const container = this.media.children[0];
|
||||||
|
|
||||||
|
if (MediaPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
|
||||||
|
this.renderAudio(this.media, true);
|
||||||
|
} else {
|
||||||
|
player.append(
|
||||||
|
this.file(),
|
||||||
|
container,
|
||||||
|
{ autoplay: true, controls: true },
|
||||||
|
renderMediaCallback.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (this.fileType() && !fileSource && downloadCompleted) {
|
||||||
|
this.renderFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
document.removeEventListener('keydown', this.togglePlayListener);
|
||||||
|
const mediaElement = this.media.children[0];
|
||||||
|
if (mediaElement) {
|
||||||
|
mediaElement.removeEventListener('click', this.togglePlayListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleFullScreen(event) {
|
||||||
|
const mediaElement = this.media.children[0];
|
||||||
|
if (mediaElement) {
|
||||||
|
if (document.webkitIsFullScreen) {
|
||||||
|
document.webkitExitFullscreen();
|
||||||
|
} else {
|
||||||
|
mediaElement.webkitRequestFullScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playMedia() {
|
||||||
|
const { hasMetadata } = this.state;
|
||||||
|
|
||||||
const container = this.media;
|
const container = this.media;
|
||||||
const {
|
const {
|
||||||
downloadCompleted,
|
downloadCompleted,
|
||||||
|
@ -51,15 +113,6 @@ class MediaPlayer extends React.PureComponent {
|
||||||
savePosition,
|
savePosition,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const loadedMetadata = () => {
|
|
||||||
this.setState({ hasMetadata: true, startedPlaying: true });
|
|
||||||
|
|
||||||
if (onStartCb) {
|
|
||||||
onStartCb();
|
|
||||||
}
|
|
||||||
this.media.children[0].play();
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderMediaCallback = error => {
|
const renderMediaCallback = error => {
|
||||||
if (error) this.setState({ unplayable: true });
|
if (error) this.setState({ unplayable: true });
|
||||||
};
|
};
|
||||||
|
@ -91,16 +144,15 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('keydown', this.togglePlayListener);
|
document.addEventListener('keydown', this.togglePlayListener);
|
||||||
const mediaElement = this.media.children[0];
|
const mediaElement = container.children[0];
|
||||||
if (mediaElement) {
|
if (mediaElement) {
|
||||||
if (position) {
|
if (position) {
|
||||||
mediaElement.currentTime = position;
|
mediaElement.currentTime = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mediaElement.addEventListener('loadedmetadata', () => this.refreshMetadata());
|
||||||
mediaElement.addEventListener('timeupdate', () => savePosition(mediaElement.currentTime));
|
mediaElement.addEventListener('timeupdate', () => savePosition(mediaElement.currentTime));
|
||||||
mediaElement.addEventListener('click', this.togglePlayListener);
|
mediaElement.addEventListener('click', this.togglePlayListener);
|
||||||
mediaElement.addEventListener('loadedmetadata', loadedMetadata.bind(this), {
|
|
||||||
once: true,
|
|
||||||
});
|
|
||||||
mediaElement.addEventListener('ended', () => {
|
mediaElement.addEventListener('ended', () => {
|
||||||
if (onFinishCb) {
|
if (onFinishCb) {
|
||||||
onFinishCb();
|
onFinishCb();
|
||||||
|
@ -116,48 +168,18 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(next) {
|
refreshMetadata() {
|
||||||
const el = this.media.children[0];
|
const { onStartCb } = this.props;
|
||||||
if (!this.props.paused && next.paused && !el.paused) el.pause();
|
this.setState({ hasMetadata: true, startedPlaying: true });
|
||||||
|
|
||||||
|
if (onStartCb) {
|
||||||
|
onStartCb();
|
||||||
|
}
|
||||||
|
this.media.children[0].play();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
setReady() {
|
||||||
const { contentType, downloadCompleted } = this.props;
|
this.setState({ ready: true });
|
||||||
const { startedPlaying, fileSource } = this.state;
|
|
||||||
|
|
||||||
if (this.playableType() && !startedPlaying && downloadCompleted) {
|
|
||||||
const container = this.media.children[0];
|
|
||||||
|
|
||||||
if (MediaPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
|
|
||||||
this.renderAudio(this.media, true);
|
|
||||||
} else {
|
|
||||||
player.render(this.file(), container, {
|
|
||||||
autoplay: true,
|
|
||||||
controls: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (this.fileType() && !fileSource && downloadCompleted) {
|
|
||||||
this.renderFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
document.removeEventListener('keydown', this.togglePlayListener);
|
|
||||||
const mediaElement = this.media.children[0];
|
|
||||||
if (mediaElement) {
|
|
||||||
mediaElement.removeEventListener('click', this.togglePlayListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleFullScreen(event) {
|
|
||||||
const mediaElement = this.media.children[0];
|
|
||||||
if (mediaElement) {
|
|
||||||
if (document.webkitIsFullScreen) {
|
|
||||||
document.webkitExitFullscreen();
|
|
||||||
} else {
|
|
||||||
mediaElement.webkitRequestFullScreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
togglePlay(event) {
|
togglePlay(event) {
|
||||||
|
|
|
@ -1,13 +1,42 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectSearchOptions, doUpdateSearchOptions } from 'lbry-redux';
|
import {
|
||||||
|
selectSearchOptions,
|
||||||
|
doUpdateSearchOptions,
|
||||||
|
makeSelectQueryWithOptions,
|
||||||
|
doToast,
|
||||||
|
} from 'lbry-redux';
|
||||||
|
import { doToggleSearchExpanded } from 'redux/actions/app';
|
||||||
|
import { selectSearchOptionsExpanded } from 'redux/selectors/app';
|
||||||
|
import analytics from 'analytics';
|
||||||
import SearchOptions from './view';
|
import SearchOptions from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
options: selectSearchOptions(state),
|
options: selectSearchOptions(state),
|
||||||
|
expanded: selectSearchOptionsExpanded(state),
|
||||||
|
query: makeSelectQueryWithOptions()(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
setSearchOption: (option, value) => dispatch(doUpdateSearchOptions({ [option]: value })),
|
setSearchOption: (option, value) => dispatch(doUpdateSearchOptions({ [option]: value })),
|
||||||
|
toggleSearchExpanded: () => dispatch(doToggleSearchExpanded()),
|
||||||
|
onFeedbackPositive: query => {
|
||||||
|
analytics.apiSearchFeedback(query, 1);
|
||||||
|
dispatch(
|
||||||
|
doToast({
|
||||||
|
message: __('Thanks for the feedback! You help make the app better for everyone.'),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onFeedbackNegative: query => {
|
||||||
|
analytics.apiSearchFeedback(query, 0);
|
||||||
|
dispatch(
|
||||||
|
doToast({
|
||||||
|
message: __(
|
||||||
|
'Thanks for the feedback. Mark has been notified and is currently walking over to his computer to work on this.'
|
||||||
|
),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import { SEARCH_OPTIONS } from 'lbry-redux';
|
import { SEARCH_OPTIONS } from 'lbry-redux';
|
||||||
import { Form, FormField } from 'component/common/form';
|
import { Form, FormField } from 'component/common/form';
|
||||||
import posed from 'react-pose';
|
import posed from 'react-pose';
|
||||||
|
@ -14,28 +14,50 @@ const ExpandableOptions = posed.div({
|
||||||
type Props = {
|
type Props = {
|
||||||
setSearchOption: (string, boolean | string | number) => void,
|
setSearchOption: (string, boolean | string | number) => void,
|
||||||
options: {},
|
options: {},
|
||||||
|
expanded: boolean,
|
||||||
|
toggleSearchExpanded: () => void,
|
||||||
|
query: string,
|
||||||
|
onFeedbackPositive: string => void,
|
||||||
|
onFeedbackNegative: string => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SearchOptions = (props: Props) => {
|
const SearchOptions = (props: Props) => {
|
||||||
const { options, setSearchOption } = props;
|
const {
|
||||||
const [expanded, setExpanded] = useState(false);
|
options,
|
||||||
|
setSearchOption,
|
||||||
|
expanded,
|
||||||
|
toggleSearchExpanded,
|
||||||
|
query,
|
||||||
|
onFeedbackPositive,
|
||||||
|
onFeedbackNegative,
|
||||||
|
} = props;
|
||||||
const resultCount = options[SEARCH_OPTIONS.RESULT_COUNT];
|
const resultCount = options[SEARCH_OPTIONS.RESULT_COUNT];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card card--section search__options-wrapper">
|
<div className="card card--section search__options-wrapper">
|
||||||
<div className="card--space-between">
|
<div className="card--space-between">
|
||||||
<Button
|
<Button
|
||||||
label={__('SEARCH OPTIONS')}
|
button="alt"
|
||||||
icon={ICONS.OPTIONS}
|
label={__('ADVANCED SEARCH')}
|
||||||
onClick={() => setExpanded(!expanded)}
|
iconRight={expanded ? ICONS.UP : ICONS.DOWN}
|
||||||
|
onClick={toggleSearchExpanded}
|
||||||
/>
|
/>
|
||||||
{/*
|
|
||||||
Will be added back when api is ready
|
|
||||||
<div className="media__action-group">
|
<div className="media__action-group">
|
||||||
<span>{__('Find what you were looking for?')}</span>
|
<span>{__('Find what you were looking for?')}</span>
|
||||||
<Button description={__('Yes')} icon={ICONS.YES} />
|
<Button
|
||||||
<Button description={__('No')} icon={ICONS.NO} />
|
button="alt"
|
||||||
</div> */}
|
description={__('Yes')}
|
||||||
|
onClick={() => onFeedbackPositive(query)}
|
||||||
|
icon={ICONS.YES}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
button="alt"
|
||||||
|
description={__('No')}
|
||||||
|
onClick={() => onFeedbackNegative(query)}
|
||||||
|
icon={ICONS.NO}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ExpandableOptions pose={expanded ? 'show' : 'hide'}>
|
<ExpandableOptions pose={expanded ? 'show' : 'hide'}>
|
||||||
{expanded && (
|
{expanded && (
|
||||||
|
@ -77,7 +99,7 @@ const SearchOptions = (props: Props) => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
option: SEARCH_OPTIONS.MEDIA_AUDIO,
|
option: SEARCH_OPTIONS.MEDIA_AUDIO,
|
||||||
label: __('Sounds'),
|
label: __('Audio'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
option: SEARCH_OPTIONS.MEDIA_IMAGE,
|
option: SEARCH_OPTIONS.MEDIA_IMAGE,
|
||||||
|
@ -108,13 +130,18 @@ const SearchOptions = (props: Props) => {
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend className="search__legend--3">{__('Other Options')}</legend>
|
<legend className="search__legend--3">{__('Other Options')}</legend>
|
||||||
<FormField
|
<FormField
|
||||||
type="number"
|
type="select"
|
||||||
name="result-count"
|
name="result-count"
|
||||||
value={resultCount}
|
value={resultCount}
|
||||||
onChange={e => setSearchOption(SEARCH_OPTIONS.RESULT_COUNT, e.target.value)}
|
onChange={e => setSearchOption(SEARCH_OPTIONS.RESULT_COUNT, e.target.value)}
|
||||||
blockWrap={false}
|
blockWrap={false}
|
||||||
label={__('Returned Results')}
|
label={__('Returned Results')}
|
||||||
/>
|
>
|
||||||
|
<option value={10}>10</option>
|
||||||
|
<option value={30}>30</option>
|
||||||
|
<option value={50}>50</option>
|
||||||
|
<option value={100}>100</option>
|
||||||
|
</FormField>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -16,6 +16,7 @@ export const VOLUME_CHANGED = 'VOLUME_CHANGED';
|
||||||
export const ADD_COMMENT = 'ADD_COMMENT';
|
export const ADD_COMMENT = 'ADD_COMMENT';
|
||||||
export const SHOW_MODAL = 'SHOW_MODAL';
|
export const SHOW_MODAL = 'SHOW_MODAL';
|
||||||
export const HIDE_MODAL = 'HIDE_MODAL';
|
export const HIDE_MODAL = 'HIDE_MODAL';
|
||||||
|
export const TOGGLE_SEARCH_EXPANDED = 'TOGGLE_SEARCH_EXPANDED';
|
||||||
export const ENNNHHHAAANNNCEEE = 'ENNNHHHAAANNNCEEE';
|
export const ENNNHHHAAANNNCEEE = 'ENNNHHHAAANNNCEEE';
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
|
|
|
@ -44,3 +44,5 @@ export const FILE = 'File';
|
||||||
export const OPTIONS = 'Sliders';
|
export const OPTIONS = 'Sliders';
|
||||||
export const YES = 'ThumbsUp';
|
export const YES = 'ThumbsUp';
|
||||||
export const NO = 'ThumbsDown';
|
export const NO = 'ThumbsDown';
|
||||||
|
export const UP = 'ChevronUp';
|
||||||
|
export const DOWN = 'ChevronDown';
|
||||||
|
|
|
@ -129,7 +129,7 @@ class RewardsPage extends PureComponent<Props> {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section className="card card--section">
|
<section className="card card--section">
|
||||||
<h2 className="card__title">{__('No Rewards Available')}</h2>
|
<h2 className="card__title">{__('No Rewards Available')}</h2>
|
||||||
<p>
|
<p className="card__content">
|
||||||
{claimed && claimed.length
|
{claimed && claimed.length
|
||||||
? __(
|
? __(
|
||||||
"You have claimed all available rewards! We're regularly adding more so be sure to check back later."
|
"You have claimed all available rewards! We're regularly adding more so be sure to check back later."
|
||||||
|
|
|
@ -31,7 +31,7 @@ class ShowPage extends React.PureComponent<Props> {
|
||||||
if (
|
if (
|
||||||
!isResolvingUri &&
|
!isResolvingUri &&
|
||||||
uri &&
|
uri &&
|
||||||
(claim === undefined || (claim.name[0] === '@' && totalPages === undefined))
|
(claim === undefined || (claim && claim.name[0] === '@' && totalPages === undefined))
|
||||||
) {
|
) {
|
||||||
resolveUri(uri);
|
resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,3 +380,9 @@ export function doToggleEnhancedLayout() {
|
||||||
type: ACTIONS.ENNNHHHAAANNNCEEE,
|
type: ACTIONS.ENNNHHHAAANNNCEEE,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doToggleSearchExpanded() {
|
||||||
|
return {
|
||||||
|
type: ACTIONS.TOGGLE_SEARCH_EXPANDED,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ export type AppState = {
|
||||||
isUpgradeSkipped: ?boolean,
|
isUpgradeSkipped: ?boolean,
|
||||||
hasClickedComment: boolean,
|
hasClickedComment: boolean,
|
||||||
enhancedLayout: boolean,
|
enhancedLayout: boolean,
|
||||||
|
searchOptionsExpanded: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultState: AppState = {
|
const defaultState: AppState = {
|
||||||
|
@ -59,6 +60,7 @@ const defaultState: AppState = {
|
||||||
isUpgradeAvailable: undefined,
|
isUpgradeAvailable: undefined,
|
||||||
isUpgradeSkipped: undefined,
|
isUpgradeSkipped: undefined,
|
||||||
enhancedLayout: false,
|
enhancedLayout: false,
|
||||||
|
searchOptionsExpanded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[ACTIONS.DAEMON_READY] = state =>
|
reducers[ACTIONS.DAEMON_READY] = state =>
|
||||||
|
@ -220,6 +222,11 @@ reducers[ACTIONS.ENNNHHHAAANNNCEEE] = state =>
|
||||||
enhancedLayout: !state.enhancedLayout,
|
enhancedLayout: !state.enhancedLayout,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reducers[ACTIONS.TOGGLE_SEARCH_EXPANDED] = state =>
|
||||||
|
Object.assign({}, state, {
|
||||||
|
searchOptionsExpanded: !state.searchOptionsExpanded,
|
||||||
|
});
|
||||||
|
|
||||||
export default function reducer(state: AppState = defaultState, action: any) {
|
export default function reducer(state: AppState = defaultState, action: any) {
|
||||||
const handler = reducers[action.type];
|
const handler = reducers[action.type];
|
||||||
if (handler) return handler(state, action);
|
if (handler) return handler(state, action);
|
||||||
|
|
|
@ -248,3 +248,8 @@ export const selectModal = createSelector(selectState, state => {
|
||||||
});
|
});
|
||||||
|
|
||||||
export const selectEnhancedLayout = createSelector(selectState, state => state.enhancedLayout);
|
export const selectEnhancedLayout = createSelector(selectState, state => state.enhancedLayout);
|
||||||
|
|
||||||
|
export const selectSearchOptionsExpanded = createSelector(
|
||||||
|
selectState,
|
||||||
|
state => state.searchOptionsExpanded
|
||||||
|
);
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
stroke-opacity: 1;
|
stroke-opacity: 1;
|
||||||
width: 1.4rem;
|
width: 1.4rem;
|
||||||
height: 1.4rem;
|
height: 1.4rem;
|
||||||
top: 0;
|
top: 0.1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svg + .button__label {
|
svg + .button__label,
|
||||||
|
.button__label + svg {
|
||||||
margin-left: var(--spacing-vertical-small);
|
margin-left: var(--spacing-vertical-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,26 +53,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--inverse {
|
// This is a hack and the extra styles are just so this is more specific than the @lbry/components styling
|
||||||
|
// Will make a PR there, but just doing it now for the release - Sean
|
||||||
|
[type='button'].button--inverse {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
html[data-mode='dark'] & {
|
||||||
|
&:not(:hover) {
|
||||||
border-color: rgba($lbry-white, 0.1);
|
border-color: rgba($lbry-white, 0.1);
|
||||||
background-color: rgba($lbry-black, 0.3);
|
background-color: rgba($lbry-black, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba($lbry-white, 0.1);
|
||||||
|
background-color: rgba($lbry-white, 0.1);
|
||||||
|
color: $lbry-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-mode='light'] & {
|
||||||
&:not(:hover) {
|
&:not(:hover) {
|
||||||
background-color: $lbry-white;
|
background-color: $lbry-white;
|
||||||
|
color: $lbry-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $lbry-gray-1;
|
background-color: $lbry-gray-1;
|
||||||
color: $lbry-black;
|
color: $lbry-black;
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
background-color: rgba($lbry-white, 0.1);
|
|
||||||
color: $lbry-white;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +91,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--link:not(:disabled) {
|
.button--link:not(:disabled) {
|
||||||
html[data-mode='dark'] & {
|
html[data-mode='dark'] & {
|
||||||
&:not(:hover) {
|
&:not(:hover) {
|
||||||
|
|
|
@ -192,6 +192,10 @@
|
||||||
.card__title {
|
.card__title {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__title--flex {
|
.card__title--flex {
|
||||||
|
|
|
@ -9,7 +9,7 @@ input[type='number'] {
|
||||||
input[type='text'],
|
input[type='text'],
|
||||||
input[type='number'],
|
input[type='number'],
|
||||||
select {
|
select {
|
||||||
padding-bottom: 0.2em;
|
padding-bottom: 0.1em;
|
||||||
|
|
||||||
[data-mode='dark'] & {
|
[data-mode='dark'] & {
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
|
@ -99,6 +99,10 @@ fieldset-group {
|
||||||
&.fieldset-group--disabled-prefix {
|
&.fieldset-group--disabled-prefix {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|
||||||
|
label {
|
||||||
|
min-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
fieldset-section:first-child .form-field__prefix,
|
fieldset-section:first-child .form-field__prefix,
|
||||||
fieldset-section:last-child input {
|
fieldset-section:last-child input {
|
||||||
border-color: $lbry-black;
|
border-color: $lbry-black;
|
||||||
|
@ -110,6 +114,7 @@ fieldset-group {
|
||||||
|
|
||||||
fieldset-section:first-child {
|
fieldset-section:first-child {
|
||||||
.form-field__prefix {
|
.form-field__prefix {
|
||||||
|
white-space: nowrap;
|
||||||
padding: 0.15em var(--spacing-s);
|
padding: 0.15em var(--spacing-s);
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
|
@ -142,16 +147,24 @@ fieldset-group {
|
||||||
|
|
||||||
// form buttons are black by default
|
// form buttons are black by default
|
||||||
form {
|
form {
|
||||||
// [data-mode='dark'] & {
|
[type='button'],
|
||||||
.button--primary:not(:hover) {
|
[type='submit'] {
|
||||||
|
&.button--primary {
|
||||||
|
&:not(:hover) {
|
||||||
background-color: $lbry-teal-5;
|
background-color: $lbry-teal-5;
|
||||||
border-color: $lbry-teal-5;
|
border-color: $lbry-teal-5;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $lbry-teal-3;
|
background-color: $lbry-teal-3;
|
||||||
border-color: $lbry-teal-3;
|
border-color: $lbry-teal-3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.button--inverse {
|
||||||
|
@extend .button--inverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset-section {
|
fieldset-section {
|
||||||
|
@ -175,6 +188,10 @@ fieldset-section {
|
||||||
|
|
||||||
[data-mode='dark'] & {
|
[data-mode='dark'] & {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
|
option {
|
||||||
|
background-color: $lbry-gray-5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,17 +232,6 @@ label + .react-toggle,
|
||||||
margin-left: var(--spacing-vertical-small);
|
margin-left: var(--spacing-vertical-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field--inline-prefix {
|
|
||||||
position: absolute;
|
|
||||||
top: 9.5em;
|
|
||||||
left: 2.75em;
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
& + input {
|
|
||||||
padding-left: 4em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-field__help {
|
.form-field__help {
|
||||||
@extend .help;
|
@extend .help;
|
||||||
margin-top: var(--spacing-vertical-medium);
|
margin-top: var(--spacing-vertical-medium);
|
||||||
|
|
|
@ -144,8 +144,8 @@
|
||||||
.media__actions {
|
.media__actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-top: var(--spacing-vertical-large);
|
margin-top: var(--spacing-vertical-small);
|
||||||
padding-bottom: var(--spacing-vertical-large);
|
margin-bottom: var(--spacing-vertical-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
.media__actions--between {
|
.media__actions--between {
|
||||||
|
@ -160,6 +160,8 @@
|
||||||
|
|
||||||
.media__action-group--large {
|
.media__action-group--large {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-top: var(--spacing-vertical-small);
|
||||||
|
margin-bottom: var(--spacing-vertical-small);
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
font-size: 1.15rem;
|
font-size: 1.15rem;
|
||||||
|
@ -168,6 +170,10 @@
|
||||||
margin-right: var(--spacing-vertical-large);
|
margin-right: var(--spacing-vertical-large);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: var(--spacing-vertical-large);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// M E D I A
|
// M E D I A
|
||||||
|
|
|
@ -89,6 +89,7 @@ code {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.busy-indicator__loader {
|
.busy-indicator__loader {
|
||||||
|
|
|
@ -99,7 +99,7 @@ const fileInfoFilter = createFilter('fileInfo', [
|
||||||
'fileListDownloadedSort',
|
'fileListDownloadedSort',
|
||||||
'fileListSubscriptionSort',
|
'fileListSubscriptionSort',
|
||||||
]);
|
]);
|
||||||
const appFilter = createFilter('app', ['hasClickedComment']);
|
const appFilter = createFilter('app', ['hasClickedComment', 'searchOptionsExpanded']);
|
||||||
// We only need to persist the receiveAddress for the wallet
|
// We only need to persist the receiveAddress for the wallet
|
||||||
const walletFilter = createFilter('wallet', ['receiveAddress']);
|
const walletFilter = createFilter('wallet', ['receiveAddress']);
|
||||||
const searchFilter = createFilter('search', ['options']);
|
const searchFilter = createFilter('search', ['options']);
|
||||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -111,10 +111,10 @@
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f"
|
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f"
|
||||||
|
|
||||||
"@lbry/components@^2.2.1":
|
"@lbry/components@^2.2.4":
|
||||||
version "2.2.1"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/@lbry/components/-/components-2.2.1.tgz#3fc67e807796e9dc8cd1d5cd86a719849c4710d5"
|
resolved "https://registry.yarnpkg.com/@lbry/components/-/components-2.2.4.tgz#ee2c91788de447ed33185daa7a747ba684e5143f"
|
||||||
integrity sha512-k8bdSjr0Hq3+ZlvAKRuPea4LTEvXx4zF7+IOb1RmFWfMIk8jBNZi02LmvLoj4VuCa3mKoVfECeaYyXg6vwmY3w==
|
integrity sha512-SF0g4JROwYsvJc9fEFmAYAj9cITJ9L2MTkWCs9vfPhDS4iXE6ZW5VNtcxI5JOVAvsZMRHq5oX9EtjxHs1pIIdg==
|
||||||
|
|
||||||
"@mapbox/hast-util-table-cell-style@^0.1.3":
|
"@mapbox/hast-util-table-cell-style@^0.1.3":
|
||||||
version "0.1.3"
|
version "0.1.3"
|
||||||
|
@ -5668,19 +5668,20 @@ lbry-redux@lbryio/lbry-redux#3ab065b11a52d3e2e6a50a25459f9ff0aac03b13:
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#84b7d396934d57a37802aadbef71db91230a9404:
|
lbry-redux@lbryio/lbry-redux#76d8bbef9640bf8ea5c4f45550e55b77d3944ee3:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/84b7d396934d57a37802aadbef71db91230a9404"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/76d8bbef9640bf8ea5c4f45550e55b77d3944ee3"
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
lbryinc@lbryio/lbryinc#60d80401891743f991c040bafa8e51da7e939777:
|
lbryinc@lbryio/lbryinc#2334ad53e82c22d6291899785d5292347008f2a9:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/60d80401891743f991c040bafa8e51da7e939777"
|
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/2334ad53e82c22d6291899785d5292347008f2a9"
|
||||||
dependencies:
|
dependencies:
|
||||||
lbry-redux lbryio/lbry-redux#84b7d396934d57a37802aadbef71db91230a9404
|
bluebird "^3.5.1"
|
||||||
|
lbry-redux lbryio/lbry-redux#76d8bbef9640bf8ea5c4f45550e55b77d3944ee3
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
||||||
lcid@^1.0.0:
|
lcid@^1.0.0:
|
||||||
|
|
Loading…
Reference in a new issue