style pass
This commit is contained in:
parent
72443d4d2e
commit
6718f153a9
6 changed files with 68 additions and 107 deletions
|
@ -26,10 +26,10 @@ if (isProduction) {
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
type Analytics = {
|
type Analytics = {
|
||||||
error: string => Promise<any>,
|
error: (string) => Promise<any>,
|
||||||
sentryError: ({} | string, {}) => Promise<any>,
|
sentryError: ({} | string, {}) => Promise<any>,
|
||||||
pageView: (string, ?string) => void,
|
pageView: (string, ?string) => void,
|
||||||
setUser: Object => void,
|
setUser: (Object) => void,
|
||||||
toggleInternal: (boolean, ?boolean) => void,
|
toggleInternal: (boolean, ?boolean) => void,
|
||||||
apiLogView: (string, string, string, ?number, ?() => void) => Promise<any>,
|
apiLogView: (string, string, string, ?number, ?() => void) => Promise<any>,
|
||||||
apiLogPublish: (ChannelClaim | StreamClaim) => void,
|
apiLogPublish: (ChannelClaim | StreamClaim) => void,
|
||||||
|
@ -55,9 +55,9 @@ type Analytics = {
|
||||||
emailVerifiedEvent: () => void,
|
emailVerifiedEvent: () => void,
|
||||||
rewardEligibleEvent: () => void,
|
rewardEligibleEvent: () => void,
|
||||||
startupEvent: () => void,
|
startupEvent: () => void,
|
||||||
purchaseEvent: number => void,
|
purchaseEvent: (number) => void,
|
||||||
readyEvent: number => void,
|
readyEvent: (number) => void,
|
||||||
openUrlEvent: string => void,
|
openUrlEvent: (string) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
type LogPublishParams = {
|
type LogPublishParams = {
|
||||||
|
@ -75,8 +75,8 @@ if (window.localStorage.getItem(SHARE_INTERNAL) === 'true') internalAnalyticsEna
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
const analytics: Analytics = {
|
const analytics: Analytics = {
|
||||||
error: message => {
|
error: (message) => {
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve) => {
|
||||||
if (internalAnalyticsEnabled && isProduction) {
|
if (internalAnalyticsEnabled && isProduction) {
|
||||||
return Lbryio.call('event', 'desktop_error', { error_message: message }).then(() => {
|
return Lbryio.call('event', 'desktop_error', { error_message: message }).then(() => {
|
||||||
resolve(true);
|
resolve(true);
|
||||||
|
@ -87,9 +87,9 @@ const analytics: Analytics = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
sentryError: (error, errorInfo) => {
|
sentryError: (error, errorInfo) => {
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve) => {
|
||||||
if (internalAnalyticsEnabled && isProduction) {
|
if (internalAnalyticsEnabled && isProduction) {
|
||||||
Sentry.withScope(scope => {
|
Sentry.withScope((scope) => {
|
||||||
scope.setExtras(errorInfo);
|
scope.setExtras(errorInfo);
|
||||||
const eventId = Sentry.captureException(error);
|
const eventId = Sentry.captureException(error);
|
||||||
resolve(eventId);
|
resolve(eventId);
|
||||||
|
@ -114,7 +114,7 @@ const analytics: Analytics = {
|
||||||
MatomoInstance.trackPageView(params);
|
MatomoInstance.trackPageView(params);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setUser: userId => {
|
setUser: (userId) => {
|
||||||
if (internalAnalyticsEnabled && userId) {
|
if (internalAnalyticsEnabled && userId) {
|
||||||
window._paq.push(['setUserId', String(userId)]);
|
window._paq.push(['setUserId', String(userId)]);
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
|
@ -188,19 +188,12 @@ const analytics: Analytics = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
apiSyncTags: params => {
|
apiSyncTags: (params) => {
|
||||||
if (internalAnalyticsEnabled && isProduction) {
|
if (internalAnalyticsEnabled && isProduction) {
|
||||||
Lbryio.call('content_tags', 'sync', params);
|
Lbryio.call('content_tags', 'sync', params);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
apiSearchFeedback: (query, vote) => {
|
|
||||||
if (isProduction) {
|
|
||||||
// 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 });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
videoFetchDuration: (source, duration) => {
|
videoFetchDuration: (source, duration) => {
|
||||||
sendPromMetric('time_to_fetch', duration);
|
sendPromMetric('time_to_fetch', duration);
|
||||||
sendMatomoEvent('Media', 'TimeToFetch', source, duration);
|
sendMatomoEvent('Media', 'TimeToFetch', source, duration);
|
||||||
|
@ -238,10 +231,10 @@ const analytics: Analytics = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
playerLoadedEvent: embedded => {
|
playerLoadedEvent: (embedded) => {
|
||||||
sendMatomoEvent('Player', 'Loaded', embedded ? 'embedded' : 'onsite');
|
sendMatomoEvent('Player', 'Loaded', embedded ? 'embedded' : 'onsite');
|
||||||
},
|
},
|
||||||
playerStartedEvent: embedded => {
|
playerStartedEvent: (embedded) => {
|
||||||
sendMatomoEvent('Player', 'Started', embedded ? 'embedded' : 'onsite');
|
sendMatomoEvent('Player', 'Started', embedded ? 'embedded' : 'onsite');
|
||||||
},
|
},
|
||||||
tagFollowEvent: (tag, following) => {
|
tagFollowEvent: (tag, following) => {
|
||||||
|
@ -316,7 +309,7 @@ analytics.pageView(
|
||||||
|
|
||||||
// Listen for url changes and report
|
// Listen for url changes and report
|
||||||
// This will include search queries
|
// This will include search queries
|
||||||
history.listen(location => {
|
history.listen((location) => {
|
||||||
const { pathname, search } = location;
|
const { pathname, search } = location;
|
||||||
|
|
||||||
const page = `${pathname}${search}`;
|
const page = `${pathname}${search}`;
|
||||||
|
|
|
@ -117,21 +117,23 @@ export default function ClaimList(props: Props) {
|
||||||
<div className={classnames('claim-list__header', { 'section__title--small': type === 'small' })}>
|
<div className={classnames('claim-list__header', { 'section__title--small': type === 'small' })}>
|
||||||
{header}
|
{header}
|
||||||
{loading && <Spinner type="small" />}
|
{loading && <Spinner type="small" />}
|
||||||
<div className="claim-list__alt-controls">
|
{(headerAltControls || defaultSort) && (
|
||||||
{headerAltControls}
|
<div className="claim-list__alt-controls">
|
||||||
{defaultSort && (
|
{headerAltControls}
|
||||||
<FormField
|
{defaultSort && (
|
||||||
className="claim-list__dropdown"
|
<FormField
|
||||||
type="select"
|
className="claim-list__dropdown"
|
||||||
name="file_sort"
|
type="select"
|
||||||
value={currentSort}
|
name="file_sort"
|
||||||
onChange={handleSortChange}
|
value={currentSort}
|
||||||
>
|
onChange={handleSortChange}
|
||||||
<option value={SORT_NEW}>{__('Newest First')}</option>
|
>
|
||||||
<option value={SORT_OLD}>{__('Oldest First')}</option>
|
<option value={SORT_NEW}>{__('Newest First')}</option>
|
||||||
</FormField>
|
<option value={SORT_OLD}>{__('Oldest First')}</option>
|
||||||
)}
|
</FormField>
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
|
@ -127,9 +127,9 @@ const SearchOptions = (props: Props) => {
|
||||||
onClick={() => updateSearchOptions(SEARCH_OPTIONS.CLAIM_TYPE, SEARCH_OPTIONS.INCLUDE_FILES_AND_CHANNELS)}
|
onClick={() => updateSearchOptions(SEARCH_OPTIONS.CLAIM_TYPE, SEARCH_OPTIONS.INCLUDE_FILES_AND_CHANNELS)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="media-types">
|
{options[SEARCH_OPTIONS.CLAIM_TYPE] === SEARCH_OPTIONS.INCLUDE_FILES && (
|
||||||
{options[SEARCH_OPTIONS.CLAIM_TYPE] === SEARCH_OPTIONS.INCLUDE_FILES &&
|
<div className="media-types">
|
||||||
Object.entries(TYPES_ADVANCED).map((t) => {
|
{Object.entries(TYPES_ADVANCED).map((t) => {
|
||||||
const option = t[0];
|
const option = t[0];
|
||||||
return (
|
return (
|
||||||
<FormField
|
<FormField
|
||||||
|
@ -144,7 +144,8 @@ const SearchOptions = (props: Props) => {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doToast } from 'lbry-redux';
|
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { doSearch } from 'redux/actions/search';
|
import { doSearch } from 'redux/actions/search';
|
||||||
import {
|
import {
|
||||||
|
@ -11,7 +10,6 @@ import {
|
||||||
} from 'redux/selectors/search';
|
} from 'redux/selectors/search';
|
||||||
import { selectShowMatureContent } from 'redux/selectors/settings';
|
import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import analytics from 'analytics';
|
|
||||||
import SearchPage from './view';
|
import SearchPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
|
@ -41,24 +39,6 @@ const select = (state, props) => {
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
search: (query, options) => dispatch(doSearch(query, options)),
|
search: (query, options) => dispatch(doSearch(query, options)),
|
||||||
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 withRouter(connect(select, perform)(SearchPage));
|
export default withRouter(connect(select, perform)(SearchPage));
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { SIMPLE_SITE, SHOW_ADS } from 'config';
|
import { SIMPLE_SITE, SHOW_ADS } from 'config';
|
||||||
import * as ICONS from 'constants/icons';
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Lbry, parseURI, isNameValid } from 'lbry-redux';
|
import { Lbry, parseURI, isNameValid } from 'lbry-redux';
|
||||||
import ClaimList from 'component/claimList';
|
import ClaimList from 'component/claimList';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import SearchOptions from 'component/searchOptions';
|
import SearchOptions from 'component/searchOptions';
|
||||||
import Button from 'component/button';
|
|
||||||
import Ads from 'web/component/ads';
|
import Ads from 'web/component/ads';
|
||||||
import SearchTopClaim from 'component/searchTopClaim';
|
import SearchTopClaim from 'component/searchTopClaim';
|
||||||
import { formatLbryUrlForWeb } from 'util/url';
|
import { formatLbryUrlForWeb } from 'util/url';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import ClaimPreview from 'component/claimPreview';
|
|
||||||
import { SEARCH_PAGE_SIZE } from 'constants/search';
|
import { SEARCH_PAGE_SIZE } from 'constants/search';
|
||||||
|
|
||||||
type AdditionalOptions = {
|
type AdditionalOptions = {
|
||||||
|
@ -26,8 +23,6 @@ type Props = {
|
||||||
isSearching: boolean,
|
isSearching: boolean,
|
||||||
location: UrlLocation,
|
location: UrlLocation,
|
||||||
uris: Array<string>,
|
uris: Array<string>,
|
||||||
onFeedbackNegative: (string) => void,
|
|
||||||
onFeedbackPositive: (string) => void,
|
|
||||||
showNsfw: boolean,
|
showNsfw: boolean,
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
hasReachedMaxResultsLength: boolean,
|
hasReachedMaxResultsLength: boolean,
|
||||||
|
@ -37,8 +32,6 @@ export default function SearchPage(props: Props) {
|
||||||
const {
|
const {
|
||||||
search,
|
search,
|
||||||
uris,
|
uris,
|
||||||
onFeedbackPositive,
|
|
||||||
onFeedbackNegative,
|
|
||||||
location,
|
location,
|
||||||
isSearching,
|
isSearching,
|
||||||
showNsfw,
|
showNsfw,
|
||||||
|
@ -128,25 +121,7 @@ export default function SearchPage(props: Props) {
|
||||||
injectedItem={
|
injectedItem={
|
||||||
SHOW_ADS && IS_WEB ? (SIMPLE_SITE ? false : !isAuthenticated && <Ads small type={'video'} />) : false
|
SHOW_ADS && IS_WEB ? (SIMPLE_SITE ? false : !isAuthenticated && <Ads small type={'video'} />) : false
|
||||||
}
|
}
|
||||||
headerAltControls={
|
|
||||||
<>
|
|
||||||
<span>{__('Find what you were looking for?')}</span>
|
|
||||||
<Button
|
|
||||||
button="alt"
|
|
||||||
description={__('Yes')}
|
|
||||||
onClick={() => onFeedbackPositive(urlQuery)}
|
|
||||||
icon={ICONS.YES}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
button="alt"
|
|
||||||
description={__('No')}
|
|
||||||
onClick={() => onFeedbackNegative(urlQuery)}
|
|
||||||
icon={ICONS.NO}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
{isSearching && new Array(5).fill(1).map((x, i) => <ClaimPreview key={i} placeholder="loading" />)}
|
|
||||||
|
|
||||||
<div className="main--empty help">{__('These search results are provided by LBRY, Inc.')}</div>
|
<div className="main--empty help">{__('These search results are provided by LBRY, Inc.')}</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -9,21 +9,7 @@
|
||||||
|
|
||||||
.search__options {
|
.search__options {
|
||||||
margin-top: var(--spacing-s);
|
margin-top: var(--spacing-s);
|
||||||
padding-left: var(--spacing-m);
|
display: none;
|
||||||
|
|
||||||
transition: all 0.3s ease-out;
|
|
||||||
|
|
||||||
// These will be expanded by 'search__options--expanded'.
|
|
||||||
max-height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
|
|
||||||
.search__legend {
|
|
||||||
font-weight: var(--font-weight-bold);
|
|
||||||
font-size: var(--font-small);
|
|
||||||
margin-bottom: var(--spacing-s);
|
|
||||||
padding: var(--spacing-xxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset:not(:first-child) {
|
fieldset:not(:first-child) {
|
||||||
margin-top: var(--spacing-m);
|
margin-top: var(--spacing-m);
|
||||||
|
@ -34,9 +20,16 @@
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
td:nth-of-type(1) {
|
td:nth-of-type(1) {
|
||||||
width: 20%;
|
width: 25%;
|
||||||
vertical-align: top;
|
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.claim-type-filter {
|
.claim-type-filter {
|
||||||
|
@ -77,12 +70,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-types {
|
.media-types {
|
||||||
margin-top: var(--spacing-s);
|
margin-top: var(--spacing-m);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: $breakpoint-small) {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio,
|
.radio,
|
||||||
|
@ -91,15 +90,26 @@
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
&:not(:first-of-type) {
|
||||||
margin-left: var(--spacing-m);
|
margin-top: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: $breakpoint-small) {
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
margin-left: var(--spacing-m);
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search__options--expanded {
|
.search__options--expanded {
|
||||||
max-height: 400px; // how to not hardcode this :(
|
display: block;
|
||||||
opacity: 1;
|
}
|
||||||
visibility: visible;
|
|
||||||
|
.search__legend {
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
font-size: var(--font-small);
|
||||||
|
padding: var(--spacing-xxs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search__top-link {
|
.search__top-link {
|
||||||
|
|
Loading…
Reference in a new issue