0.36.0 sdk changes
This commit is contained in:
parent
c6a33c7a90
commit
2d95c5a337
71 changed files with 525 additions and 843 deletions
|
@ -1,10 +1,10 @@
|
|||
[ignore]
|
||||
node_modules/
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
./flow-typed
|
||||
node_modules/lbry-redux/flow-typed/
|
||||
|
||||
[lints]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
|
||||
export type UrlLocation = {
|
||||
declare type UrlLocation = {
|
||||
search: string,
|
||||
hash: string,
|
||||
host: string,
|
59
flow-typed/npm/redux_v3.x.x.js
vendored
59
flow-typed/npm/redux_v3.x.x.js
vendored
|
@ -1,59 +0,0 @@
|
|||
// flow-typed signature: cca4916b0213065533df8335c3285a4a
|
||||
// flow-typed version: cab04034e7/redux_v3.x.x/flow_>=v0.55.x
|
||||
|
||||
declare module 'redux' {
|
||||
|
||||
/*
|
||||
|
||||
S = State
|
||||
A = Action
|
||||
D = Dispatch
|
||||
|
||||
*/
|
||||
|
||||
declare export type DispatchAPI<A> = (action: A) => A;
|
||||
declare export type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
|
||||
|
||||
declare export type MiddlewareAPI<S, A, D = Dispatch<A>> = {
|
||||
dispatch: D;
|
||||
getState(): S;
|
||||
};
|
||||
|
||||
declare export type Store<S, A, D = Dispatch<A>> = {
|
||||
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
|
||||
dispatch: D;
|
||||
getState(): S;
|
||||
subscribe(listener: () => void): () => void;
|
||||
replaceReducer(nextReducer: Reducer<S, A>): void
|
||||
};
|
||||
|
||||
declare export type Reducer<S, A> = (state: S | void, action: A) => S;
|
||||
|
||||
declare export type CombinedReducer<S, A> = (state: $Shape<S> & {} | void, action: A) => S;
|
||||
|
||||
declare export type Middleware<S, A, D = Dispatch<A>> =
|
||||
(api: MiddlewareAPI<S, A, D>) =>
|
||||
(next: D) => D;
|
||||
|
||||
declare export type StoreCreator<S, A, D = Dispatch<A>> = {
|
||||
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
};
|
||||
|
||||
declare export type StoreEnhancer<S, A, D = Dispatch<A>> = (next: StoreCreator<S, A, D>) => StoreCreator<S, A, D>;
|
||||
|
||||
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, preloadedState?: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
|
||||
declare export function applyMiddleware<S, A, D>(...middlewares: Array<Middleware<S, A, D>>): StoreEnhancer<S, A, D>;
|
||||
|
||||
declare export type ActionCreator<A, B> = (...args: Array<B>) => A;
|
||||
declare export type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
|
||||
|
||||
declare export function bindActionCreators<A, C: ActionCreator<A, any>, D: DispatchAPI<A>>(actionCreator: C, dispatch: D): C;
|
||||
declare export function bindActionCreators<A, K, C: ActionCreators<K, A>, D: DispatchAPI<A>>(actionCreators: C, dispatch: D): C;
|
||||
|
||||
declare export function combineReducers<O: Object, A>(reducers: O): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
|
||||
|
||||
declare export var compose: $Compose;
|
||||
}
|
52
flow-typed/publish.js
vendored
Normal file
52
flow-typed/publish.js
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
// @flow
|
||||
|
||||
declare type UpdatePublishFormData = {
|
||||
filePath?: string,
|
||||
contentIsFree?: boolean,
|
||||
price?: {
|
||||
amount: number,
|
||||
currency: string,
|
||||
},
|
||||
title?: string,
|
||||
thumbnail_url?: string,
|
||||
uploadThumbnailStatus?: string,
|
||||
thumbnailPath?: string,
|
||||
description?: string,
|
||||
language?: string,
|
||||
channel?: string,
|
||||
channelId?: string,
|
||||
name?: string,
|
||||
nameError?: string,
|
||||
bid?: number,
|
||||
bidError?: string,
|
||||
otherLicenseDescription?: string,
|
||||
licenseUrl?: string,
|
||||
licenseType?: string,
|
||||
uri?: string,
|
||||
};
|
||||
|
||||
declare type PublishParams = {
|
||||
name: ?string,
|
||||
bid: ?number,
|
||||
filePath?: string,
|
||||
description: ?string,
|
||||
language: string,
|
||||
publishingLicense?: string,
|
||||
publishingLicenseUrl?: string,
|
||||
thumbnail: ?string,
|
||||
channel: string,
|
||||
channelId?: string,
|
||||
title: string,
|
||||
contentIsFree: boolean,
|
||||
uri?: string,
|
||||
license: ?string,
|
||||
licenseUrl: ?string,
|
||||
fee?: {
|
||||
currency: string,
|
||||
amount: number,
|
||||
},
|
||||
|
||||
// This is bad.
|
||||
// Will be removed for tags soon
|
||||
nsfw: boolean,
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
|
||||
export type Reward = {
|
||||
declare type Reward = {
|
||||
created_at: string,
|
||||
id: number,
|
||||
reward_amount: number,
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Dispatch as ReduxDispatch } from 'types/redux';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import {
|
||||
DOWNLOADED,
|
||||
|
@ -12,7 +11,7 @@ import {
|
|||
SUGGESTED_FEATURED,
|
||||
} from 'constants/subscriptions';
|
||||
|
||||
export type Subscription = {
|
||||
declare type Subscription = {
|
||||
channelName: string, // @CryptoCandor,
|
||||
uri: string, // lbry://@CryptoCandor#9152f3b054f692076a6882d1b58a30e8781cc8e6
|
||||
latest?: string, // substratum#b0ab143243020e7831fd070d9f871e1fda948620
|
||||
|
@ -21,26 +20,26 @@ export type Subscription = {
|
|||
// Tracking for new content
|
||||
// i.e. If a subscription has a DOWNLOADING type, we will trigger an OS notification
|
||||
// to tell users there is new content from their subscriptions
|
||||
export type SubscriptionNotificationType = DOWNLOADED | DOWNLOADING | NOTIFY_ONLY;
|
||||
declare type SubscriptionNotificationType = DOWNLOADED | DOWNLOADING | NOTIFY_ONLY;
|
||||
|
||||
export type UnreadSubscription = {
|
||||
declare type UnreadSubscription = {
|
||||
type: SubscriptionNotificationType,
|
||||
uris: Array<string>,
|
||||
};
|
||||
|
||||
export type UnreadSubscriptions = {
|
||||
declare type UnreadSubscriptions = {
|
||||
[string]: UnreadSubscription,
|
||||
};
|
||||
|
||||
export type ViewMode = VIEW_LATEST_FIRST | VIEW_ALL;
|
||||
declare type ViewMode = VIEW_LATEST_FIRST | VIEW_ALL;
|
||||
|
||||
export type SuggestedType = SUGGESTED_TOP_BID | SUGGESTED_TOP_SUBSCRIBED | SUGGESTED_FEATURED;
|
||||
declare type SuggestedType = SUGGESTED_TOP_BID | SUGGESTED_TOP_SUBSCRIBED | SUGGESTED_FEATURED;
|
||||
|
||||
export type SuggestedSubscriptions = {
|
||||
declare type SuggestedSubscriptions = {
|
||||
[SuggestedType]: string,
|
||||
};
|
||||
|
||||
export type SubscriptionState = {
|
||||
declare type SubscriptionState = {
|
||||
subscriptions: Array<Subscription>,
|
||||
unread: UnreadSubscriptions,
|
||||
loading: boolean,
|
||||
|
@ -54,17 +53,17 @@ export type SubscriptionState = {
|
|||
//
|
||||
// Action types
|
||||
//
|
||||
export type DoChannelSubscribe = {
|
||||
declare type DoChannelSubscribe = {
|
||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||
data: Subscription,
|
||||
};
|
||||
|
||||
export type DoChannelUnsubscribe = {
|
||||
declare type DoChannelUnsubscribe = {
|
||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||
data: Subscription,
|
||||
};
|
||||
|
||||
export type DoUpdateSubscriptionUnreads = {
|
||||
declare type DoUpdateSubscriptionUnreads = {
|
||||
type: ACTIONS.UPDATE_SUBSCRIPTION_UNREADS,
|
||||
data: {
|
||||
channel: string,
|
||||
|
@ -73,7 +72,7 @@ export type DoUpdateSubscriptionUnreads = {
|
|||
},
|
||||
};
|
||||
|
||||
export type DoRemoveSubscriptionUnreads = {
|
||||
declare type DoRemoveSubscriptionUnreads = {
|
||||
type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS,
|
||||
data: {
|
||||
channel: string,
|
||||
|
@ -81,7 +80,7 @@ export type DoRemoveSubscriptionUnreads = {
|
|||
},
|
||||
};
|
||||
|
||||
export type SetSubscriptionLatest = {
|
||||
declare type SetSubscriptionLatest = {
|
||||
type: ACTIONS.SET_SUBSCRIPTION_LATEST,
|
||||
data: {
|
||||
subscription: Subscription,
|
||||
|
@ -89,25 +88,25 @@ export type SetSubscriptionLatest = {
|
|||
},
|
||||
};
|
||||
|
||||
export type CheckSubscriptionStarted = {
|
||||
declare type CheckSubscriptionStarted = {
|
||||
type: ACTIONS.CHECK_SUBSCRIPTION_STARTED,
|
||||
};
|
||||
|
||||
export type CheckSubscriptionCompleted = {
|
||||
declare type CheckSubscriptionCompleted = {
|
||||
type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED,
|
||||
};
|
||||
|
||||
export type FetchedSubscriptionsSucess = {
|
||||
declare type FetchedSubscriptionsSucess = {
|
||||
type: ACTIONS.FETCH_SUBSCRIPTIONS_SUCCESS,
|
||||
data: Array<Subscription>,
|
||||
};
|
||||
|
||||
export type SetViewMode = {
|
||||
declare type SetViewMode = {
|
||||
type: ACTIONS.SET_VIEW_MODE,
|
||||
data: ViewMode,
|
||||
};
|
||||
|
||||
export type GetSuggestedSubscriptionsSuccess = {
|
||||
declare type GetSuggestedSubscriptionsSuccess = {
|
||||
type: ACTIONS.GET_SUGGESTED_SUBSCRIPTIONS_START,
|
||||
data: SuggestedSubscriptions,
|
||||
};
|
|
@ -93,7 +93,6 @@
|
|||
"electron-webpack": "^2.6.2",
|
||||
"electron-window-state": "^4.1.1",
|
||||
"eslint": "^5.15.2",
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-config-standard-jsx": "^6.0.2",
|
||||
|
@ -106,7 +105,7 @@
|
|||
"eslint-plugin-promise": "^4.0.1",
|
||||
"eslint-plugin-react": "^7.7.0",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"flow-bin": "^0.94.0",
|
||||
"flow-bin": "^0.97.0",
|
||||
"flow-typed": "^2.3.0",
|
||||
"formik": "^0.10.4",
|
||||
"hast-util-sanitize": "^1.1.2",
|
||||
|
@ -115,8 +114,8 @@
|
|||
"jsmediatags": "^3.8.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#d4c7dea65f7179974e9b96c863022fe7b049ff7d",
|
||||
"lbryinc": "lbryio/lbryinc#4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02",
|
||||
"lbry-redux": "lbryio/lbry-redux#cc42856676541120b088e4228c04246ba8ff3274",
|
||||
"lbryinc": "lbryio/lbryinc#9665f2d1c818f1a86b2e5daab642f6879746f25f",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
"lodash-es": "^4.17.11",
|
||||
|
@ -186,7 +185,7 @@
|
|||
"yarn": "^1.3"
|
||||
},
|
||||
"lbrySettings": {
|
||||
"lbrynetDaemonVersion": "0.34.0",
|
||||
"lbrynetDaemonVersion": "0.36.0",
|
||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
||||
"lbrynetDaemonDir": "static/daemon",
|
||||
"lbrynetDaemonFileName": "lbrynet"
|
||||
|
|
|
@ -113,7 +113,12 @@ class Button extends React.PureComponent<Props> {
|
|||
exact
|
||||
to={path}
|
||||
title={title}
|
||||
onClick={e => e.stopPropagation()}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
if (onClick) {
|
||||
onClick();
|
||||
}
|
||||
}}
|
||||
className={combinedClassName}
|
||||
activeClassName={activeClass}
|
||||
>
|
||||
|
|
|
@ -4,7 +4,6 @@ import CardMedia from 'component/cardMedia';
|
|||
import TruncatedText from 'component/common/truncated-text';
|
||||
import classnames from 'classnames';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
import type { Claim } from 'types/claim';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { formatLbryUriForWeb } from 'util/uri';
|
||||
|
||||
|
@ -13,7 +12,7 @@ type Props = {
|
|||
isResolvingUri: boolean,
|
||||
totalItems: number,
|
||||
size: string,
|
||||
claim: ?Claim,
|
||||
claim: ?ChannelClaim,
|
||||
resolveUri: string => void,
|
||||
history: { push: string => void },
|
||||
};
|
||||
|
@ -44,7 +43,7 @@ class ChannelTile extends React.PureComponent<Props> {
|
|||
let subscriptionUri;
|
||||
if (claim) {
|
||||
channelName = claim.name;
|
||||
subscriptionUri = `lbry://${claim.permanent_url}`;
|
||||
subscriptionUri = claim.permanent_url;
|
||||
}
|
||||
|
||||
const onClick = () => history.push(formatLbryUriForWeb(uri));
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import type { Price } from 'page/settings';
|
||||
import { FormField } from './form-field';
|
||||
|
||||
type FormPrice = {
|
||||
amount: ?number,
|
||||
currency: string,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
price: Price,
|
||||
onChange: Price => void,
|
||||
price: FormPrice,
|
||||
onChange: FormPrice => void,
|
||||
placeholder: number,
|
||||
min: number,
|
||||
disabled: boolean,
|
||||
|
@ -23,7 +27,7 @@ export class FormFieldPrice extends React.PureComponent<Props> {
|
|||
|
||||
handleAmountChange(event: SyntheticInputEvent<*>) {
|
||||
const { price, onChange } = this.props;
|
||||
const amount = event.target.value ? parseFloat(event.target.value) : '';
|
||||
const amount = event.target.value ? parseFloat(event.target.value) : undefined;
|
||||
onChange({
|
||||
currency: price.currency,
|
||||
amount,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
import type { ElementRef } from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
import MarkdownPreview from 'component/common/markdown-preview';
|
||||
|
@ -6,24 +7,24 @@ import 'easymde/dist/easymde.min.css';
|
|||
import Toggle from 'react-toggle';
|
||||
import { openEditorMenu, stopContextMenu } from 'util/context-menu';
|
||||
|
||||
const SimpleMDE = React.lazy(() => import(
|
||||
/* webpackChunkName: "SimpleMDE" */
|
||||
'react-simplemde-editor'
|
||||
));
|
||||
const SimpleMDE = React.lazy(() =>
|
||||
import(/* webpackChunkName: "SimpleMDE" */
|
||||
'react-simplemde-editor')
|
||||
);
|
||||
|
||||
type Props = {
|
||||
name: string,
|
||||
label?: string,
|
||||
render?: () => React.Node,
|
||||
render?: () => React$Node,
|
||||
prefix?: string,
|
||||
postfix?: string,
|
||||
error?: string | boolean,
|
||||
helper?: string | React.Node,
|
||||
helper?: string | React$Node,
|
||||
type?: string,
|
||||
onChange?: any => any,
|
||||
defaultValue?: string | number,
|
||||
placeholder?: string | number,
|
||||
children?: React.Node,
|
||||
children?: React$Node,
|
||||
stretch?: boolean,
|
||||
affixClass?: string, // class applied to prefix/postfix label
|
||||
firstInList?: boolean, // at the top of a list, no padding top
|
||||
|
@ -32,7 +33,7 @@ type Props = {
|
|||
inputProps?: {
|
||||
disabled?: boolean,
|
||||
},
|
||||
inputButton?: React.Node,
|
||||
inputButton?: React$Node,
|
||||
blockWrap: boolean,
|
||||
};
|
||||
|
||||
|
@ -42,7 +43,7 @@ export class FormField extends React.PureComponent<Props> {
|
|||
blockWrap: true,
|
||||
};
|
||||
|
||||
input: { current: React.ElementRef<any> };
|
||||
input: { current: ElementRef<any> };
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
@ -136,7 +137,7 @@ export class FormField extends React.PureComponent<Props> {
|
|||
<div className="form-field--SimpleMDE" onContextMenu={stopContextMenu}>
|
||||
<fieldset-section>
|
||||
<label htmlFor={name}>{label}</label>
|
||||
<Suspense fallback={<div></div>}>
|
||||
<Suspense fallback={<div />}>
|
||||
<SimpleMDE
|
||||
{...inputProps}
|
||||
id={name}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Node } from 'react';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
|
||||
|
@ -9,7 +8,7 @@ type IconProps = {
|
|||
};
|
||||
|
||||
// Returns a react component
|
||||
const buildIcon = (iconStrokes: Node, options?: {} = {}) => (props: IconProps) => {
|
||||
const buildIcon = (iconStrokes: React$Node, options?: {} = {}) => (props: IconProps) => {
|
||||
const { size = 24, color = 'currentColor', ...otherProps } = props;
|
||||
return (
|
||||
<svg
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import React, { PureComponent, Node } from 'react';
|
||||
import React, { PureComponent } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import Button from 'component/button';
|
||||
|
||||
|
@ -8,7 +8,7 @@ import Button from 'component/button';
|
|||
// add props for collapsed height
|
||||
|
||||
type Props = {
|
||||
children: Node | Array<Node>,
|
||||
children: React$Node | Array<React$Node>,
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
|
|
@ -7,6 +7,9 @@ import {
|
|||
makeSelectIsUriResolving,
|
||||
makeSelectClaimIsMine,
|
||||
makeSelectClaimIsPending,
|
||||
makeSelectThumbnailForUri,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectClaimIsNsfw,
|
||||
} from 'lbry-redux';
|
||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||
import { makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||
|
@ -27,6 +30,9 @@ const select = (state, props) => ({
|
|||
position: makeSelectContentPositionForUri(props.uri)(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||
isNew: makeSelectIsNew(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim, Metadata } from 'types/claim';
|
||||
import * as icons from 'constants/icons';
|
||||
import * as React from 'react';
|
||||
import { normalizeURI, convertToShareLink } from 'lbry-redux';
|
||||
|
@ -13,12 +12,13 @@ import { openCopyLinkMenu } from 'util/context-menu';
|
|||
import DateTime from 'component/dateTime';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { formatLbryUriForWeb } from 'util/uri';
|
||||
import get from 'lodash.get';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claim: ?Claim,
|
||||
claim: ?StreamClaim,
|
||||
fileInfo: ?{},
|
||||
metadata: ?Metadata,
|
||||
metadata: ?StreamMetadata,
|
||||
rewardedContentClaimIds: Array<string>,
|
||||
obscureNsfw: boolean,
|
||||
claimIsMine: boolean,
|
||||
|
@ -30,6 +30,9 @@ type Props = {
|
|||
placeholder: boolean,
|
||||
preventResolve: boolean,
|
||||
history: { push: string => void },
|
||||
thumbnail: string,
|
||||
title: string,
|
||||
nsfw: boolean,
|
||||
};
|
||||
|
||||
class FileCard extends React.PureComponent<Props> {
|
||||
|
@ -72,6 +75,9 @@ class FileCard extends React.PureComponent<Props> {
|
|||
isResolvingUri,
|
||||
placeholder,
|
||||
history,
|
||||
thumbnail,
|
||||
title,
|
||||
nsfw,
|
||||
} = this.props;
|
||||
|
||||
const abandoned = !isResolvingUri && !claim && !pending && !placeholder;
|
||||
|
@ -92,14 +98,13 @@ class FileCard extends React.PureComponent<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
const shouldHide = !claimIsMine && !pending && obscureNsfw && metadata && metadata.nsfw;
|
||||
// fix to use tags - one of many nsfw tags...
|
||||
const shouldHide = !claimIsMine && !pending && obscureNsfw && nsfw;
|
||||
if (shouldHide) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri;
|
||||
const title = metadata && metadata.title ? metadata.title : uri;
|
||||
const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null;
|
||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||
const height = claim && claim.height;
|
||||
const handleContextMenu = event => {
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim, Metadata } from 'types/claim';
|
||||
import type { FileInfo } from 'types/file_info';
|
||||
import type { Node } from 'react';
|
||||
import React, { Fragment, PureComponent } from 'react';
|
||||
import { Lbryio } from 'lbryinc';
|
||||
import MarkdownPreview from 'component/common/markdown-preview';
|
||||
|
@ -10,13 +7,13 @@ import Expandable from 'component/expandable';
|
|||
import path from 'path';
|
||||
|
||||
type Props = {
|
||||
claim: Claim,
|
||||
fileInfo: FileInfo,
|
||||
metadata: Metadata,
|
||||
claim: StreamClaim,
|
||||
fileInfo: FileListItem,
|
||||
metadata: StreamMetadata,
|
||||
openFolder: string => void,
|
||||
contentType: string,
|
||||
clickCommentButton: () => void,
|
||||
showSnackBar: Node => void,
|
||||
showSnackBar: React$Node => void,
|
||||
hasClickedComment: boolean,
|
||||
user: ?any,
|
||||
};
|
||||
|
@ -59,7 +56,7 @@ class FileDetails extends PureComponent<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
const { description, language, license } = metadata;
|
||||
const { description, languages, license } = metadata;
|
||||
|
||||
const mediaType = contentType || 'unknown';
|
||||
let downloadPath =
|
||||
|
@ -90,9 +87,9 @@ class FileDetails extends PureComponent<Props> {
|
|||
{mediaType}
|
||||
</div>
|
||||
<div>
|
||||
{__('Language')}
|
||||
{__('Languages')}
|
||||
{': '}
|
||||
{language}
|
||||
{languages ? languages.join(' ') : null}
|
||||
</div>
|
||||
<div>
|
||||
{__('License')}
|
||||
|
@ -106,7 +103,11 @@ class FileDetails extends PureComponent<Props> {
|
|||
<Button
|
||||
constrict
|
||||
button="link"
|
||||
onClick={() => openFolder(downloadPath)}
|
||||
onClick={() => {
|
||||
if (downloadPath) {
|
||||
openFolder(downloadPath);
|
||||
}
|
||||
}}
|
||||
label={downloadNote || downloadPath}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
|
@ -7,7 +6,7 @@ import ToolTip from 'component/common/tooltip';
|
|||
import analytics from 'analytics';
|
||||
|
||||
type Props = {
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
uri: string,
|
||||
downloading: boolean,
|
||||
fileInfo: ?{
|
||||
|
|
|
@ -3,13 +3,12 @@ import * as React from 'react';
|
|||
import { buildURI, SORT_OPTIONS } from 'lbry-redux';
|
||||
import { FormField, Form } from 'component/common/form';
|
||||
import FileCard from 'component/fileCard';
|
||||
import type { FileInfo } from 'types/file_info';
|
||||
|
||||
type Props = {
|
||||
hideFilter: boolean,
|
||||
sortByHeight?: boolean,
|
||||
claimsById: Array<{}>,
|
||||
fileInfos: Array<FileInfo>,
|
||||
claimsById: Array<StreamClaim>,
|
||||
fileInfos: Array<FileListItem>,
|
||||
sortBy: string,
|
||||
page?: string,
|
||||
setFileListSort: (?string, string) => void,
|
||||
|
@ -29,47 +28,47 @@ class FileList extends React.PureComponent<Props> {
|
|||
[SORT_OPTIONS.DATE_NEW]: fileInfos =>
|
||||
this.props.sortByHeight
|
||||
? fileInfos.sort((fileInfo1, fileInfo2) => {
|
||||
if (fileInfo1.confirmations < 1) {
|
||||
return -1;
|
||||
} else if (fileInfo2.confirmations < 1) {
|
||||
return 1;
|
||||
}
|
||||
if (fileInfo1.confirmations < 1) {
|
||||
return -1;
|
||||
} else if (fileInfo2.confirmations < 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const height1 = this.props.claimsById[fileInfo1.claim_id]
|
||||
? this.props.claimsById[fileInfo1.claim_id].height
|
||||
: 0;
|
||||
const height2 = this.props.claimsById[fileInfo2.claim_id]
|
||||
? this.props.claimsById[fileInfo2.claim_id].height
|
||||
: 0;
|
||||
const height1 = this.props.claimsById[fileInfo1.claim_id]
|
||||
? this.props.claimsById[fileInfo1.claim_id].height
|
||||
: 0;
|
||||
const height2 = this.props.claimsById[fileInfo2.claim_id]
|
||||
? this.props.claimsById[fileInfo2.claim_id].height
|
||||
: 0;
|
||||
|
||||
if (height1 !== height2) {
|
||||
// flipped because heigher block height is newer
|
||||
return height2 - height1;
|
||||
}
|
||||
if (height1 !== height2) {
|
||||
// flipped because heigher block height is newer
|
||||
return height2 - height1;
|
||||
}
|
||||
|
||||
if (fileInfo1.absolute_channel_position && fileInfo2.absolute_channel_position) {
|
||||
return fileInfo1.absolute_channel_position - fileInfo2.absolute_channel_position;
|
||||
}
|
||||
if (fileInfo1.absolute_channel_position && fileInfo2.absolute_channel_position) {
|
||||
return fileInfo1.absolute_channel_position - fileInfo2.absolute_channel_position;
|
||||
}
|
||||
|
||||
return 0;
|
||||
})
|
||||
return 0;
|
||||
})
|
||||
: [...fileInfos].reverse(),
|
||||
[SORT_OPTIONS.DATE_OLD]: fileInfos =>
|
||||
this.props.sortByHeight
|
||||
? fileInfos.slice().sort((fileInfo1, fileInfo2) => {
|
||||
const height1 = this.props.claimsById[fileInfo1.claim_id]
|
||||
? this.props.claimsById[fileInfo1.claim_id].height
|
||||
: 999999;
|
||||
const height2 = this.props.claimsById[fileInfo2.claim_id]
|
||||
? this.props.claimsById[fileInfo2.claim_id].height
|
||||
: 999999;
|
||||
if (height1 < height2) {
|
||||
return -1;
|
||||
} else if (height1 > height2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
const height1 = this.props.claimsById[fileInfo1.claim_id]
|
||||
? this.props.claimsById[fileInfo1.claim_id].height
|
||||
: 999999;
|
||||
const height2 = this.props.claimsById[fileInfo2.claim_id]
|
||||
? this.props.claimsById[fileInfo2.claim_id].height
|
||||
: 999999;
|
||||
if (height1 < height2) {
|
||||
return -1;
|
||||
} else if (height1 > height2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
: fileInfos,
|
||||
[SORT_OPTIONS.TITLE]: fileInfos =>
|
||||
fileInfos.slice().sort((fileInfo1, fileInfo2) => {
|
||||
|
@ -80,7 +79,7 @@ class FileList extends React.PureComponent<Props> {
|
|||
return metadata.title || claimName;
|
||||
} else if (value) {
|
||||
// published claim
|
||||
const { title } = value.stream.metadata;
|
||||
const { title } = value.stream;
|
||||
return title || name;
|
||||
}
|
||||
// Invalid claim
|
||||
|
@ -109,14 +108,11 @@ class FileList extends React.PureComponent<Props> {
|
|||
};
|
||||
}
|
||||
|
||||
getChannelSignature = (fileInfo: FileInfo) => {
|
||||
getChannelSignature = (fileInfo: { pending: boolean } & FileListItem) => {
|
||||
if (fileInfo.pending) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (fileInfo.value) {
|
||||
return fileInfo.value.publisherSignature.certificateId;
|
||||
}
|
||||
return fileInfo.channel_claim_id;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,46 +1,45 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import { remote } from 'electron';
|
||||
import React, { Suspense } from 'react';
|
||||
import LoadingScreen from 'component/common/loading-screen';
|
||||
import VideoViewer from 'component/viewers/videoViewer';
|
||||
|
||||
const AudioViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "audioViewer" */
|
||||
'component/viewers/audioViewer'
|
||||
));
|
||||
const AudioViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "audioViewer" */
|
||||
'component/viewers/audioViewer')
|
||||
);
|
||||
|
||||
const DocumentViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "documentViewer" */
|
||||
'component/viewers/documentViewer'
|
||||
));
|
||||
const DocumentViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "documentViewer" */
|
||||
'component/viewers/documentViewer')
|
||||
);
|
||||
|
||||
const DocxViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "docxViewer" */
|
||||
'component/viewers/docxViewer'
|
||||
));
|
||||
const DocxViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "docxViewer" */
|
||||
'component/viewers/docxViewer')
|
||||
);
|
||||
|
||||
const HtmlViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "htmlViewer" */
|
||||
'component/viewers/htmlViewer'
|
||||
));
|
||||
const HtmlViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "htmlViewer" */
|
||||
'component/viewers/htmlViewer')
|
||||
);
|
||||
|
||||
const PdfViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "pdfViewer" */
|
||||
'component/viewers/pdfViewer'
|
||||
));
|
||||
const PdfViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "pdfViewer" */
|
||||
'component/viewers/pdfViewer')
|
||||
);
|
||||
|
||||
// @if TARGET='app'
|
||||
const ThreeViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "threeViewer" */
|
||||
'component/viewers/threeViewer'
|
||||
));
|
||||
const ThreeViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "threeViewer" */
|
||||
'component/viewers/threeViewer')
|
||||
);
|
||||
// @endif
|
||||
|
||||
type Props = {
|
||||
mediaType: string,
|
||||
poster?: string,
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
source: {
|
||||
stream: string => void,
|
||||
fileName: string,
|
||||
|
@ -119,8 +118,6 @@ class FileRender extends React.PureComponent<Props> {
|
|||
renderViewer() {
|
||||
const { source, mediaType, currentTheme, poster, claim } = this.props;
|
||||
|
||||
console.log('mediaType', mediaType);
|
||||
|
||||
// Extract relevant data to render file
|
||||
const { stream, fileType, contentType, downloadPath, fileName } = source;
|
||||
|
||||
|
@ -155,11 +152,7 @@ class FileRender extends React.PureComponent<Props> {
|
|||
/>
|
||||
),
|
||||
audio: (
|
||||
<AudioViewer
|
||||
claim={claim}
|
||||
source={{ downloadPath, fileName }}
|
||||
contentType={contentType}
|
||||
/>
|
||||
<AudioViewer claim={claim} source={{ downloadPath, fileName }} contentType={contentType} />
|
||||
),
|
||||
// Add routes to viewer...
|
||||
};
|
||||
|
@ -182,7 +175,7 @@ class FileRender extends React.PureComponent<Props> {
|
|||
|
||||
// @if TARGET='web'
|
||||
// temp workaround to disabled paid content on web
|
||||
if (claim && claim.value.stream.metadata.fee && claim.value.stream.metadata.fee.amount > 0) {
|
||||
if (claim && claim.value.fee && claim.value.fee.amount > 0) {
|
||||
const paidMessage = __(
|
||||
'Currently, only free content is available on lbry.tv. Try viewing it in the desktop app.'
|
||||
);
|
||||
|
@ -200,12 +193,9 @@ class FileRender extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
render() {
|
||||
console.log('RENDER')
|
||||
return (
|
||||
<div className="file-render">
|
||||
<React.Suspense fallback={<div></div>}>
|
||||
{this.renderViewer()}
|
||||
</React.Suspense>
|
||||
<React.Suspense fallback={<div />}>{this.renderViewer()}</React.Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ import {
|
|||
makeSelectFileInfoForUri,
|
||||
makeSelectIsUriResolving,
|
||||
makeSelectClaimIsMine,
|
||||
makeSelectThumbnailForUri,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectClaimIsNsfw,
|
||||
} from 'lbry-redux';
|
||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
|
@ -23,6 +26,9 @@ const select = (state, props) => ({
|
|||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||
isNew: makeSelectIsNew(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim, Metadata } from 'types/claim';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React, { Fragment } from 'react';
|
||||
import { normalizeURI, parseURI } from 'lbry-redux';
|
||||
|
@ -22,8 +21,8 @@ type Props = {
|
|||
uri: string,
|
||||
isResolvingUri: boolean,
|
||||
rewardedContentClaimIds: Array<string>,
|
||||
claim: ?Claim,
|
||||
metadata: ?Metadata,
|
||||
claim: ?StreamClaim,
|
||||
metadata: ?StreamMetadata,
|
||||
resolveUri: string => void,
|
||||
clearPublish: () => void,
|
||||
updatePublishForm: ({}) => void,
|
||||
|
@ -33,6 +32,9 @@ type Props = {
|
|||
isSubscribed: boolean,
|
||||
isNew: boolean,
|
||||
history: { push: string => void },
|
||||
thumbnail: ?string,
|
||||
title: ?string,
|
||||
nsfw: boolean,
|
||||
};
|
||||
|
||||
class FileTile extends React.PureComponent<Props> {
|
||||
|
@ -93,6 +95,9 @@ class FileTile extends React.PureComponent<Props> {
|
|||
displayHiddenMessage,
|
||||
size,
|
||||
history,
|
||||
thumbnail,
|
||||
title,
|
||||
nsfw,
|
||||
} = this.props;
|
||||
|
||||
if (!claim && isResolvingUri) {
|
||||
|
@ -112,7 +117,7 @@ class FileTile extends React.PureComponent<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
const shouldHide = !claimIsMine && obscureNsfw && metadata && metadata.nsfw;
|
||||
const shouldHide = !claimIsMine && obscureNsfw && nsfw;
|
||||
if (shouldHide) {
|
||||
return displayHiddenMessage ? (
|
||||
<span className="help">
|
||||
|
@ -126,9 +131,6 @@ class FileTile extends React.PureComponent<Props> {
|
|||
const uri = normalizeURI(this.props.uri);
|
||||
const isClaimed = !!claim;
|
||||
const description = isClaimed && metadata && metadata.description ? metadata.description : '';
|
||||
const title =
|
||||
isClaimed && metadata && metadata.title ? metadata.title : parseURI(uri).contentName;
|
||||
const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null;
|
||||
|
||||
let height;
|
||||
let name;
|
||||
|
@ -211,7 +213,7 @@ class FileTile extends React.PureComponent<Props> {
|
|||
|
||||
clearPublish(); // to remove any existing publish data
|
||||
updatePublishForm({ name: claimName }); // to populate the name
|
||||
history.push('/publish');
|
||||
history.push('/$/publish');
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
makeSelectDownloadingForUri,
|
||||
selectSearchBarFocused,
|
||||
makeSelectFirstRecommendedFileForUri,
|
||||
makeSelectClaimIsNsfw,
|
||||
makeSelectThumbnailForUri,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
|
||||
import { selectPlayingUri, makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||
|
@ -35,6 +37,8 @@ const select = (state, props) => ({
|
|||
searchBarFocused: selectSearchBarFocused(state),
|
||||
fileInfoErrors: selectFileInfoErrors(state),
|
||||
nextFileToPlay: makeSelectFirstRecommendedFileForUri(props.uri)(state),
|
||||
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
import 'babel-polyfill';
|
||||
import type { Claim } from 'types/claim';
|
||||
import * as React from 'react';
|
||||
// @if TARGET='app'
|
||||
import { remote } from 'electron';
|
||||
|
@ -19,7 +18,7 @@ type Props = {
|
|||
position: ?number,
|
||||
downloadPath: string,
|
||||
fileName: string,
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
onStartCb: ?() => void,
|
||||
onFinishCb: ?() => void,
|
||||
savePosition: number => void,
|
||||
|
@ -263,11 +262,6 @@ class MediaPlayer extends React.PureComponent<Props, State> {
|
|||
// This files are supported using a custom viewer
|
||||
const { mediaType, contentType } = this.props;
|
||||
|
||||
console.log({
|
||||
mediaType,
|
||||
contentType
|
||||
})
|
||||
|
||||
return (
|
||||
MediaPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1 ||
|
||||
MediaPlayer.SANDBOX_TYPES.indexOf(contentType) > -1
|
||||
|
@ -362,13 +356,6 @@ class MediaPlayer extends React.PureComponent<Props, State> {
|
|||
const isPlayableType = this.playableType();
|
||||
const { isLoading, loadingStatus } = this.showLoadingScreen(isFileType, isPlayableType);
|
||||
|
||||
console.log({
|
||||
mediaType,
|
||||
fileSource,
|
||||
isFileReady,
|
||||
isFileType
|
||||
})
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{loadingStatus && <LoadingScreen status={loadingStatus} spinner={isLoading} />}
|
||||
|
|
|
@ -3,14 +3,13 @@ import * as PAGES from 'constants/pages';
|
|||
import React, { Suspense } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import analytics from 'analytics';
|
||||
import type { Claim } from 'types/claim';
|
||||
import LoadingScreen from 'component/common/loading-screen';
|
||||
import PlayButton from './internal/play-button';
|
||||
|
||||
const Player = React.lazy(() => import(
|
||||
/* webpackChunkName: "player-legacy" */
|
||||
'./internal/player'
|
||||
));
|
||||
const Player = React.lazy(() =>
|
||||
import(/* webpackChunkName: "player-legacy" */
|
||||
'./internal/player')
|
||||
);
|
||||
|
||||
const SPACE_BAR_KEYCODE = 32;
|
||||
|
||||
|
@ -27,10 +26,6 @@ type Props = {
|
|||
fileInfoErrors: ?{
|
||||
[string]: boolean,
|
||||
},
|
||||
metadata: ?{
|
||||
nsfw: boolean,
|
||||
thumbnail: string,
|
||||
},
|
||||
autoplay: boolean,
|
||||
isLoading: boolean,
|
||||
isDownloading: boolean,
|
||||
|
@ -38,7 +33,7 @@ type Props = {
|
|||
contentType: string,
|
||||
changeVolume: number => void,
|
||||
volume: number,
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
uri: string,
|
||||
savePosition: (string, string, number) => void,
|
||||
position: ?number,
|
||||
|
@ -52,6 +47,8 @@ type Props = {
|
|||
navigate: (string, {}) => void,
|
||||
costInfo: ?{ cost: number },
|
||||
insufficientCredits: boolean,
|
||||
nsfw: boolean,
|
||||
thumbnail: ?string,
|
||||
};
|
||||
|
||||
class FileViewer extends React.PureComponent<Props> {
|
||||
|
@ -135,9 +132,9 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
handleAutoplay = (props: Props) => {
|
||||
const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, metadata } = props;
|
||||
const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, nsfw } = props;
|
||||
|
||||
const playable = autoplay && playingUri !== uri && metadata && !metadata.nsfw;
|
||||
const playable = autoplay && playingUri !== uri && !nsfw;
|
||||
|
||||
if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) {
|
||||
this.playContent();
|
||||
|
@ -184,7 +181,7 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
fireAnalyticsEvent(claim: Claim, startTime: ?number, playTime: ?number) {
|
||||
fireAnalyticsEvent(claim: StreamClaim, startTime: ?number, playTime: ?number) {
|
||||
const { claimRewards } = this.props;
|
||||
const { name, claim_id: claimId, txid, nout } = claim;
|
||||
|
||||
|
@ -214,7 +211,6 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
|
||||
render() {
|
||||
const {
|
||||
metadata,
|
||||
isLoading,
|
||||
isDownloading,
|
||||
playingUri,
|
||||
|
@ -230,19 +226,21 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
obscureNsfw,
|
||||
mediaType,
|
||||
insufficientCredits,
|
||||
thumbnail,
|
||||
nsfw,
|
||||
} = this.props;
|
||||
|
||||
const isPlaying = playingUri === uri;
|
||||
let isReadyToPlay = false;
|
||||
// @if TARGET='app'
|
||||
const isReadyToPlay = fileInfo && fileInfo.download_path && fileInfo.written_bytes > 0;
|
||||
isReadyToPlay = fileInfo && fileInfo.download_path && fileInfo.written_bytes > 0;
|
||||
// @endif
|
||||
// @if TARGET='web'
|
||||
// try to play immediately on web, we don't need to call file_list since we are streaming from reflector
|
||||
// $FlowFixMe
|
||||
const isReadyToPlay = isPlaying;
|
||||
isReadyToPlay = isPlaying;
|
||||
// @endif
|
||||
|
||||
const shouldObscureNsfw = obscureNsfw && metadata && metadata.nsfw;
|
||||
const shouldObscureNsfw = obscureNsfw && nsfw;
|
||||
let loadStatusMessage = '';
|
||||
|
||||
if (fileInfo && fileInfo.completed && (!fileInfo.download_path || !fileInfo.written_bytes)) {
|
||||
|
@ -255,14 +253,13 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
loadStatusMessage = __('Downloading stream... not long left now!');
|
||||
}
|
||||
|
||||
const poster = metadata && metadata.thumbnail;
|
||||
const layoverClass = classnames('content__cover', {
|
||||
'card__media--nsfw': shouldObscureNsfw,
|
||||
'card__media--disabled': insufficientCredits,
|
||||
});
|
||||
|
||||
const layoverStyle =
|
||||
!shouldObscureNsfw && poster ? { backgroundImage: `url("${poster}")` } : {};
|
||||
!shouldObscureNsfw && thumbnail ? { backgroundImage: `url("${thumbnail}")` } : {};
|
||||
|
||||
return (
|
||||
<div className={classnames('video', {}, className)}>
|
||||
|
@ -273,10 +270,10 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
<LoadingScreen status={loadStatusMessage} />
|
||||
</div>
|
||||
) : (
|
||||
<Suspense fallback={<div></div>}>
|
||||
<Suspense fallback={<div />}>
|
||||
<Player
|
||||
fileName={fileInfo.file_name}
|
||||
poster={poster}
|
||||
poster={thumbnail}
|
||||
downloadPath={fileInfo.download_path}
|
||||
mediaType={mediaType}
|
||||
contentType={contentType}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Reward } from 'types/reward';
|
||||
import React from 'react';
|
||||
import RewardLink from 'component/rewardLink';
|
||||
import Yrbl from 'component/yrbl';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import type { Claim } from 'types/claim';
|
||||
import moment from 'moment';
|
||||
import classnames from 'classnames';
|
||||
import Button from 'component/button';
|
||||
|
@ -11,7 +10,7 @@ import { formatLbryUriForWeb } from 'util/uri';
|
|||
type Props = {
|
||||
lastViewed: number,
|
||||
uri: string,
|
||||
claim: ?Claim,
|
||||
claim: ?StreamClaim,
|
||||
selected: boolean,
|
||||
onSelect?: () => void,
|
||||
resolveUri: string => void,
|
||||
|
@ -37,9 +36,9 @@ class NavigationHistoryItem extends React.PureComponent<Props> {
|
|||
|
||||
let name;
|
||||
let title;
|
||||
if (claim && claim.value && claim.value.stream) {
|
||||
if (claim && claim.value) {
|
||||
({ name } = claim);
|
||||
({ title } = claim.value.stream.metadata);
|
||||
({ title } = claim.value);
|
||||
}
|
||||
|
||||
const navigatePath = formatLbryUriForWeb(uri);
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
import * as React from 'react';
|
||||
import Button from 'component/button';
|
||||
import { buildURI } from 'lbry-redux';
|
||||
import type { Claim } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
uri: ?string,
|
||||
myClaimForUri: ?Claim,
|
||||
myClaimForUri: ?StreamClaim,
|
||||
isStillEditing: boolean,
|
||||
onEditMyClaim: (any, string) => void,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import type { PublishParams, UpdatePublishFormData } from 'redux/reducers/publish';
|
||||
import { COPYRIGHT, OTHER } from 'constants/licenses';
|
||||
import { CHANNEL_NEW, CHANNEL_ANONYMOUS, MINIMUM_PUBLISH_BID } from 'constants/claim';
|
||||
import * as ICONS from 'constants/icons';
|
||||
|
@ -40,7 +38,7 @@ type Props = {
|
|||
nameError: ?string,
|
||||
isResolvingUri: boolean,
|
||||
winningBidForClaimUri: number,
|
||||
myClaimForUri: ?Claim,
|
||||
myClaimForUri: ?StreamClaim,
|
||||
licenseType: string,
|
||||
otherLicenseDescription: ?string,
|
||||
licenseUrl: ?string,
|
||||
|
@ -232,12 +230,6 @@ class PublishForm extends React.PureComponent<Props> {
|
|||
isStillEditing: this.props.isStillEditing,
|
||||
};
|
||||
|
||||
// Editing a claim
|
||||
if (!filePath && myClaimForUri && myClaimForUri.value) {
|
||||
const { source } = myClaimForUri.value.stream;
|
||||
publishParams.sources = source;
|
||||
}
|
||||
|
||||
publish(publishParams);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import FileTile from 'component/fileTile';
|
||||
import type { Claim } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claim: ?Claim,
|
||||
claim: ?StreamClaim,
|
||||
recommendedContent: Array<string>,
|
||||
isSearching: boolean,
|
||||
search: string => void,
|
||||
|
@ -37,10 +36,12 @@ export default class RecommendedContent extends React.PureComponent<Props> {
|
|||
getRecommendedContent() {
|
||||
const { claim, search } = this.props;
|
||||
|
||||
if (claim && claim.value && claim.value.stream && claim.value.stream.metadata) {
|
||||
const { title } = claim.value.stream.metadata;
|
||||
search(title);
|
||||
this.didSearch = true;
|
||||
if (claim && claim.value && claim.value) {
|
||||
const { title } = claim.value;
|
||||
if (title) {
|
||||
search(title);
|
||||
this.didSearch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import { connect } from 'react-redux';
|
||||
import SelectChannel from './view';
|
||||
import { selectBalance, selectMyChannelClaims, selectFetchingMyChannels } from 'lbry-redux';
|
||||
import { doFetchChannelListMine, doCreateChannel } from 'redux/actions/content';
|
||||
import {
|
||||
selectBalance,
|
||||
selectMyChannelClaims,
|
||||
selectFetchingMyChannels,
|
||||
doFetchChannelListMine,
|
||||
doCreateChannel,
|
||||
} from 'lbry-redux';
|
||||
|
||||
const select = state => ({
|
||||
channels: selectMyChannelClaims(state),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
|
@ -7,7 +6,7 @@ import CopyableText from 'component/copyableText';
|
|||
import ToolTip from 'component/common/tooltip';
|
||||
|
||||
type Props = {
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
onDone: () => void,
|
||||
speechShareable: boolean,
|
||||
isChannel: boolean,
|
||||
|
@ -31,8 +30,7 @@ class SocialShare extends React.PureComponent<Props> {
|
|||
const { claim_id: claimId, name: claimName, channel_name: channelName, value } = claim;
|
||||
|
||||
const { speechShareable, onDone } = this.props;
|
||||
const channelClaimId =
|
||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||
const channelClaimId = claim.signing_channel && claim.signing_channel.claim_id;
|
||||
|
||||
const getSpeechUri = (): string => {
|
||||
if (isChannel) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Status } from 'types/status';
|
||||
import * as React from 'react';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
|
@ -97,11 +96,11 @@ export default class SplashScreen extends React.PureComponent<Props, State> {
|
|||
});
|
||||
}
|
||||
|
||||
updateStatusCallback(status: Status) {
|
||||
updateStatusCallback(status: StatusResponse) {
|
||||
const { notifyUnlockWallet, authenticate, modal } = this.props;
|
||||
const { launchedModal } = this.state;
|
||||
|
||||
if (status.error) {
|
||||
if (status.connection_status.code !== 'connected') {
|
||||
this.setState({ error: true });
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Transaction } from 'types/transaction';
|
||||
import * as TXN_TYPES from 'constants/transaction_types';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
// @flow
|
||||
import type { Transaction } from 'types/transaction';
|
||||
import * as icons from 'constants/icons';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import * as React from 'react';
|
||||
import { List } from 'react-virtualized'
|
||||
import { List } from 'react-virtualized';
|
||||
import { FormField, Form } from 'component/common/form';
|
||||
import Button from 'component/button';
|
||||
import FileExporter from 'component/common/file-exporter';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Transaction } from 'types/transaction';
|
||||
import * as icons from 'constants/icons';
|
||||
import React, { Fragment } from 'react';
|
||||
import BusyIndicator from 'component/common/busy-indicator';
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
import { buildURI } from 'lbry-redux';
|
||||
import type { Claim } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
isResolvingUri: boolean,
|
||||
claim: Claim,
|
||||
channelUri: ?string,
|
||||
link: ?boolean,
|
||||
claim: ?StreamClaim,
|
||||
channelClaim: ?ChannelClaim,
|
||||
// Lint thinks we aren't using these, even though we are.
|
||||
// Possibly because the resolve function is an arrow function that is passed in props?
|
||||
resolveUri: string => void,
|
||||
|
@ -32,25 +33,23 @@ class UriIndicator extends React.PureComponent<Props> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { claim, link, isResolvingUri } = this.props;
|
||||
const { link, isResolvingUri, claim } = this.props;
|
||||
|
||||
if (!claim) {
|
||||
return <span className="empty">{isResolvingUri ? 'Validating...' : 'Unused'}</span>;
|
||||
}
|
||||
const { channel_name: channelName, signature_is_valid: signatureIsValid, value } = claim;
|
||||
|
||||
const channelClaimId =
|
||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||
|
||||
if (!channelName) {
|
||||
if (!claim.signing_channel) {
|
||||
return <span className="channel-name">Anonymous</span>;
|
||||
}
|
||||
|
||||
const { name, claim_id: claimId } = claim.signing_channel;
|
||||
let channelLink;
|
||||
if (signatureIsValid) {
|
||||
channelLink = link ? buildURI({ channelName, claimId: channelClaimId }) : false;
|
||||
if (claim.is_channel_signature_valid) {
|
||||
channelLink = link ? buildURI({ channelName: name, claimId }) : false;
|
||||
}
|
||||
|
||||
const inner = <span className="channel-name">{channelName}</span>;
|
||||
const inner = <span className="channel-name">{name}</span>;
|
||||
|
||||
if (!channelLink) {
|
||||
return inner;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import React from 'react';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import Button from 'component/button';
|
||||
|
@ -15,18 +13,7 @@ import styles from './audioViewer.module.scss';
|
|||
|
||||
const isButterchurnSupported = detectButterchurnSupport();
|
||||
|
||||
const EQ_BANDS_SIMPLE = [
|
||||
55,
|
||||
150,
|
||||
250,
|
||||
400,
|
||||
500,
|
||||
1000,
|
||||
2000,
|
||||
4000,
|
||||
8000,
|
||||
16000,
|
||||
]
|
||||
const EQ_BANDS_SIMPLE = [55, 150, 250, 400, 500, 1000, 2000, 4000, 8000, 16000];
|
||||
/*
|
||||
const EQ_LOWSHELF = EQ_BANDS_SIMPLE.shift();
|
||||
const EQ_HIGHSHELF = EQ_BANDS_SIMPLE.pop();
|
||||
|
@ -41,15 +28,15 @@ const eqFilters = EQ.map(function(band) {
|
|||
});
|
||||
*/
|
||||
|
||||
type Props = {
|
||||
source: {
|
||||
downloadPath: string,
|
||||
fileName: string,
|
||||
},
|
||||
contentType: string,
|
||||
poster?: string,
|
||||
claim: Claim,
|
||||
};
|
||||
// type Props = {
|
||||
// source: {
|
||||
// downloadPath: string,
|
||||
// fileName: string,
|
||||
// },
|
||||
// contentType: string,
|
||||
// poster?: string,
|
||||
// claim: StreamClaim,
|
||||
// };
|
||||
|
||||
const presets = [
|
||||
require('butterchurn-presets/presets/converted/Flexi - when monopolies were the future [simple warp + non-reactive moebius].json'),
|
||||
|
@ -61,9 +48,9 @@ const presets = [
|
|||
require('butterchurn-presets/presets/converted/Zylot - Crosshair Dimension (Light of Ages).json'),
|
||||
];
|
||||
|
||||
class AudioVideoViewer extends React.PureComponent<Props> {
|
||||
audioNode: ?HTMLAudioElement;
|
||||
player: ?{ dispose: () => void };
|
||||
class AudioVideoViewer extends React.PureComponent {
|
||||
// audioNode: ?HTMLAudioElement;
|
||||
// player: ?{ dispose: () => void };
|
||||
|
||||
state = {
|
||||
playing: false,
|
||||
|
@ -107,12 +94,16 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
audioSource.connect(audioContext.destination);
|
||||
|
||||
if (isButterchurnSupported) {
|
||||
const visualizer = me.visualizer = butterchurn.createVisualizer(audioContext, me.canvasNode, {
|
||||
height: canvasHeight,
|
||||
width: canvasWidth,
|
||||
pixelRatio: window.devicePixelRatio || 1,
|
||||
textureRatio: 1,
|
||||
});
|
||||
const visualizer = (me.visualizer = butterchurn.createVisualizer(
|
||||
audioContext,
|
||||
me.canvasNode,
|
||||
{
|
||||
height: canvasHeight,
|
||||
width: canvasWidth,
|
||||
pixelRatio: window.devicePixelRatio || 1,
|
||||
textureRatio: 1,
|
||||
}
|
||||
));
|
||||
|
||||
visualizer.connectAudio(audioSource);
|
||||
visualizer.loadPreset(presets[Math.floor(Math.random() * presets.length)], 2.0);
|
||||
|
@ -120,10 +111,10 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
me._frameCycle = () => {
|
||||
requestAnimationFrame(me._frameCycle);
|
||||
|
||||
if(me.state.enableMilkdrop === true) {
|
||||
if (me.state.enableMilkdrop === true) {
|
||||
visualizer.render();
|
||||
}
|
||||
}
|
||||
};
|
||||
me._frameCycle();
|
||||
}
|
||||
|
||||
|
@ -145,12 +136,7 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
jsmediatags.Config.setDisallowedXhrHeaders(['If-Modified-Since', 'Range']);
|
||||
jsmediatags.read(path, {
|
||||
onSuccess: function(result) {
|
||||
const {
|
||||
album,
|
||||
artist,
|
||||
title,
|
||||
picture
|
||||
} = result.tags;
|
||||
const { album, artist, title, picture } = result.tags;
|
||||
|
||||
if (picture) {
|
||||
const byteArray = new Uint8Array(picture.data);
|
||||
|
@ -169,7 +155,7 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
},
|
||||
onError: function(error) {
|
||||
console.log(':(', error.type, error.info);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -203,18 +189,26 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
const path = `https://api.lbry.tv/content/claims/${claim.name}/${claim.claim_id}/stream.mp4`;
|
||||
|
||||
const playButton = (
|
||||
<div onClick={()=>{
|
||||
<div
|
||||
onClick={() => {
|
||||
const audioNode = this.audioNode;
|
||||
if (audioNode.paused) {
|
||||
audioNode.play();
|
||||
} else {
|
||||
audioNode.pause();
|
||||
}
|
||||
}} className={playing ? styles.playButtonPause : styles.playButtonPlay}></div>
|
||||
}}
|
||||
className={playing ? styles.playButtonPause : styles.playButtonPlay}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={userActive ? styles.userActive : styles.wrapper} onMouseEnter={()=>me.setState({ userActive: true })} onMouseLeave={()=>me.setState({ userActive: false })} onContextMenu={stopContextMenu}>
|
||||
<div
|
||||
className={userActive ? styles.userActive : styles.wrapper}
|
||||
onMouseEnter={() => me.setState({ userActive: true })}
|
||||
onMouseLeave={() => me.setState({ userActive: false })}
|
||||
onContextMenu={stopContextMenu}
|
||||
>
|
||||
<div className={enableMilkdrop ? styles.containerWithMilkdrop : styles.container}>
|
||||
<div style={{ position: 'absolute', top: 0, right: 0 }}>
|
||||
<Tooltip onComponent body={__('Toggle Visualizer')}>
|
||||
|
@ -226,9 +220,12 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
// Get new preset
|
||||
this.visualizer.loadPreset(presets[Math.floor(Math.random() * presets.length)], 2.0);
|
||||
this.visualizer.loadPreset(
|
||||
presets[Math.floor(Math.random() * presets.length)],
|
||||
2.0
|
||||
);
|
||||
|
||||
this.setState({ enableMilkdrop: !enableMilkdrop })
|
||||
this.setState({ enableMilkdrop: !enableMilkdrop });
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
@ -251,24 +248,56 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div ref={node => (this.waveNode = node)} className={styles.wave}></div>
|
||||
<div ref={node => (this.waveNode = node)} className={styles.wave} />
|
||||
<div className={styles.infoContainer}>
|
||||
<div className={renderArt ? styles.infoArtContainer : styles.infoArtContainerHidden}>
|
||||
<img className={styles.infoArtImage} ref={node => (this.artNode = node)} />
|
||||
{renderArt && playButton}
|
||||
</div>
|
||||
<div className={showSongDetails ? (renderArt ? styles.songDetailsContainer : styles.songDetailsContainerNoArt) : styles.songDetailsContainerHidden}>
|
||||
<div
|
||||
className={
|
||||
showSongDetails
|
||||
? renderArt
|
||||
? styles.songDetailsContainer
|
||||
: styles.songDetailsContainerNoArt
|
||||
: styles.songDetailsContainerHidden
|
||||
}
|
||||
>
|
||||
<div className={renderArt ? styles.songDetails : styles.songDetailsNoArt}>
|
||||
{artist && <div className={styles.detailsLineArtist}><Button icon={ICONS.MUSIC_ARTIST} className={styles.detailsIconArtist} />{artist}</div>}
|
||||
{title && <div className={styles.detailsLineSong}><Button icon={ICONS.MUSIC_SONG} className={styles.detailsIconSong} />{title}</div>}
|
||||
{album && <div className={styles.detailsLineAlbum}><Button icon={ICONS.MUSIC_ALBUM} className={styles.detailsIconAlbum} />{album}</div>}
|
||||
{artist && (
|
||||
<div className={styles.detailsLineArtist}>
|
||||
<Button icon={ICONS.MUSIC_ARTIST} className={styles.detailsIconArtist} />
|
||||
{artist}
|
||||
</div>
|
||||
)}
|
||||
{title && (
|
||||
<div className={styles.detailsLineSong}>
|
||||
<Button icon={ICONS.MUSIC_SONG} className={styles.detailsIconSong} />
|
||||
{title}
|
||||
</div>
|
||||
)}
|
||||
{album && (
|
||||
<div className={styles.detailsLineAlbum}>
|
||||
<Button icon={ICONS.MUSIC_ALBUM} className={styles.detailsIconAlbum} />
|
||||
{album}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!renderArt && <div className={styles.playButtonDetachedContainer}>{playButton}</div>}
|
||||
</div>
|
||||
<canvas ref={node => (this.canvasNode = node)} className={enableMilkdrop ? styles.milkdrop : styles.milkdropDisabled} />
|
||||
<audio ref={node => (this.audioNode = node)} src={path} style={{ position: 'absolute', top: '-100px' }} onPlay={()=>this.setState({ playing: true })} onPause={()=>this.setState({ playing: false })} />
|
||||
<canvas
|
||||
ref={node => (this.canvasNode = node)}
|
||||
className={enableMilkdrop ? styles.milkdrop : styles.milkdropDisabled}
|
||||
/>
|
||||
<audio
|
||||
ref={node => (this.audioNode = node)}
|
||||
src={path}
|
||||
style={{ position: 'absolute', top: '-100px' }}
|
||||
onPlay={() => this.setState({ playing: true })}
|
||||
onPause={() => this.setState({ playing: false })}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ import React, { Suspense } from 'react';
|
|||
import LoadingScreen from 'component/common/loading-screen';
|
||||
import MarkdownPreview from 'component/common/markdown-preview';
|
||||
|
||||
const LazyCodeViewer = React.lazy(() => import(
|
||||
/* webpackChunkName: "codeViewer" */
|
||||
'component/viewers/codeViewer'
|
||||
));
|
||||
const LazyCodeViewer = React.lazy<*>(() =>
|
||||
import(/* webpackChunkName: "codeViewer" */
|
||||
'component/viewers/codeViewer')
|
||||
);
|
||||
|
||||
type Props = {
|
||||
theme: string,
|
||||
|
@ -84,7 +84,7 @@ class DocumentViewer extends React.PureComponent<Props, State> {
|
|||
<div className="file-render__viewer document-viewer">
|
||||
{loading && !error && <LoadingScreen status={loadingMessage} spinner />}
|
||||
{error && <LoadingScreen status={errorMessage} spinner={!error} />}
|
||||
{isReady && <Suspense fallback={<div></div>}>{this.renderDocument()}</Suspense>}
|
||||
{isReady && <Suspense fallback={<div />}>{this.renderDocument()}</Suspense>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import React, { Suspense } from 'react';
|
||||
import { stopContextMenu } from 'util/context-menu';
|
||||
import analytics from 'analytics';
|
||||
import(/* webpackChunkName: "videojs" */
|
||||
/* webpackPreload: true */
|
||||
'video.js/dist/video-js.css');
|
||||
'video.js/dist/video-js.css');
|
||||
|
||||
type Props = {
|
||||
source: {
|
||||
|
@ -14,7 +13,7 @@ type Props = {
|
|||
},
|
||||
contentType: string,
|
||||
poster?: string,
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
};
|
||||
|
||||
class AudioVideoViewer extends React.PureComponent<Props> {
|
||||
|
@ -50,11 +49,13 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
|||
import(/* webpackChunkName: "videojs" */
|
||||
/* webpackMode: "lazy" */
|
||||
/* webpackPreload: true */
|
||||
'video.js').then(videojs => {
|
||||
'video.js').then(videojs => {
|
||||
if (videojs.__esModule) {
|
||||
videojs = videojs.default;
|
||||
this.player = videojs(this.videoNode, videoJsOptions, () => {});
|
||||
} else {
|
||||
throw Error('Unable to import and use videojs');
|
||||
}
|
||||
this.player = videojs(this.videoNode, videoJsOptions, () => {});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
import { FormField, Form } from 'component/common/form';
|
||||
import type { Claim } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
title: string,
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
isPending: boolean,
|
||||
sendSupport: (number, string, string) => void,
|
||||
onCancel: () => void,
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
import React from 'react';
|
||||
import FilePrice from 'component/filePrice';
|
||||
import { Modal } from 'modal/modal';
|
||||
import type { Metadata } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
closeModal: () => void,
|
||||
loadVideo: string => void,
|
||||
uri: string,
|
||||
cancelPurchase: () => void,
|
||||
metadata: Metadata,
|
||||
metadata: StreamMetadata,
|
||||
};
|
||||
|
||||
class ModalAffirmPurchase extends React.PureComponent<Props> {
|
||||
|
@ -42,7 +41,7 @@ class ModalAffirmPurchase extends React.PureComponent<Props> {
|
|||
>
|
||||
<section className="card__content">
|
||||
<p>
|
||||
{__('This will purchase')} <strong>{`"${title}"`}</strong> {__('for')}{' '}
|
||||
{__('This will purchase')} <strong>{title ? `"${title}"` : uri}</strong> {__('for')}{' '}
|
||||
<strong>
|
||||
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
|
||||
</strong>{' '}
|
||||
|
|
|
@ -1,21 +1,15 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doHideModal } from 'redux/actions/app';
|
||||
import { doUploadThumbnail, doUpdatePublishForm } from 'redux/actions/publish';
|
||||
import { selectPublishFormValues } from 'redux/selectors/publish';
|
||||
import ModalConfirmThumbnailUpload from './view';
|
||||
|
||||
const select = state => {
|
||||
const publishState = selectPublishFormValues(state);
|
||||
return { nsfw: publishState.nsfw };
|
||||
};
|
||||
|
||||
const perform = dispatch => ({
|
||||
closeModal: () => dispatch(doHideModal()),
|
||||
upload: (path, nsfw = false) => dispatch(doUploadThumbnail(path, nsfw)),
|
||||
upload: path => dispatch(doUploadThumbnail(path)),
|
||||
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
null,
|
||||
perform
|
||||
)(ModalConfirmThumbnailUpload);
|
||||
|
|
|
@ -4,23 +4,22 @@ import { Modal } from 'modal/modal';
|
|||
import { FormField } from 'component/common/form';
|
||||
|
||||
type Props = {
|
||||
upload: (string, boolean) => void,
|
||||
upload: string => void,
|
||||
path: string,
|
||||
nsfw: boolean,
|
||||
closeModal: () => void,
|
||||
updatePublishForm: ({}) => void,
|
||||
};
|
||||
|
||||
class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
|
||||
upload() {
|
||||
const { upload, updatePublishForm, closeModal, path, nsfw } = this.props;
|
||||
upload(path, nsfw);
|
||||
const { upload, updatePublishForm, closeModal, path } = this.props;
|
||||
upload(path);
|
||||
updatePublishForm({ thumbnailPath: path });
|
||||
closeModal();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { closeModal, path, updatePublishForm, nsfw } = this.props;
|
||||
const { closeModal, path, updatePublishForm } = this.props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
@ -36,14 +35,6 @@ class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
|
|||
<p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p>
|
||||
|
||||
<blockquote>{path}</blockquote>
|
||||
|
||||
<FormField
|
||||
type="checkbox"
|
||||
name="content_is_mature"
|
||||
label={__('For mature audiences only')}
|
||||
checked={nsfw}
|
||||
onChange={event => updatePublishForm({ nsfw: event.target.checked })}
|
||||
/>
|
||||
</section>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
@ -10,7 +10,9 @@ type Props = {
|
|||
|
||||
class ModalError extends React.PureComponent<Props> {
|
||||
componentDidMount() {
|
||||
Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) });
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) });
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { closeModal, error } = this.props;
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import type { Metadata } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
metadata: Metadata,
|
||||
uri: string,
|
||||
metadata: StreamMetadata,
|
||||
closeModal: () => void,
|
||||
};
|
||||
|
||||
class ModalFileTimeout extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const {
|
||||
uri,
|
||||
metadata: { title },
|
||||
closeModal,
|
||||
} = this.props;
|
||||
|
@ -26,7 +27,7 @@ class ModalFileTimeout extends React.PureComponent<Props> {
|
|||
<p className="error-modal__error-list">
|
||||
{__('LBRY was unable to download the stream')}:
|
||||
<div>
|
||||
<b>{`"${title}"`}</b>
|
||||
<b>{title ? `"${title}"` : uri}</b>
|
||||
</div>
|
||||
</p>
|
||||
</section>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Transaction } from 'types/transaction';
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import * as txnTypes from 'constants/transaction_types';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { UrlLocation } from 'types/location';
|
||||
import React from 'react';
|
||||
import BusyIndicator from 'component/common/busy-indicator';
|
||||
import Button from 'component/button';
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import type { UrlLocation } from 'types/location';
|
||||
import * as icons from 'constants/icons';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import React, { useEffect } from 'react';
|
||||
|
@ -19,8 +17,8 @@ type Props = {
|
|||
totalPages: number,
|
||||
fetching: boolean,
|
||||
params: { page: number },
|
||||
claim: Claim,
|
||||
claimsInChannel: Array<Claim>,
|
||||
claim: ChannelClaim,
|
||||
claimsInChannel: Array<StreamClaim>,
|
||||
channelIsMine: boolean,
|
||||
fetchClaims: (string, number) => void,
|
||||
history: { push: string => void },
|
||||
|
@ -82,10 +80,10 @@ function ChannelPage(props: Props) {
|
|||
{name}
|
||||
{fetching && <BusyIndicator />}
|
||||
</h1>
|
||||
<span>{`lbry://${permanentUrl}`}</span>
|
||||
<span>{permanentUrl}</span>
|
||||
|
||||
<div className="channel-info__actions__group">
|
||||
<SubscribeButton uri={`lbry://${permanentUrl}`} channelName={name} />
|
||||
<SubscribeButton uri={permanentUrl} channelName={name} />
|
||||
<Button
|
||||
button="alt"
|
||||
icon={icons.SHARE}
|
||||
|
|
|
@ -13,6 +13,9 @@ import {
|
|||
makeSelectMetadataForUri,
|
||||
makeSelectChannelForClaimUri,
|
||||
selectBalance,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
makeSelectClaimIsNsfw,
|
||||
} from 'lbry-redux';
|
||||
import {
|
||||
doFetchViewCount,
|
||||
|
@ -41,6 +44,9 @@ const select = (state, props) => ({
|
|||
channelUri: makeSelectChannelForClaimUri(props.uri, true)(state),
|
||||
viewCount: makeSelectViewCountForUri(props.uri)(state),
|
||||
balance: selectBalance(state),
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
// @flow
|
||||
import type { Claim, Metadata } from 'types/claim';
|
||||
import type { FileInfo } from 'types/file_info';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import * as icons from 'constants/icons';
|
||||
import * as React from 'react';
|
||||
import { buildURI, normalizeURI } from 'lbry-redux';
|
||||
import {buildURI, normalizeURI} from 'lbry-redux';
|
||||
import FileViewer from 'component/fileViewer';
|
||||
import Thumbnail from 'component/common/thumbnail';
|
||||
import FilePrice from 'component/filePrice';
|
||||
|
@ -22,15 +20,15 @@ import getMediaType from 'util/get-media-type';
|
|||
import RecommendedContent from 'component/recommendedContent';
|
||||
|
||||
type Props = {
|
||||
claim: Claim,
|
||||
fileInfo: FileInfo,
|
||||
metadata: Metadata,
|
||||
claim: StreamClaim,
|
||||
fileInfo: FileListItem,
|
||||
metadata: StreamMetadata,
|
||||
contentType: string,
|
||||
uri: string,
|
||||
rewardedContentClaimIds: Array<string>,
|
||||
obscureNsfw: boolean,
|
||||
claimIsMine: boolean,
|
||||
costInfo: ?{ cost: number },
|
||||
costInfo: ?{cost: number},
|
||||
fetchFileInfo: string => void,
|
||||
fetchCostInfo: string => void,
|
||||
setViewed: string => void,
|
||||
|
@ -39,10 +37,13 @@ type Props = {
|
|||
channelUri: string,
|
||||
viewCount: number,
|
||||
prepareEdit: ({}, string) => void,
|
||||
openModal: (id: string, { uri: string }) => void,
|
||||
openModal: (id: string, {uri: string}) => void,
|
||||
markSubscriptionRead: (string, string) => void,
|
||||
fetchViewCount: string => void,
|
||||
balance: number,
|
||||
title: string,
|
||||
thumbnail: ?string,
|
||||
nsfw: boolean,
|
||||
};
|
||||
|
||||
class FilePage extends React.Component<Props> {
|
||||
|
@ -71,11 +72,11 @@ class FilePage extends React.Component<Props> {
|
|||
claim,
|
||||
} = this.props;
|
||||
|
||||
if (isSubscribed) {
|
||||
if(isSubscribed) {
|
||||
this.removeFromSubscriptionNotifications();
|
||||
}
|
||||
|
||||
if (claimIsMine) {
|
||||
if(claimIsMine) {
|
||||
fetchViewCount(claim.claim_id);
|
||||
}
|
||||
|
||||
|
@ -90,26 +91,26 @@ class FilePage extends React.Component<Props> {
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
const { fetchFileInfo, uri, setViewed } = this.props;
|
||||
const {fetchFileInfo, uri, setViewed} = this.props;
|
||||
// @if TARGET='app'
|
||||
if (nextProps.fileInfo === undefined) {
|
||||
if(nextProps.fileInfo === undefined) {
|
||||
fetchFileInfo(uri);
|
||||
}
|
||||
// @endif
|
||||
|
||||
if (uri !== nextProps.uri) {
|
||||
if(uri !== nextProps.uri) {
|
||||
setViewed(nextProps.uri);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
const { isSubscribed, claim, uri, fetchViewCount, claimIsMine } = this.props;
|
||||
const {isSubscribed, claim, uri, fetchViewCount, claimIsMine} = this.props;
|
||||
|
||||
if (!prevProps.isSubscribed && isSubscribed) {
|
||||
if(!prevProps.isSubscribed && isSubscribed) {
|
||||
this.removeFromSubscriptionNotifications();
|
||||
}
|
||||
|
||||
if (prevProps.uri !== uri && claimIsMine) {
|
||||
if(prevProps.uri !== uri && claimIsMine) {
|
||||
fetchViewCount(claim.claim_id);
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ class FilePage extends React.Component<Props> {
|
|||
removeFromSubscriptionNotifications() {
|
||||
// Always try to remove
|
||||
// If it doesn't exist, nothing will happen
|
||||
const { markSubscriptionRead, uri, channelUri } = this.props;
|
||||
const {markSubscriptionRead, uri, channelUri} = this.props;
|
||||
markSubscriptionRead(channelUri, uri);
|
||||
}
|
||||
|
||||
|
@ -137,21 +138,18 @@ class FilePage extends React.Component<Props> {
|
|||
channelUri,
|
||||
viewCount,
|
||||
balance,
|
||||
title,
|
||||
thumbnail,
|
||||
nsfw,
|
||||
} = this.props;
|
||||
|
||||
// File info
|
||||
const { title, thumbnail } = metadata;
|
||||
const { height, channel_name: channelName } = claim;
|
||||
const { PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES } = FilePage;
|
||||
const {height, channel_name: channelName} = claim;
|
||||
const {PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES} = FilePage;
|
||||
const isRewardContent = (rewardedContentClaimIds || []).includes(claim.claim_id);
|
||||
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
|
||||
const shouldObscureThumbnail = obscureNsfw && nsfw;
|
||||
const fileName = fileInfo ? fileInfo.file_name : null;
|
||||
const mediaType = getMediaType(contentType, fileName);
|
||||
console.log({
|
||||
mediaType,
|
||||
contentType,
|
||||
fileName,
|
||||
});
|
||||
const showFile =
|
||||
PLAYABLE_MEDIA_TYPES.includes(mediaType) || PREVIEW_MEDIA_TYPES.includes(mediaType);
|
||||
|
||||
|
@ -164,12 +162,12 @@ class FilePage extends React.Component<Props> {
|
|||
// This is what the user is used to seeing, they don't care about the claim id
|
||||
// We will select the claim id before they publish
|
||||
let editUri;
|
||||
if (claimIsMine) {
|
||||
const uriObject: { contentName: string, claimId: string, channelName?: string } = {
|
||||
if(claimIsMine) {
|
||||
const uriObject: {contentName: string, claimId: string, channelName?: string} = {
|
||||
contentName: claim.name,
|
||||
claimId: claim.claim_id,
|
||||
};
|
||||
if (channelName) {
|
||||
if(channelName) {
|
||||
uriObject.channelName = channelName;
|
||||
}
|
||||
|
||||
|
@ -204,16 +202,16 @@ class FilePage extends React.Component<Props> {
|
|||
(thumbnail ? (
|
||||
<Thumbnail shouldObscure={shouldObscureThumbnail} src={thumbnail} />
|
||||
) : (
|
||||
<div
|
||||
className={classnames('content__empty', {
|
||||
'content__empty--nsfw': shouldObscureThumbnail,
|
||||
})}
|
||||
>
|
||||
<div className="card__media-text">
|
||||
{__("Sorry, looks like we can't preview this file.")}
|
||||
<div
|
||||
className={classnames('content__empty', {
|
||||
'content__empty--nsfw': shouldObscureThumbnail,
|
||||
})}
|
||||
>
|
||||
<div className="card__media-text">
|
||||
{__("Sorry, looks like we can't preview this file.")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid-area--info media__content media__content--large">
|
||||
|
@ -225,13 +223,13 @@ class FilePage extends React.Component<Props> {
|
|||
size={20}
|
||||
iconColor="red"
|
||||
icon={icons.FEATURED}
|
||||
// Figure out how to get the tooltip to overlap the navbar on the file page and I will love you
|
||||
// https://stackoverflow.com/questions/6421966/css-overflow-x-visible-and-overflow-y-hidden-causing-scrollbar-issue
|
||||
// https://spee.ch/4/overflow-issue
|
||||
// tooltip="bottom"
|
||||
// Figure out how to get the tooltip to overlap the navbar on the file page and I will love you
|
||||
// https://stackoverflow.com/questions/6421966/css-overflow-x-visible-and-overflow-y-hidden-causing-scrollbar-issue
|
||||
// https://spee.ch/4/overflow-issue
|
||||
// tooltip="bottom"
|
||||
/>
|
||||
)}
|
||||
{metadata.nsfw && <div className="badge badge--nsfw">NSFW</div>}
|
||||
{nsfw && <div className="badge badge--nsfw">MATURE</div>}
|
||||
<FilePrice badge uri={normalizeURI(uri)} />
|
||||
</div>
|
||||
|
||||
|
@ -271,7 +269,7 @@ class FilePage extends React.Component<Props> {
|
|||
button="alt"
|
||||
icon={icons.TIP}
|
||||
label={__('Send a tip')}
|
||||
onClick={() => openModal(MODALS.SEND_TIP, { uri })}
|
||||
onClick={() => openModal(MODALS.SEND_TIP, {uri})}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
@ -279,7 +277,7 @@ class FilePage extends React.Component<Props> {
|
|||
button="alt"
|
||||
icon={icons.SHARE}
|
||||
label={__('Share')}
|
||||
onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, speechShareable })}
|
||||
onClick={() => openModal(MODALS.SOCIAL_SHARE, {uri, speechShareable})}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import React from 'react';
|
||||
import Button from 'component/button';
|
||||
import FileList from 'component/fileList';
|
||||
|
@ -7,7 +6,7 @@ import Page from 'component/page';
|
|||
import { PAGES } from 'lbry-redux';
|
||||
|
||||
type Props = {
|
||||
claims: Array<Claim>,
|
||||
claims: Array<StreamClaim>,
|
||||
checkPendingPublishes: () => void,
|
||||
fetching: boolean,
|
||||
sortBy: string,
|
||||
|
|
|
@ -6,7 +6,6 @@ import RewardTile from 'component/rewardTile';
|
|||
import Button from 'component/button';
|
||||
import Page from 'component/page';
|
||||
import classnames from 'classnames';
|
||||
import type { Reward } from 'types/reward';
|
||||
import { rewards as REWARD_TYPES } from 'lbryinc';
|
||||
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { UrlLocation } from 'types/location';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React, { useEffect, Fragment } from 'react';
|
||||
import { isURIValid, normalizeURI, parseURI } from 'lbry-redux';
|
||||
|
|
|
@ -9,7 +9,7 @@ import Page from 'component/page';
|
|||
import FileSelector from 'component/common/file-selector';
|
||||
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
||||
|
||||
export type Price = {
|
||||
type Price = {
|
||||
currency: string,
|
||||
amount: number,
|
||||
};
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
// @flow
|
||||
import type { UrlLocation } from 'types/location';
|
||||
import React from 'react';
|
||||
import BusyIndicator from 'component/common/busy-indicator';
|
||||
import ChannelPage from 'page/channel';
|
||||
import FilePage from 'page/file';
|
||||
import Page from 'component/page';
|
||||
import Button from 'component/button';
|
||||
import type { Claim } from 'types/claim';
|
||||
|
||||
type Props = {
|
||||
isResolvingUri: boolean,
|
||||
resolveUri: string => void,
|
||||
uri: string,
|
||||
claim: Claim,
|
||||
claim: StreamClaim,
|
||||
totalPages: number,
|
||||
location: UrlLocation,
|
||||
blackListedOutpoints: Array<{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// @flow
|
||||
import type { ViewMode } from 'types/subscription';
|
||||
import type { Claim } from 'types/claim';
|
||||
import { VIEW_ALL, VIEW_LATEST_FIRST } from 'constants/subscriptions';
|
||||
import React, { Fragment } from 'react';
|
||||
import Button from 'component/button';
|
||||
|
@ -19,7 +17,7 @@ type Props = {
|
|||
viewMode: ViewMode,
|
||||
doSetViewMode: ViewMode => void,
|
||||
hasSubscriptions: boolean,
|
||||
subscriptions: Array<{ uri: string, ...Claim }>,
|
||||
subscriptions: Array<{ uri: string, ...StreamClaim }>,
|
||||
autoDownload: boolean,
|
||||
onChangeAutoDownload: (SyntheticInputEvent<*>) => void,
|
||||
unreadSubscriptions: Array<{ channel: string, uris: Array<string> }>,
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// @flow
|
||||
import type { ViewMode } from 'types/subscription';
|
||||
import type { Claim } from 'types/claim';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import React, { PureComponent } from 'react';
|
||||
import Page from 'component/page';
|
||||
|
@ -13,7 +11,7 @@ type Props = {
|
|||
channel: string,
|
||||
uris: Array<string>,
|
||||
}>,
|
||||
allSubscriptions: Array<{ uri: string, ...Claim }>,
|
||||
allSubscriptions: Array<{ uri: string, ...StreamClaim }>,
|
||||
loading: boolean,
|
||||
autoDownload: boolean,
|
||||
viewMode: ViewMode,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Dispatch, GetState } from 'types/redux';
|
||||
import * as NOTIFICATION_TYPES from 'constants/subscriptions';
|
||||
import { PAGE_SIZE } from 'constants/claim';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
|
@ -25,9 +24,7 @@ import {
|
|||
creditsToString,
|
||||
doError,
|
||||
} from 'lbry-redux';
|
||||
import {
|
||||
makeSelectCostInfoForUri,
|
||||
} from 'lbryinc';
|
||||
import { makeSelectCostInfoForUri } from 'lbryinc';
|
||||
import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings';
|
||||
import analytics from 'analytics';
|
||||
import { formatLbryUriForWeb } from 'util/uri';
|
||||
|
@ -305,9 +302,12 @@ export function doFetchClaimsByChannel(
|
|||
data: { uri, page },
|
||||
});
|
||||
|
||||
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;
|
||||
// TODO: can we keep uri?
|
||||
// claim_search should accept a uri (this allows for fetching vanity channel content)
|
||||
const { claimId } = parseURI(uri);
|
||||
|
||||
Lbry.claim_search({ channel_id: claimId, page, page_size: pageSize }).then(result => {
|
||||
const { items: claimsInChannel, page: returnedPage } = result;
|
||||
|
||||
if (claimsInChannel && claimsInChannel.length) {
|
||||
if (page === 1) {
|
||||
|
@ -319,7 +319,7 @@ export function doFetchClaimsByChannel(
|
|||
uri: buildURI(
|
||||
{
|
||||
contentName: latest.channel_name,
|
||||
claimId: latest.value.publisherSignature.certificateId,
|
||||
claimId: latest.claim_id,
|
||||
},
|
||||
false
|
||||
),
|
||||
|
@ -351,51 +351,6 @@ export function doPlayUri(uri: string) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doFetchChannelListMine() {
|
||||
return (dispatch: Dispatch) => {
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_CHANNEL_LIST_STARTED,
|
||||
});
|
||||
|
||||
const callback = channels => {
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_CHANNEL_LIST_COMPLETED,
|
||||
data: { claims: channels },
|
||||
});
|
||||
};
|
||||
|
||||
Lbry.channel_list().then(callback);
|
||||
};
|
||||
}
|
||||
|
||||
export function doCreateChannel(name: string, amount: number) {
|
||||
return (dispatch: Dispatch) => {
|
||||
dispatch({
|
||||
type: ACTIONS.CREATE_CHANNEL_STARTED,
|
||||
});
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
Lbry.channel_new({
|
||||
channel_name: name,
|
||||
amount: creditsToString(amount),
|
||||
}).then(
|
||||
newChannelClaim => {
|
||||
const channelClaim = newChannelClaim;
|
||||
channelClaim.name = name;
|
||||
dispatch({
|
||||
type: ACTIONS.CREATE_CHANNEL_COMPLETED,
|
||||
data: { channelClaim },
|
||||
});
|
||||
resolve(channelClaim);
|
||||
},
|
||||
error => {
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function savePosition(claimId: string, outpoint: string, position: number) {
|
||||
return (dispatch: Dispatch) => {
|
||||
dispatch({
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
// @flow
|
||||
import type { Dispatch, GetState } from 'types/redux';
|
||||
import type { Metadata } from 'types/claim';
|
||||
import type {
|
||||
UpdatePublishFormData,
|
||||
UpdatePublishFormAction,
|
||||
PublishParams,
|
||||
} from 'redux/reducers/publish';
|
||||
import { CC_LICENSES, COPYRIGHT, OTHER, NONE, PUBLIC_DOMAIN } from 'constants/licenses';
|
||||
import * as MODALS from 'constants/modal_types';
|
||||
import {
|
||||
|
@ -29,9 +22,7 @@ import fs from 'fs';
|
|||
import path from 'path';
|
||||
// @endif
|
||||
|
||||
type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH };
|
||||
|
||||
export const doResetThumbnailStatus = () => (dispatch: Dispatch): Promise<Action> => {
|
||||
export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
|
||||
dispatch({
|
||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||
data: {
|
||||
|
@ -67,22 +58,20 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch): Promise<Action
|
|||
);
|
||||
};
|
||||
|
||||
export const doClearPublish = () => (dispatch: Dispatch): Promise<Action> => {
|
||||
export const doClearPublish = () => (dispatch: Dispatch) => {
|
||||
dispatch({ type: ACTIONS.CLEAR_PUBLISH });
|
||||
return dispatch(doResetThumbnailStatus());
|
||||
};
|
||||
|
||||
export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => (
|
||||
dispatch: Dispatch
|
||||
): UpdatePublishFormAction =>
|
||||
dispatch(
|
||||
({
|
||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||
data: { ...publishFormValue },
|
||||
}: UpdatePublishFormAction)
|
||||
);
|
||||
) =>
|
||||
dispatch({
|
||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||
data: { ...publishFormValue },
|
||||
});
|
||||
|
||||
export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: Dispatch) => {
|
||||
export const doUploadThumbnail = (filePath: string) => (dispatch: Dispatch) => {
|
||||
const thumbnail = fs.readFileSync(filePath);
|
||||
const fileExt = path.extname(filePath);
|
||||
const fileName = path.basename(filePath);
|
||||
|
@ -119,7 +108,7 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch:
|
|||
const file = new File([thumbnail], fileName, { type: `image/${fileExt.slice(1)}` });
|
||||
data.append('name', name);
|
||||
data.append('file', file);
|
||||
data.append('nsfw', nsfw.toString());
|
||||
|
||||
return fetch('https://spee.ch/api/claim/publish', {
|
||||
method: 'POST',
|
||||
body: data,
|
||||
|
@ -139,15 +128,8 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch:
|
|||
.catch(err => uploadError(err.message));
|
||||
};
|
||||
|
||||
export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) => {
|
||||
const {
|
||||
name,
|
||||
amount,
|
||||
channel_name: channelName,
|
||||
value: {
|
||||
stream: { metadata },
|
||||
},
|
||||
} = claim;
|
||||
export const doPrepareEdit = (claim: StreamClaim, uri: string) => (dispatch: Dispatch) => {
|
||||
const { name, amount, channel_name: channelName, value } = claim;
|
||||
|
||||
const {
|
||||
author,
|
||||
|
@ -158,26 +140,23 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) =
|
|||
amount: 0,
|
||||
currency: 'LBC',
|
||||
},
|
||||
language,
|
||||
languages,
|
||||
license,
|
||||
licenseUrl,
|
||||
nsfw,
|
||||
license_url: licenseUrl,
|
||||
thumbnail,
|
||||
title,
|
||||
} = metadata;
|
||||
} = value;
|
||||
|
||||
const publishData: UpdatePublishFormData = {
|
||||
name,
|
||||
channel: channelName,
|
||||
bid: amount,
|
||||
price: { amount: fee.amount, currency: fee.currency },
|
||||
contentIsFree: !fee.amount,
|
||||
author,
|
||||
description,
|
||||
fee,
|
||||
language,
|
||||
nsfw,
|
||||
thumbnail,
|
||||
languages,
|
||||
thumbnail: thumbnail ? thumbnail.url : null,
|
||||
title,
|
||||
uri,
|
||||
uploadThumbnailStatus: thumbnail ? THUMBNAIL_STATUSES.MANUAL : undefined,
|
||||
|
@ -204,6 +183,8 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) =
|
|||
};
|
||||
|
||||
export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => {
|
||||
dispatch({ type: ACTIONS.PUBLISH_START });
|
||||
|
||||
const state = getState();
|
||||
const myChannels = selectMyChannelClaims(state);
|
||||
const myClaims = selectMyClaimsWithoutChannels(state);
|
||||
|
@ -217,55 +198,63 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
|
|||
license,
|
||||
licenseUrl,
|
||||
thumbnail,
|
||||
nsfw,
|
||||
channel,
|
||||
title,
|
||||
contentIsFree,
|
||||
price,
|
||||
fee,
|
||||
uri,
|
||||
nsfw,
|
||||
} = params;
|
||||
|
||||
// get the claim id from the channel name, we will use that instead
|
||||
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
|
||||
const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';
|
||||
const fee = contentIsFree || !price.amount ? undefined : { ...price };
|
||||
|
||||
const metadata: Metadata = {
|
||||
title,
|
||||
nsfw,
|
||||
license,
|
||||
licenseUrl,
|
||||
language,
|
||||
thumbnail,
|
||||
description: description || undefined,
|
||||
};
|
||||
|
||||
const publishPayload: {
|
||||
name: ?string,
|
||||
channel_id: string,
|
||||
bid: ?number,
|
||||
metadata: ?Metadata,
|
||||
channel_id?: string,
|
||||
bid: number,
|
||||
file_path?: string,
|
||||
fee?: { amount: string, currency: string },
|
||||
tags: Array<string>,
|
||||
} = {
|
||||
name,
|
||||
channel_id: channelId,
|
||||
bid: creditsToString(bid),
|
||||
metadata,
|
||||
title,
|
||||
license,
|
||||
license_url: licenseUrl,
|
||||
languages: [language],
|
||||
description,
|
||||
thumbnail_url: thumbnail,
|
||||
tags: [],
|
||||
};
|
||||
|
||||
// Temporary solution to keep the same publish flow with the new tags api
|
||||
// Eventually we will allow users to enter their own tags on publish
|
||||
// `nsfw` will probably be removed
|
||||
if (nsfw) {
|
||||
publishPayload.tags.push('mature');
|
||||
}
|
||||
|
||||
if (channelId) {
|
||||
publishPayload.channel_id = channelId;
|
||||
}
|
||||
|
||||
if (fee) {
|
||||
metadata.fee = {
|
||||
publishPayload.fee = {
|
||||
currency: fee.currency,
|
||||
amount: creditsToString(fee.amount),
|
||||
};
|
||||
}
|
||||
// only pass file on new uploads, not metadata only edits.
|
||||
|
||||
// Only pass file on new uploads, not metadata only edits.
|
||||
// The sdk will figure it out
|
||||
if (filePath) publishPayload.file_path = filePath;
|
||||
|
||||
dispatch({ type: ACTIONS.PUBLISH_START });
|
||||
|
||||
const success = pendingClaim => {
|
||||
const success = successResponse => {
|
||||
analytics.apiLogPublish();
|
||||
|
||||
const pendingClaim = successResponse.outputs[0];
|
||||
const actions = [];
|
||||
|
||||
actions.push({
|
||||
|
@ -280,8 +269,8 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
|
|||
const isMatch = claim => claim.claim_id === pendingClaim.claim_id;
|
||||
const isEdit = myClaims.some(isMatch);
|
||||
const myNewClaims = isEdit
|
||||
? myClaims.map(claim => (isMatch(claim) ? pendingClaim.output : claim))
|
||||
: myClaims.concat(pendingClaim.output);
|
||||
? myClaims.map(claim => (isMatch(claim) ? pendingClaim : claim))
|
||||
: myClaims.concat(pendingClaim);
|
||||
|
||||
actions.push({
|
||||
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
||||
|
@ -313,7 +302,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS
|
|||
let publishCheckInterval;
|
||||
|
||||
const checkFileList = () => {
|
||||
Lbry.claim_list_mine().then(claims => {
|
||||
Lbry.claim_list().then(claims => {
|
||||
claims.forEach(claim => {
|
||||
// If it's confirmed, check if it was pending previously
|
||||
if (claim.confirmations > 0 && pendingById[claim.claim_id]) {
|
||||
|
@ -322,7 +311,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS
|
|||
// If it's confirmed, check if we should notify the user
|
||||
if (selectosNotificationsEnabled(getState())) {
|
||||
const notif = new window.Notification('LBRY Publish Complete', {
|
||||
body: `${claim.value.stream.metadata.title} has been published to lbry://${
|
||||
body: `${claim.value.stream.title} has been published to lbry://${
|
||||
claim.name
|
||||
}. Click here to view it`,
|
||||
silent: false,
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
// @flow
|
||||
import type { Dispatch, GetState } from 'types/redux';
|
||||
import type {
|
||||
SubscriptionState,
|
||||
Subscription,
|
||||
SubscriptionNotificationType,
|
||||
ViewMode,
|
||||
UnreadSubscription,
|
||||
} from 'types/subscription';
|
||||
import { PAGE_SIZE } from 'constants/claim';
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
|
@ -239,8 +231,10 @@ export const doCheckSubscription = (subscriptionUri: string, shouldNotify?: bool
|
|||
);
|
||||
}
|
||||
|
||||
const { claimId } = parseURI(subscriptionUri);
|
||||
|
||||
// We may be duplicating calls here. Can this logic be baked into doFetchClaimsByChannel?
|
||||
Lbry.claim_list_by_channel({ uri: subscriptionUri, page: 1, page_size: PAGE_SIZE }).then(
|
||||
Lbry.claim_search({ channel_id: claimId, page: 1, page_size: PAGE_SIZE }).then(
|
||||
claimListByChannel => {
|
||||
const claimResult = claimListByChannel[subscriptionUri] || {};
|
||||
const { claims_in_channel: claimsInChannel } = claimResult;
|
||||
|
@ -268,9 +262,7 @@ export const doCheckSubscription = (subscriptionUri: string, shouldNotify?: bool
|
|||
const uri = buildURI({ contentName: claim.name, claimId: claim.claim_id }, true);
|
||||
const shouldDownload =
|
||||
shouldAutoDownload &&
|
||||
Boolean(
|
||||
downloadCount < SUBSCRIPTION_DOWNLOAD_LIMIT && !claim.value.stream.metadata.fee
|
||||
);
|
||||
Boolean(downloadCount < SUBSCRIPTION_DOWNLOAD_LIMIT && !claim.value.stream.fee);
|
||||
|
||||
// Add the new content to the list of "un-read" subscriptions
|
||||
if (shouldNotify) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import { buildURI } from 'lbry-redux';
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
||||
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
||||
import type { Source } from 'types/claim';
|
||||
|
||||
type PublishState = {
|
||||
editingURI: ?string,
|
||||
|
@ -15,7 +14,7 @@ type PublishState = {
|
|||
currency: string,
|
||||
},
|
||||
title: string,
|
||||
thumbnail: string,
|
||||
thumbnail_url: string,
|
||||
thumbnailPath: string,
|
||||
uploadThumbnailStatus: string,
|
||||
description: string,
|
||||
|
@ -30,60 +29,6 @@ type PublishState = {
|
|||
licenseUrl: string,
|
||||
};
|
||||
|
||||
export type UpdatePublishFormData = {
|
||||
filePath?: string,
|
||||
contentIsFree?: boolean,
|
||||
price?: {
|
||||
amount: number,
|
||||
currency: string,
|
||||
},
|
||||
title?: string,
|
||||
thumbnail?: string,
|
||||
uploadThumbnailStatus?: string,
|
||||
thumbnailPath?: string,
|
||||
description?: string,
|
||||
language?: string,
|
||||
channel?: string,
|
||||
channelId?: string,
|
||||
name?: string,
|
||||
nameError?: string,
|
||||
bid?: number,
|
||||
bidError?: string,
|
||||
otherLicenseDescription?: string,
|
||||
licenseUrl?: string,
|
||||
licenseType?: string,
|
||||
uri?: string,
|
||||
};
|
||||
|
||||
export type UpdatePublishFormAction = {
|
||||
type: ACTIONS.UPDATE_PUBLISH_FORM | ACTIONS.DO_PREPARE_EDIT,
|
||||
data: UpdatePublishFormData,
|
||||
};
|
||||
|
||||
export type PublishParams = {
|
||||
name?: string,
|
||||
bid?: number,
|
||||
filePath?: string,
|
||||
description: ?string,
|
||||
language: string,
|
||||
publishingLicense?: string,
|
||||
publishingLicenseUrl?: string,
|
||||
thumbnail: ?string,
|
||||
nsfw: boolean,
|
||||
channel: string,
|
||||
channelId?: string,
|
||||
title: string,
|
||||
contentIsFree: boolean,
|
||||
uri?: string,
|
||||
license: ?string,
|
||||
licenseUrl: ?string,
|
||||
price: {
|
||||
currency: string,
|
||||
amount: number,
|
||||
},
|
||||
sources?: Source,
|
||||
};
|
||||
|
||||
const defaultState: PublishState = {
|
||||
editingURI: undefined,
|
||||
filePath: undefined,
|
||||
|
@ -93,7 +38,7 @@ const defaultState: PublishState = {
|
|||
currency: 'LBC',
|
||||
},
|
||||
title: '',
|
||||
thumbnail: '',
|
||||
thumbnail_url: '',
|
||||
thumbnailPath: '',
|
||||
uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN,
|
||||
description: '',
|
||||
|
|
|
@ -2,18 +2,6 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import { VIEW_ALL } from 'constants/subscriptions';
|
||||
import { handleActions } from 'util/redux-utils';
|
||||
import type {
|
||||
SubscriptionState,
|
||||
Subscription,
|
||||
DoChannelSubscribe,
|
||||
DoChannelUnsubscribe,
|
||||
SetSubscriptionLatest,
|
||||
DoUpdateSubscriptionUnreads,
|
||||
DoRemoveSubscriptionUnreads,
|
||||
FetchedSubscriptionsSucess,
|
||||
SetViewMode,
|
||||
GetSuggestedSubscriptionsSuccess,
|
||||
} from 'types/subscription';
|
||||
|
||||
const defaultState: SubscriptionState = {
|
||||
subscriptions: [],
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
// @flow
|
||||
|
||||
// Currently incomplete
|
||||
|
||||
export type Source = {
|
||||
contentType: string,
|
||||
source: string,
|
||||
sourceType: string,
|
||||
version: string,
|
||||
};
|
||||
|
||||
export type Metadata = {
|
||||
nsfw: boolean,
|
||||
title: string,
|
||||
thumbnail: ?string,
|
||||
description: ?string,
|
||||
license: ?string,
|
||||
language: string,
|
||||
fee?:
|
||||
| {
|
||||
amount: number, // should be a string https://github.com/lbryio/lbry/issues/1576
|
||||
currency: string,
|
||||
address: string,
|
||||
version: string,
|
||||
}
|
||||
| {
|
||||
// We don't include a version or address in the metadata field when publishing
|
||||
amount: number,
|
||||
currency: string,
|
||||
},
|
||||
};
|
||||
|
||||
// Actual claim type has more values than this
|
||||
// Add them as they are used
|
||||
export type Claim = {
|
||||
address: string,
|
||||
amount: number,
|
||||
claim_id: string,
|
||||
claim_sequence: number,
|
||||
decoded_claim: boolean,
|
||||
depth: number,
|
||||
effective_amount: number,
|
||||
has_signature: boolean,
|
||||
height: number,
|
||||
has_signature: boolean,
|
||||
hex: string,
|
||||
name: string,
|
||||
nout: number,
|
||||
permanent_url: string,
|
||||
channel_name: ?string,
|
||||
txid: string,
|
||||
nout: number,
|
||||
signature_is_valid: boolean,
|
||||
valid_at_height: number,
|
||||
value: ?{
|
||||
publisherSignature: ?{
|
||||
certificateId: string,
|
||||
},
|
||||
stream: {
|
||||
metadata: Metadata,
|
||||
source: Source,
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
// @flow
|
||||
|
||||
export type FormikActions = {
|
||||
setSubmitting: boolean => mixed,
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
// @flow
|
||||
|
||||
export type FileInfo = {
|
||||
absolute_channel_position: ?number,
|
||||
name: string,
|
||||
channelName: ?string,
|
||||
pending?: boolean,
|
||||
channel_claim_id: string,
|
||||
file_name: string,
|
||||
download_path: string,
|
||||
value?: {
|
||||
publisherSignature: {
|
||||
certificateId: string,
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
publisherSignature: {
|
||||
certificateId: string,
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
// @flow
|
||||
/* eslint-disable no-use-before-define */
|
||||
export type GetState = () => any;
|
||||
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
||||
export type Dispatch = (action: {} | Promise<*> | Array<{}> | ThunkAction) => any; // Need to refer to ThunkAction
|
||||
/* eslint-enable */
|
|
@ -1,48 +0,0 @@
|
|||
// @flow
|
||||
|
||||
export type Status = {
|
||||
error?: {},
|
||||
is_running: boolean,
|
||||
is_first_run: boolean,
|
||||
installation_id: string,
|
||||
skipped_components: Array<string>,
|
||||
startup_status: {
|
||||
blob_manager: boolean,
|
||||
blockchain_headers: boolean,
|
||||
database: boolean,
|
||||
dht: boolean,
|
||||
exchange_rate_manager: boolean,
|
||||
file_manager: boolean,
|
||||
hash_announcer: boolean,
|
||||
payment_rate_manager: boolean,
|
||||
peer_protocol_server: boolean,
|
||||
rate_limiter: boolean,
|
||||
stream_identifier: boolean,
|
||||
upnp: boolean,
|
||||
wallet: boolean,
|
||||
},
|
||||
blob_manager: {
|
||||
finished_blobs: number,
|
||||
},
|
||||
connection_status: {
|
||||
code: string,
|
||||
message: string,
|
||||
},
|
||||
dht: {
|
||||
node_id: string,
|
||||
peers_in_routing_table: number,
|
||||
},
|
||||
hash_announcer: {
|
||||
announce_queue_size: number,
|
||||
},
|
||||
wallet?: {
|
||||
best_blockhash: string,
|
||||
blocks: number,
|
||||
blocks_behind: number,
|
||||
is_encrypted: boolean,
|
||||
is_locked: boolean,
|
||||
},
|
||||
blockchain_headers?: {
|
||||
download_progress: number,
|
||||
},
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
// @flow
|
||||
export type Transaction = {
|
||||
amount: number,
|
||||
claim_id: string,
|
||||
claim_name: string,
|
||||
fee: number,
|
||||
nout: number,
|
||||
txid: string,
|
||||
type: string,
|
||||
date: Date,
|
||||
};
|
|
@ -1,12 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>lbry.tv</title>
|
||||
<meta charset="utf-8" />
|
||||
<!-- @if TARGET='app' -->
|
||||
<title>LBRY</title>
|
||||
<!-- @endif -->
|
||||
<!-- @if TARGET='web' -->
|
||||
<title>lbry.tv</title>
|
||||
<meta property="og:url" content="https://beta.lbry.tv" />
|
||||
<meta property="og:title" content="LBRY On The Web" />
|
||||
<meta property="og:description" content="All your favorite LBRY content in your browser." />
|
||||
<meta property="og:image" content="/og.png" />
|
||||
<!-- @endif -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -56,12 +56,7 @@ let baseConfig = {
|
|||
{
|
||||
test: /\.s?css$/,
|
||||
exclude: /\.module.scss$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader',
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(png|svg|gif)$/,
|
||||
|
|
35
yarn.lock
35
yarn.lock
|
@ -3973,20 +3973,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
|
|||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
eslint-config-airbnb-base@^12.1.0:
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz#386441e54a12ccd957b0a92564a4bafebd747944"
|
||||
integrity sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA==
|
||||
dependencies:
|
||||
eslint-restricted-globals "^0.1.1"
|
||||
|
||||
eslint-config-airbnb@^16.1.0:
|
||||
version "16.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz#2546bfb02cc9fe92284bf1723ccf2e87bc45ca46"
|
||||
integrity sha512-zLyOhVWhzB/jwbz7IPSbkUuj7X2ox4PHXTcZkEmDqTvd0baJmJyuxlFPDlZOE/Y5bC+HQRaEkT3FoHo9wIdRiw==
|
||||
dependencies:
|
||||
eslint-config-airbnb-base "^12.1.0"
|
||||
|
||||
eslint-config-prettier@^2.9.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.10.0.tgz#ec07bc1d01f87d09f61d3840d112dc8a9791e30b"
|
||||
|
@ -4124,11 +4110,6 @@ eslint-plugin-standard@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c"
|
||||
integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==
|
||||
|
||||
eslint-restricted-globals@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7"
|
||||
integrity sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=
|
||||
|
||||
eslint-scope@3.7.1:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
|
||||
|
@ -4702,10 +4683,10 @@ flatten@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
|
||||
integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=
|
||||
|
||||
flow-bin@^0.94.0:
|
||||
version "0.94.0"
|
||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.94.0.tgz#b5d58fe7559705b73a18229f97edfc3ab6ffffcb"
|
||||
integrity sha512-DYF7r9CJ/AksfmmB4+q+TyLMoeQPRnqtF1Pk7KY3zgfkB/nVuA3nXyzqgsIPIvnMSiFEXQcFK4z+iPxSLckZhQ==
|
||||
flow-bin@^0.97.0:
|
||||
version "0.97.0"
|
||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.97.0.tgz#036ffcfc27503367a9d906ec9d843a0aa6f6bb83"
|
||||
integrity sha512-jXjD05gkatLuC4+e28frH1hZoRwr1iASP6oJr61Q64+kR4kmzaS+AdFBhYgoYS5kpoe4UzwDebWK8ETQFNh00w==
|
||||
|
||||
flow-typed@^2.3.0:
|
||||
version "2.5.1"
|
||||
|
@ -6475,17 +6456,17 @@ lazy-val@^1.0.3, lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#d4c7dea65f7179974e9b96c863022fe7b049ff7d:
|
||||
lbry-redux@lbryio/lbry-redux#cc42856676541120b088e4228c04246ba8ff3274:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/d4c7dea65f7179974e9b96c863022fe7b049ff7d"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/cc42856676541120b088e4228c04246ba8ff3274"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
lbryinc@lbryio/lbryinc#4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02:
|
||||
lbryinc@lbryio/lbryinc#9665f2d1c818f1a86b2e5daab642f6879746f25f:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02"
|
||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/9665f2d1c818f1a86b2e5daab642f6879746f25f"
|
||||
dependencies:
|
||||
reselect "^3.0.0"
|
||||
|
||||
|
|
Loading…
Reference in a new issue