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]
|
[ignore]
|
||||||
node_modules/
|
|
||||||
|
|
||||||
[include]
|
[include]
|
||||||
|
|
||||||
[libs]
|
[libs]
|
||||||
./flow-typed
|
./flow-typed
|
||||||
|
node_modules/lbry-redux/flow-typed/
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
export type UrlLocation = {
|
declare type UrlLocation = {
|
||||||
search: string,
|
search: string,
|
||||||
hash: string,
|
hash: string,
|
||||||
host: 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
|
// @flow
|
||||||
|
|
||||||
export type Reward = {
|
declare type Reward = {
|
||||||
created_at: string,
|
created_at: string,
|
||||||
id: number,
|
id: number,
|
||||||
reward_amount: number,
|
reward_amount: number,
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Dispatch as ReduxDispatch } from 'types/redux';
|
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import {
|
import {
|
||||||
DOWNLOADED,
|
DOWNLOADED,
|
||||||
|
@ -12,7 +11,7 @@ import {
|
||||||
SUGGESTED_FEATURED,
|
SUGGESTED_FEATURED,
|
||||||
} from 'constants/subscriptions';
|
} from 'constants/subscriptions';
|
||||||
|
|
||||||
export type Subscription = {
|
declare type Subscription = {
|
||||||
channelName: string, // @CryptoCandor,
|
channelName: string, // @CryptoCandor,
|
||||||
uri: string, // lbry://@CryptoCandor#9152f3b054f692076a6882d1b58a30e8781cc8e6
|
uri: string, // lbry://@CryptoCandor#9152f3b054f692076a6882d1b58a30e8781cc8e6
|
||||||
latest?: string, // substratum#b0ab143243020e7831fd070d9f871e1fda948620
|
latest?: string, // substratum#b0ab143243020e7831fd070d9f871e1fda948620
|
||||||
|
@ -21,26 +20,26 @@ export type Subscription = {
|
||||||
// Tracking for new content
|
// Tracking for new content
|
||||||
// i.e. If a subscription has a DOWNLOADING type, we will trigger an OS notification
|
// 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
|
// 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,
|
type: SubscriptionNotificationType,
|
||||||
uris: Array<string>,
|
uris: Array<string>,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UnreadSubscriptions = {
|
declare type UnreadSubscriptions = {
|
||||||
[string]: UnreadSubscription,
|
[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,
|
[SuggestedType]: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SubscriptionState = {
|
declare type SubscriptionState = {
|
||||||
subscriptions: Array<Subscription>,
|
subscriptions: Array<Subscription>,
|
||||||
unread: UnreadSubscriptions,
|
unread: UnreadSubscriptions,
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
|
@ -54,17 +53,17 @@ export type SubscriptionState = {
|
||||||
//
|
//
|
||||||
// Action types
|
// Action types
|
||||||
//
|
//
|
||||||
export type DoChannelSubscribe = {
|
declare type DoChannelSubscribe = {
|
||||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||||
data: Subscription,
|
data: Subscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DoChannelUnsubscribe = {
|
declare type DoChannelUnsubscribe = {
|
||||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||||
data: Subscription,
|
data: Subscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DoUpdateSubscriptionUnreads = {
|
declare type DoUpdateSubscriptionUnreads = {
|
||||||
type: ACTIONS.UPDATE_SUBSCRIPTION_UNREADS,
|
type: ACTIONS.UPDATE_SUBSCRIPTION_UNREADS,
|
||||||
data: {
|
data: {
|
||||||
channel: string,
|
channel: string,
|
||||||
|
@ -73,7 +72,7 @@ export type DoUpdateSubscriptionUnreads = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DoRemoveSubscriptionUnreads = {
|
declare type DoRemoveSubscriptionUnreads = {
|
||||||
type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS,
|
type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS,
|
||||||
data: {
|
data: {
|
||||||
channel: string,
|
channel: string,
|
||||||
|
@ -81,7 +80,7 @@ export type DoRemoveSubscriptionUnreads = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SetSubscriptionLatest = {
|
declare type SetSubscriptionLatest = {
|
||||||
type: ACTIONS.SET_SUBSCRIPTION_LATEST,
|
type: ACTIONS.SET_SUBSCRIPTION_LATEST,
|
||||||
data: {
|
data: {
|
||||||
subscription: Subscription,
|
subscription: Subscription,
|
||||||
|
@ -89,25 +88,25 @@ export type SetSubscriptionLatest = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CheckSubscriptionStarted = {
|
declare type CheckSubscriptionStarted = {
|
||||||
type: ACTIONS.CHECK_SUBSCRIPTION_STARTED,
|
type: ACTIONS.CHECK_SUBSCRIPTION_STARTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CheckSubscriptionCompleted = {
|
declare type CheckSubscriptionCompleted = {
|
||||||
type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED,
|
type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FetchedSubscriptionsSucess = {
|
declare type FetchedSubscriptionsSucess = {
|
||||||
type: ACTIONS.FETCH_SUBSCRIPTIONS_SUCCESS,
|
type: ACTIONS.FETCH_SUBSCRIPTIONS_SUCCESS,
|
||||||
data: Array<Subscription>,
|
data: Array<Subscription>,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SetViewMode = {
|
declare type SetViewMode = {
|
||||||
type: ACTIONS.SET_VIEW_MODE,
|
type: ACTIONS.SET_VIEW_MODE,
|
||||||
data: ViewMode,
|
data: ViewMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GetSuggestedSubscriptionsSuccess = {
|
declare type GetSuggestedSubscriptionsSuccess = {
|
||||||
type: ACTIONS.GET_SUGGESTED_SUBSCRIPTIONS_START,
|
type: ACTIONS.GET_SUGGESTED_SUBSCRIPTIONS_START,
|
||||||
data: SuggestedSubscriptions,
|
data: SuggestedSubscriptions,
|
||||||
};
|
};
|
|
@ -93,7 +93,6 @@
|
||||||
"electron-webpack": "^2.6.2",
|
"electron-webpack": "^2.6.2",
|
||||||
"electron-window-state": "^4.1.1",
|
"electron-window-state": "^4.1.1",
|
||||||
"eslint": "^5.15.2",
|
"eslint": "^5.15.2",
|
||||||
"eslint-config-airbnb": "^16.1.0",
|
|
||||||
"eslint-config-prettier": "^2.9.0",
|
"eslint-config-prettier": "^2.9.0",
|
||||||
"eslint-config-standard": "^12.0.0",
|
"eslint-config-standard": "^12.0.0",
|
||||||
"eslint-config-standard-jsx": "^6.0.2",
|
"eslint-config-standard-jsx": "^6.0.2",
|
||||||
|
@ -106,7 +105,7 @@
|
||||||
"eslint-plugin-promise": "^4.0.1",
|
"eslint-plugin-promise": "^4.0.1",
|
||||||
"eslint-plugin-react": "^7.7.0",
|
"eslint-plugin-react": "^7.7.0",
|
||||||
"eslint-plugin-standard": "^4.0.0",
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
"flow-bin": "^0.94.0",
|
"flow-bin": "^0.97.0",
|
||||||
"flow-typed": "^2.3.0",
|
"flow-typed": "^2.3.0",
|
||||||
"formik": "^0.10.4",
|
"formik": "^0.10.4",
|
||||||
"hast-util-sanitize": "^1.1.2",
|
"hast-util-sanitize": "^1.1.2",
|
||||||
|
@ -115,8 +114,8 @@
|
||||||
"jsmediatags": "^3.8.1",
|
"jsmediatags": "^3.8.1",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||||
"lbry-redux": "lbryio/lbry-redux#d4c7dea65f7179974e9b96c863022fe7b049ff7d",
|
"lbry-redux": "lbryio/lbry-redux#cc42856676541120b088e4228c04246ba8ff3274",
|
||||||
"lbryinc": "lbryio/lbryinc#4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02",
|
"lbryinc": "lbryio/lbryinc#9665f2d1c818f1a86b2e5daab642f6879746f25f",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"lodash-es": "^4.17.11",
|
"lodash-es": "^4.17.11",
|
||||||
|
@ -186,7 +185,7 @@
|
||||||
"yarn": "^1.3"
|
"yarn": "^1.3"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.34.0",
|
"lbrynetDaemonVersion": "0.36.0",
|
||||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
|
||||||
"lbrynetDaemonDir": "static/daemon",
|
"lbrynetDaemonDir": "static/daemon",
|
||||||
"lbrynetDaemonFileName": "lbrynet"
|
"lbrynetDaemonFileName": "lbrynet"
|
||||||
|
|
|
@ -113,7 +113,12 @@ class Button extends React.PureComponent<Props> {
|
||||||
exact
|
exact
|
||||||
to={path}
|
to={path}
|
||||||
title={title}
|
title={title}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (onClick) {
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
}}
|
||||||
className={combinedClassName}
|
className={combinedClassName}
|
||||||
activeClassName={activeClass}
|
activeClassName={activeClass}
|
||||||
>
|
>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import CardMedia from 'component/cardMedia';
|
||||||
import TruncatedText from 'component/common/truncated-text';
|
import TruncatedText from 'component/common/truncated-text';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import SubscribeButton from 'component/subscribeButton';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ type Props = {
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
totalItems: number,
|
totalItems: number,
|
||||||
size: string,
|
size: string,
|
||||||
claim: ?Claim,
|
claim: ?ChannelClaim,
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
history: { push: string => void },
|
history: { push: string => void },
|
||||||
};
|
};
|
||||||
|
@ -44,7 +43,7 @@ class ChannelTile extends React.PureComponent<Props> {
|
||||||
let subscriptionUri;
|
let subscriptionUri;
|
||||||
if (claim) {
|
if (claim) {
|
||||||
channelName = claim.name;
|
channelName = claim.name;
|
||||||
subscriptionUri = `lbry://${claim.permanent_url}`;
|
subscriptionUri = claim.permanent_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClick = () => history.push(formatLbryUriForWeb(uri));
|
const onClick = () => history.push(formatLbryUriForWeb(uri));
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { Price } from 'page/settings';
|
|
||||||
import { FormField } from './form-field';
|
import { FormField } from './form-field';
|
||||||
|
|
||||||
|
type FormPrice = {
|
||||||
|
amount: ?number,
|
||||||
|
currency: string,
|
||||||
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
price: Price,
|
price: FormPrice,
|
||||||
onChange: Price => void,
|
onChange: FormPrice => void,
|
||||||
placeholder: number,
|
placeholder: number,
|
||||||
min: number,
|
min: number,
|
||||||
disabled: boolean,
|
disabled: boolean,
|
||||||
|
@ -23,7 +27,7 @@ export class FormFieldPrice extends React.PureComponent<Props> {
|
||||||
|
|
||||||
handleAmountChange(event: SyntheticInputEvent<*>) {
|
handleAmountChange(event: SyntheticInputEvent<*>) {
|
||||||
const { price, onChange } = this.props;
|
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({
|
onChange({
|
||||||
currency: price.currency,
|
currency: price.currency,
|
||||||
amount,
|
amount,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import type { ElementRef } from 'react';
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import ReactDOMServer from 'react-dom/server';
|
import ReactDOMServer from 'react-dom/server';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
|
@ -6,24 +7,24 @@ import 'easymde/dist/easymde.min.css';
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
import { openEditorMenu, stopContextMenu } from 'util/context-menu';
|
import { openEditorMenu, stopContextMenu } from 'util/context-menu';
|
||||||
|
|
||||||
const SimpleMDE = React.lazy(() => import(
|
const SimpleMDE = React.lazy(() =>
|
||||||
/* webpackChunkName: "SimpleMDE" */
|
import(/* webpackChunkName: "SimpleMDE" */
|
||||||
'react-simplemde-editor'
|
'react-simplemde-editor')
|
||||||
));
|
);
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
name: string,
|
name: string,
|
||||||
label?: string,
|
label?: string,
|
||||||
render?: () => React.Node,
|
render?: () => React$Node,
|
||||||
prefix?: string,
|
prefix?: string,
|
||||||
postfix?: string,
|
postfix?: string,
|
||||||
error?: string | boolean,
|
error?: string | boolean,
|
||||||
helper?: string | React.Node,
|
helper?: string | React$Node,
|
||||||
type?: string,
|
type?: string,
|
||||||
onChange?: any => any,
|
onChange?: any => any,
|
||||||
defaultValue?: string | number,
|
defaultValue?: string | number,
|
||||||
placeholder?: string | number,
|
placeholder?: string | number,
|
||||||
children?: React.Node,
|
children?: React$Node,
|
||||||
stretch?: boolean,
|
stretch?: boolean,
|
||||||
affixClass?: string, // class applied to prefix/postfix label
|
affixClass?: string, // class applied to prefix/postfix label
|
||||||
firstInList?: boolean, // at the top of a list, no padding top
|
firstInList?: boolean, // at the top of a list, no padding top
|
||||||
|
@ -32,7 +33,7 @@ type Props = {
|
||||||
inputProps?: {
|
inputProps?: {
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
},
|
},
|
||||||
inputButton?: React.Node,
|
inputButton?: React$Node,
|
||||||
blockWrap: boolean,
|
blockWrap: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ export class FormField extends React.PureComponent<Props> {
|
||||||
blockWrap: true,
|
blockWrap: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
input: { current: React.ElementRef<any> };
|
input: { current: ElementRef<any> };
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -136,7 +137,7 @@ export class FormField extends React.PureComponent<Props> {
|
||||||
<div className="form-field--SimpleMDE" onContextMenu={stopContextMenu}>
|
<div className="form-field--SimpleMDE" onContextMenu={stopContextMenu}>
|
||||||
<fieldset-section>
|
<fieldset-section>
|
||||||
<label htmlFor={name}>{label}</label>
|
<label htmlFor={name}>{label}</label>
|
||||||
<Suspense fallback={<div></div>}>
|
<Suspense fallback={<div />}>
|
||||||
<SimpleMDE
|
<SimpleMDE
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
id={name}
|
id={name}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Node } from 'react';
|
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ type IconProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a react component
|
// 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;
|
const { size = 24, color = 'currentColor', ...otherProps } = props;
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React, { PureComponent, Node } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import Button from 'component/button';
|
||||||
// add props for collapsed height
|
// add props for collapsed height
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: Node | Array<Node>,
|
children: React$Node | Array<React$Node>,
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
|
|
@ -7,6 +7,9 @@ import {
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
makeSelectClaimIsPending,
|
makeSelectClaimIsPending,
|
||||||
|
makeSelectThumbnailForUri,
|
||||||
|
makeSelectTitleForUri,
|
||||||
|
makeSelectClaimIsNsfw,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||||
import { makeSelectContentPositionForUri } from 'redux/selectors/content';
|
import { makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||||
|
@ -27,6 +30,9 @@ const select = (state, props) => ({
|
||||||
position: makeSelectContentPositionForUri(props.uri)(state),
|
position: makeSelectContentPositionForUri(props.uri)(state),
|
||||||
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||||
isNew: makeSelectIsNew(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 => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim, Metadata } from 'types/claim';
|
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { normalizeURI, convertToShareLink } from 'lbry-redux';
|
import { normalizeURI, convertToShareLink } from 'lbry-redux';
|
||||||
|
@ -13,12 +12,13 @@ import { openCopyLinkMenu } from 'util/context-menu';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
import get from 'lodash.get';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: ?Claim,
|
claim: ?StreamClaim,
|
||||||
fileInfo: ?{},
|
fileInfo: ?{},
|
||||||
metadata: ?Metadata,
|
metadata: ?StreamMetadata,
|
||||||
rewardedContentClaimIds: Array<string>,
|
rewardedContentClaimIds: Array<string>,
|
||||||
obscureNsfw: boolean,
|
obscureNsfw: boolean,
|
||||||
claimIsMine: boolean,
|
claimIsMine: boolean,
|
||||||
|
@ -30,6 +30,9 @@ type Props = {
|
||||||
placeholder: boolean,
|
placeholder: boolean,
|
||||||
preventResolve: boolean,
|
preventResolve: boolean,
|
||||||
history: { push: string => void },
|
history: { push: string => void },
|
||||||
|
thumbnail: string,
|
||||||
|
title: string,
|
||||||
|
nsfw: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileCard extends React.PureComponent<Props> {
|
class FileCard extends React.PureComponent<Props> {
|
||||||
|
@ -72,6 +75,9 @@ class FileCard extends React.PureComponent<Props> {
|
||||||
isResolvingUri,
|
isResolvingUri,
|
||||||
placeholder,
|
placeholder,
|
||||||
history,
|
history,
|
||||||
|
thumbnail,
|
||||||
|
title,
|
||||||
|
nsfw,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const abandoned = !isResolvingUri && !claim && !pending && !placeholder;
|
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) {
|
if (shouldHide) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri;
|
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 isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
const height = claim && claim.height;
|
const height = claim && claim.height;
|
||||||
const handleContextMenu = event => {
|
const handleContextMenu = event => {
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
// @flow
|
// @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 React, { Fragment, PureComponent } from 'react';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
|
@ -10,13 +7,13 @@ import Expandable from 'component/expandable';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
fileInfo: FileInfo,
|
fileInfo: FileListItem,
|
||||||
metadata: Metadata,
|
metadata: StreamMetadata,
|
||||||
openFolder: string => void,
|
openFolder: string => void,
|
||||||
contentType: string,
|
contentType: string,
|
||||||
clickCommentButton: () => void,
|
clickCommentButton: () => void,
|
||||||
showSnackBar: Node => void,
|
showSnackBar: React$Node => void,
|
||||||
hasClickedComment: boolean,
|
hasClickedComment: boolean,
|
||||||
user: ?any,
|
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';
|
const mediaType = contentType || 'unknown';
|
||||||
let downloadPath =
|
let downloadPath =
|
||||||
|
@ -90,9 +87,9 @@ class FileDetails extends PureComponent<Props> {
|
||||||
{mediaType}
|
{mediaType}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{__('Language')}
|
{__('Languages')}
|
||||||
{': '}
|
{': '}
|
||||||
{language}
|
{languages ? languages.join(' ') : null}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{__('License')}
|
{__('License')}
|
||||||
|
@ -106,7 +103,11 @@ class FileDetails extends PureComponent<Props> {
|
||||||
<Button
|
<Button
|
||||||
constrict
|
constrict
|
||||||
button="link"
|
button="link"
|
||||||
onClick={() => openFolder(downloadPath)}
|
onClick={() => {
|
||||||
|
if (downloadPath) {
|
||||||
|
openFolder(downloadPath);
|
||||||
|
}
|
||||||
|
}}
|
||||||
label={downloadNote || downloadPath}
|
label={downloadNote || downloadPath}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -7,7 +6,7 @@ import ToolTip from 'component/common/tooltip';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
uri: string,
|
uri: string,
|
||||||
downloading: boolean,
|
downloading: boolean,
|
||||||
fileInfo: ?{
|
fileInfo: ?{
|
||||||
|
|
|
@ -3,13 +3,12 @@ import * as React from 'react';
|
||||||
import { buildURI, SORT_OPTIONS } from 'lbry-redux';
|
import { buildURI, SORT_OPTIONS } from 'lbry-redux';
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
import FileCard from 'component/fileCard';
|
import FileCard from 'component/fileCard';
|
||||||
import type { FileInfo } from 'types/file_info';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
hideFilter: boolean,
|
hideFilter: boolean,
|
||||||
sortByHeight?: boolean,
|
sortByHeight?: boolean,
|
||||||
claimsById: Array<{}>,
|
claimsById: Array<StreamClaim>,
|
||||||
fileInfos: Array<FileInfo>,
|
fileInfos: Array<FileListItem>,
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
page?: string,
|
page?: string,
|
||||||
setFileListSort: (?string, string) => void,
|
setFileListSort: (?string, string) => void,
|
||||||
|
@ -80,7 +79,7 @@ class FileList extends React.PureComponent<Props> {
|
||||||
return metadata.title || claimName;
|
return metadata.title || claimName;
|
||||||
} else if (value) {
|
} else if (value) {
|
||||||
// published claim
|
// published claim
|
||||||
const { title } = value.stream.metadata;
|
const { title } = value.stream;
|
||||||
return title || name;
|
return title || name;
|
||||||
}
|
}
|
||||||
// Invalid claim
|
// Invalid claim
|
||||||
|
@ -109,14 +108,11 @@ class FileList extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getChannelSignature = (fileInfo: FileInfo) => {
|
getChannelSignature = (fileInfo: { pending: boolean } & FileListItem) => {
|
||||||
if (fileInfo.pending) {
|
if (fileInfo.pending) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileInfo.value) {
|
|
||||||
return fileInfo.value.publisherSignature.certificateId;
|
|
||||||
}
|
|
||||||
return fileInfo.channel_claim_id;
|
return fileInfo.channel_claim_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,46 +1,45 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import { remote } from 'electron';
|
import { remote } from 'electron';
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import LoadingScreen from 'component/common/loading-screen';
|
import LoadingScreen from 'component/common/loading-screen';
|
||||||
import VideoViewer from 'component/viewers/videoViewer';
|
import VideoViewer from 'component/viewers/videoViewer';
|
||||||
|
|
||||||
const AudioViewer = React.lazy(() => import(
|
const AudioViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "audioViewer" */
|
import(/* webpackChunkName: "audioViewer" */
|
||||||
'component/viewers/audioViewer'
|
'component/viewers/audioViewer')
|
||||||
));
|
);
|
||||||
|
|
||||||
const DocumentViewer = React.lazy(() => import(
|
const DocumentViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "documentViewer" */
|
import(/* webpackChunkName: "documentViewer" */
|
||||||
'component/viewers/documentViewer'
|
'component/viewers/documentViewer')
|
||||||
));
|
);
|
||||||
|
|
||||||
const DocxViewer = React.lazy(() => import(
|
const DocxViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "docxViewer" */
|
import(/* webpackChunkName: "docxViewer" */
|
||||||
'component/viewers/docxViewer'
|
'component/viewers/docxViewer')
|
||||||
));
|
);
|
||||||
|
|
||||||
const HtmlViewer = React.lazy(() => import(
|
const HtmlViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "htmlViewer" */
|
import(/* webpackChunkName: "htmlViewer" */
|
||||||
'component/viewers/htmlViewer'
|
'component/viewers/htmlViewer')
|
||||||
));
|
);
|
||||||
|
|
||||||
const PdfViewer = React.lazy(() => import(
|
const PdfViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "pdfViewer" */
|
import(/* webpackChunkName: "pdfViewer" */
|
||||||
'component/viewers/pdfViewer'
|
'component/viewers/pdfViewer')
|
||||||
));
|
);
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
const ThreeViewer = React.lazy(() => import(
|
const ThreeViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "threeViewer" */
|
import(/* webpackChunkName: "threeViewer" */
|
||||||
'component/viewers/threeViewer'
|
'component/viewers/threeViewer')
|
||||||
));
|
);
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
mediaType: string,
|
mediaType: string,
|
||||||
poster?: string,
|
poster?: string,
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
source: {
|
source: {
|
||||||
stream: string => void,
|
stream: string => void,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
|
@ -119,8 +118,6 @@ class FileRender extends React.PureComponent<Props> {
|
||||||
renderViewer() {
|
renderViewer() {
|
||||||
const { source, mediaType, currentTheme, poster, claim } = this.props;
|
const { source, mediaType, currentTheme, poster, claim } = this.props;
|
||||||
|
|
||||||
console.log('mediaType', mediaType);
|
|
||||||
|
|
||||||
// Extract relevant data to render file
|
// Extract relevant data to render file
|
||||||
const { stream, fileType, contentType, downloadPath, fileName } = source;
|
const { stream, fileType, contentType, downloadPath, fileName } = source;
|
||||||
|
|
||||||
|
@ -155,11 +152,7 @@ class FileRender extends React.PureComponent<Props> {
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
audio: (
|
audio: (
|
||||||
<AudioViewer
|
<AudioViewer claim={claim} source={{ downloadPath, fileName }} contentType={contentType} />
|
||||||
claim={claim}
|
|
||||||
source={{ downloadPath, fileName }}
|
|
||||||
contentType={contentType}
|
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
// Add routes to viewer...
|
// Add routes to viewer...
|
||||||
};
|
};
|
||||||
|
@ -182,7 +175,7 @@ class FileRender extends React.PureComponent<Props> {
|
||||||
|
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
// temp workaround to disabled paid content on 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 = __(
|
const paidMessage = __(
|
||||||
'Currently, only free content is available on lbry.tv. Try viewing it in the desktop app.'
|
'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() {
|
render() {
|
||||||
console.log('RENDER')
|
|
||||||
return (
|
return (
|
||||||
<div className="file-render">
|
<div className="file-render">
|
||||||
<React.Suspense fallback={<div></div>}>
|
<React.Suspense fallback={<div />}>{this.renderViewer()}</React.Suspense>
|
||||||
{this.renderViewer()}
|
|
||||||
</React.Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ import {
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
|
makeSelectThumbnailForUri,
|
||||||
|
makeSelectTitleForUri,
|
||||||
|
makeSelectClaimIsNsfw,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
|
@ -23,6 +26,9 @@ const select = (state, props) => ({
|
||||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||||
isNew: makeSelectIsNew(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 => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim, Metadata } from 'types/claim';
|
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import { normalizeURI, parseURI } from 'lbry-redux';
|
import { normalizeURI, parseURI } from 'lbry-redux';
|
||||||
|
@ -22,8 +21,8 @@ type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
rewardedContentClaimIds: Array<string>,
|
rewardedContentClaimIds: Array<string>,
|
||||||
claim: ?Claim,
|
claim: ?StreamClaim,
|
||||||
metadata: ?Metadata,
|
metadata: ?StreamMetadata,
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
clearPublish: () => void,
|
clearPublish: () => void,
|
||||||
updatePublishForm: ({}) => void,
|
updatePublishForm: ({}) => void,
|
||||||
|
@ -33,6 +32,9 @@ type Props = {
|
||||||
isSubscribed: boolean,
|
isSubscribed: boolean,
|
||||||
isNew: boolean,
|
isNew: boolean,
|
||||||
history: { push: string => void },
|
history: { push: string => void },
|
||||||
|
thumbnail: ?string,
|
||||||
|
title: ?string,
|
||||||
|
nsfw: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileTile extends React.PureComponent<Props> {
|
class FileTile extends React.PureComponent<Props> {
|
||||||
|
@ -93,6 +95,9 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
displayHiddenMessage,
|
displayHiddenMessage,
|
||||||
size,
|
size,
|
||||||
history,
|
history,
|
||||||
|
thumbnail,
|
||||||
|
title,
|
||||||
|
nsfw,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!claim && isResolvingUri) {
|
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) {
|
if (shouldHide) {
|
||||||
return displayHiddenMessage ? (
|
return displayHiddenMessage ? (
|
||||||
<span className="help">
|
<span className="help">
|
||||||
|
@ -126,9 +131,6 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
const uri = normalizeURI(this.props.uri);
|
const uri = normalizeURI(this.props.uri);
|
||||||
const isClaimed = !!claim;
|
const isClaimed = !!claim;
|
||||||
const description = isClaimed && metadata && metadata.description ? metadata.description : '';
|
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 height;
|
||||||
let name;
|
let name;
|
||||||
|
@ -211,7 +213,7 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
|
|
||||||
clearPublish(); // to remove any existing publish data
|
clearPublish(); // to remove any existing publish data
|
||||||
updatePublishForm({ name: claimName }); // to populate the name
|
updatePublishForm({ name: claimName }); // to populate the name
|
||||||
history.push('/publish');
|
history.push('/$/publish');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import {
|
||||||
makeSelectDownloadingForUri,
|
makeSelectDownloadingForUri,
|
||||||
selectSearchBarFocused,
|
selectSearchBarFocused,
|
||||||
makeSelectFirstRecommendedFileForUri,
|
makeSelectFirstRecommendedFileForUri,
|
||||||
|
makeSelectClaimIsNsfw,
|
||||||
|
makeSelectThumbnailForUri,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { selectPlayingUri, makeSelectContentPositionForUri } from 'redux/selectors/content';
|
import { selectPlayingUri, makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||||
|
@ -35,6 +37,8 @@ const select = (state, props) => ({
|
||||||
searchBarFocused: selectSearchBarFocused(state),
|
searchBarFocused: selectSearchBarFocused(state),
|
||||||
fileInfoErrors: selectFileInfoErrors(state),
|
fileInfoErrors: selectFileInfoErrors(state),
|
||||||
nextFileToPlay: makeSelectFirstRecommendedFileForUri(props.uri)(state),
|
nextFileToPlay: makeSelectFirstRecommendedFileForUri(props.uri)(state),
|
||||||
|
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||||
|
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import 'babel-polyfill';
|
import 'babel-polyfill';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import { remote } from 'electron';
|
import { remote } from 'electron';
|
||||||
|
@ -19,7 +18,7 @@ type Props = {
|
||||||
position: ?number,
|
position: ?number,
|
||||||
downloadPath: string,
|
downloadPath: string,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
onStartCb: ?() => void,
|
onStartCb: ?() => void,
|
||||||
onFinishCb: ?() => void,
|
onFinishCb: ?() => void,
|
||||||
savePosition: number => void,
|
savePosition: number => void,
|
||||||
|
@ -263,11 +262,6 @@ class MediaPlayer extends React.PureComponent<Props, State> {
|
||||||
// This files are supported using a custom viewer
|
// This files are supported using a custom viewer
|
||||||
const { mediaType, contentType } = this.props;
|
const { mediaType, contentType } = this.props;
|
||||||
|
|
||||||
console.log({
|
|
||||||
mediaType,
|
|
||||||
contentType
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
MediaPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1 ||
|
MediaPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1 ||
|
||||||
MediaPlayer.SANDBOX_TYPES.indexOf(contentType) > -1
|
MediaPlayer.SANDBOX_TYPES.indexOf(contentType) > -1
|
||||||
|
@ -362,13 +356,6 @@ class MediaPlayer extends React.PureComponent<Props, State> {
|
||||||
const isPlayableType = this.playableType();
|
const isPlayableType = this.playableType();
|
||||||
const { isLoading, loadingStatus } = this.showLoadingScreen(isFileType, isPlayableType);
|
const { isLoading, loadingStatus } = this.showLoadingScreen(isFileType, isPlayableType);
|
||||||
|
|
||||||
console.log({
|
|
||||||
mediaType,
|
|
||||||
fileSource,
|
|
||||||
isFileReady,
|
|
||||||
isFileType
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{loadingStatus && <LoadingScreen status={loadingStatus} spinner={isLoading} />}
|
{loadingStatus && <LoadingScreen status={loadingStatus} spinner={isLoading} />}
|
||||||
|
|
|
@ -3,14 +3,13 @@ import * as PAGES from 'constants/pages';
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import LoadingScreen from 'component/common/loading-screen';
|
import LoadingScreen from 'component/common/loading-screen';
|
||||||
import PlayButton from './internal/play-button';
|
import PlayButton from './internal/play-button';
|
||||||
|
|
||||||
const Player = React.lazy(() => import(
|
const Player = React.lazy(() =>
|
||||||
/* webpackChunkName: "player-legacy" */
|
import(/* webpackChunkName: "player-legacy" */
|
||||||
'./internal/player'
|
'./internal/player')
|
||||||
));
|
);
|
||||||
|
|
||||||
const SPACE_BAR_KEYCODE = 32;
|
const SPACE_BAR_KEYCODE = 32;
|
||||||
|
|
||||||
|
@ -27,10 +26,6 @@ type Props = {
|
||||||
fileInfoErrors: ?{
|
fileInfoErrors: ?{
|
||||||
[string]: boolean,
|
[string]: boolean,
|
||||||
},
|
},
|
||||||
metadata: ?{
|
|
||||||
nsfw: boolean,
|
|
||||||
thumbnail: string,
|
|
||||||
},
|
|
||||||
autoplay: boolean,
|
autoplay: boolean,
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
isDownloading: boolean,
|
isDownloading: boolean,
|
||||||
|
@ -38,7 +33,7 @@ type Props = {
|
||||||
contentType: string,
|
contentType: string,
|
||||||
changeVolume: number => void,
|
changeVolume: number => void,
|
||||||
volume: number,
|
volume: number,
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
uri: string,
|
uri: string,
|
||||||
savePosition: (string, string, number) => void,
|
savePosition: (string, string, number) => void,
|
||||||
position: ?number,
|
position: ?number,
|
||||||
|
@ -52,6 +47,8 @@ type Props = {
|
||||||
navigate: (string, {}) => void,
|
navigate: (string, {}) => void,
|
||||||
costInfo: ?{ cost: number },
|
costInfo: ?{ cost: number },
|
||||||
insufficientCredits: boolean,
|
insufficientCredits: boolean,
|
||||||
|
nsfw: boolean,
|
||||||
|
thumbnail: ?string,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileViewer extends React.PureComponent<Props> {
|
class FileViewer extends React.PureComponent<Props> {
|
||||||
|
@ -135,9 +132,9 @@ class FileViewer extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAutoplay = (props: 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) {
|
if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) {
|
||||||
this.playContent();
|
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 { claimRewards } = this.props;
|
||||||
const { name, claim_id: claimId, txid, nout } = claim;
|
const { name, claim_id: claimId, txid, nout } = claim;
|
||||||
|
|
||||||
|
@ -214,7 +211,6 @@ class FileViewer extends React.PureComponent<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
metadata,
|
|
||||||
isLoading,
|
isLoading,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
playingUri,
|
playingUri,
|
||||||
|
@ -230,19 +226,21 @@ class FileViewer extends React.PureComponent<Props> {
|
||||||
obscureNsfw,
|
obscureNsfw,
|
||||||
mediaType,
|
mediaType,
|
||||||
insufficientCredits,
|
insufficientCredits,
|
||||||
|
thumbnail,
|
||||||
|
nsfw,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const isPlaying = playingUri === uri;
|
const isPlaying = playingUri === uri;
|
||||||
|
let isReadyToPlay = false;
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
const isReadyToPlay = fileInfo && fileInfo.download_path && fileInfo.written_bytes > 0;
|
isReadyToPlay = fileInfo && fileInfo.download_path && fileInfo.written_bytes > 0;
|
||||||
// @endif
|
// @endif
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
// try to play immediately on web, we don't need to call file_list since we are streaming from reflector
|
// try to play immediately on web, we don't need to call file_list since we are streaming from reflector
|
||||||
// $FlowFixMe
|
isReadyToPlay = isPlaying;
|
||||||
const isReadyToPlay = isPlaying;
|
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
const shouldObscureNsfw = obscureNsfw && metadata && metadata.nsfw;
|
const shouldObscureNsfw = obscureNsfw && nsfw;
|
||||||
let loadStatusMessage = '';
|
let loadStatusMessage = '';
|
||||||
|
|
||||||
if (fileInfo && fileInfo.completed && (!fileInfo.download_path || !fileInfo.written_bytes)) {
|
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!');
|
loadStatusMessage = __('Downloading stream... not long left now!');
|
||||||
}
|
}
|
||||||
|
|
||||||
const poster = metadata && metadata.thumbnail;
|
|
||||||
const layoverClass = classnames('content__cover', {
|
const layoverClass = classnames('content__cover', {
|
||||||
'card__media--nsfw': shouldObscureNsfw,
|
'card__media--nsfw': shouldObscureNsfw,
|
||||||
'card__media--disabled': insufficientCredits,
|
'card__media--disabled': insufficientCredits,
|
||||||
});
|
});
|
||||||
|
|
||||||
const layoverStyle =
|
const layoverStyle =
|
||||||
!shouldObscureNsfw && poster ? { backgroundImage: `url("${poster}")` } : {};
|
!shouldObscureNsfw && thumbnail ? { backgroundImage: `url("${thumbnail}")` } : {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames('video', {}, className)}>
|
<div className={classnames('video', {}, className)}>
|
||||||
|
@ -273,10 +270,10 @@ class FileViewer extends React.PureComponent<Props> {
|
||||||
<LoadingScreen status={loadStatusMessage} />
|
<LoadingScreen status={loadStatusMessage} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Suspense fallback={<div></div>}>
|
<Suspense fallback={<div />}>
|
||||||
<Player
|
<Player
|
||||||
fileName={fileInfo.file_name}
|
fileName={fileInfo.file_name}
|
||||||
poster={poster}
|
poster={thumbnail}
|
||||||
downloadPath={fileInfo.download_path}
|
downloadPath={fileInfo.download_path}
|
||||||
mediaType={mediaType}
|
mediaType={mediaType}
|
||||||
contentType={contentType}
|
contentType={contentType}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Reward } from 'types/reward';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import RewardLink from 'component/rewardLink';
|
import RewardLink from 'component/rewardLink';
|
||||||
import Yrbl from 'component/yrbl';
|
import Yrbl from 'component/yrbl';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -11,7 +10,7 @@ import { formatLbryUriForWeb } from 'util/uri';
|
||||||
type Props = {
|
type Props = {
|
||||||
lastViewed: number,
|
lastViewed: number,
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: ?Claim,
|
claim: ?StreamClaim,
|
||||||
selected: boolean,
|
selected: boolean,
|
||||||
onSelect?: () => void,
|
onSelect?: () => void,
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
|
@ -37,9 +36,9 @@ class NavigationHistoryItem extends React.PureComponent<Props> {
|
||||||
|
|
||||||
let name;
|
let name;
|
||||||
let title;
|
let title;
|
||||||
if (claim && claim.value && claim.value.stream) {
|
if (claim && claim.value) {
|
||||||
({ name } = claim);
|
({ name } = claim);
|
||||||
({ title } = claim.value.stream.metadata);
|
({ title } = claim.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigatePath = formatLbryUriForWeb(uri);
|
const navigatePath = formatLbryUriForWeb(uri);
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { buildURI } from 'lbry-redux';
|
import { buildURI } from 'lbry-redux';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: ?string,
|
uri: ?string,
|
||||||
myClaimForUri: ?Claim,
|
myClaimForUri: ?StreamClaim,
|
||||||
isStillEditing: boolean,
|
isStillEditing: boolean,
|
||||||
onEditMyClaim: (any, string) => void,
|
onEditMyClaim: (any, string) => void,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import type { PublishParams, UpdatePublishFormData } from 'redux/reducers/publish';
|
|
||||||
import { COPYRIGHT, OTHER } from 'constants/licenses';
|
import { COPYRIGHT, OTHER } from 'constants/licenses';
|
||||||
import { CHANNEL_NEW, CHANNEL_ANONYMOUS, MINIMUM_PUBLISH_BID } from 'constants/claim';
|
import { CHANNEL_NEW, CHANNEL_ANONYMOUS, MINIMUM_PUBLISH_BID } from 'constants/claim';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
|
@ -40,7 +38,7 @@ type Props = {
|
||||||
nameError: ?string,
|
nameError: ?string,
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
winningBidForClaimUri: number,
|
winningBidForClaimUri: number,
|
||||||
myClaimForUri: ?Claim,
|
myClaimForUri: ?StreamClaim,
|
||||||
licenseType: string,
|
licenseType: string,
|
||||||
otherLicenseDescription: ?string,
|
otherLicenseDescription: ?string,
|
||||||
licenseUrl: ?string,
|
licenseUrl: ?string,
|
||||||
|
@ -232,12 +230,6 @@ class PublishForm extends React.PureComponent<Props> {
|
||||||
isStillEditing: this.props.isStillEditing,
|
isStillEditing: this.props.isStillEditing,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Editing a claim
|
|
||||||
if (!filePath && myClaimForUri && myClaimForUri.value) {
|
|
||||||
const { source } = myClaimForUri.value.stream;
|
|
||||||
publishParams.sources = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
publish(publishParams);
|
publish(publishParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: ?Claim,
|
claim: ?StreamClaim,
|
||||||
recommendedContent: Array<string>,
|
recommendedContent: Array<string>,
|
||||||
isSearching: boolean,
|
isSearching: boolean,
|
||||||
search: string => void,
|
search: string => void,
|
||||||
|
@ -37,12 +36,14 @@ export default class RecommendedContent extends React.PureComponent<Props> {
|
||||||
getRecommendedContent() {
|
getRecommendedContent() {
|
||||||
const { claim, search } = this.props;
|
const { claim, search } = this.props;
|
||||||
|
|
||||||
if (claim && claim.value && claim.value.stream && claim.value.stream.metadata) {
|
if (claim && claim.value && claim.value) {
|
||||||
const { title } = claim.value.stream.metadata;
|
const { title } = claim.value;
|
||||||
|
if (title) {
|
||||||
search(title);
|
search(title);
|
||||||
this.didSearch = true;
|
this.didSearch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
didSearch: ?boolean;
|
didSearch: ?boolean;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SelectChannel from './view';
|
import SelectChannel from './view';
|
||||||
import { selectBalance, selectMyChannelClaims, selectFetchingMyChannels } from 'lbry-redux';
|
import {
|
||||||
import { doFetchChannelListMine, doCreateChannel } from 'redux/actions/content';
|
selectBalance,
|
||||||
|
selectMyChannelClaims,
|
||||||
|
selectFetchingMyChannels,
|
||||||
|
doFetchChannelListMine,
|
||||||
|
doCreateChannel,
|
||||||
|
} from 'lbry-redux';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -7,7 +6,7 @@ import CopyableText from 'component/copyableText';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
onDone: () => void,
|
onDone: () => void,
|
||||||
speechShareable: boolean,
|
speechShareable: boolean,
|
||||||
isChannel: 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 { claim_id: claimId, name: claimName, channel_name: channelName, value } = claim;
|
||||||
|
|
||||||
const { speechShareable, onDone } = this.props;
|
const { speechShareable, onDone } = this.props;
|
||||||
const channelClaimId =
|
const channelClaimId = claim.signing_channel && claim.signing_channel.claim_id;
|
||||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
|
||||||
|
|
||||||
const getSpeechUri = (): string => {
|
const getSpeechUri = (): string => {
|
||||||
if (isChannel) {
|
if (isChannel) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Status } from 'types/status';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { Lbry } from 'lbry-redux';
|
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 { notifyUnlockWallet, authenticate, modal } = this.props;
|
||||||
const { launchedModal } = this.state;
|
const { launchedModal } = this.state;
|
||||||
|
|
||||||
if (status.error) {
|
if (status.connection_status.code !== 'connected') {
|
||||||
this.setState({ error: true });
|
this.setState({ error: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Transaction } from 'types/transaction';
|
|
||||||
import * as TXN_TYPES from 'constants/transaction_types';
|
import * as TXN_TYPES from 'constants/transaction_types';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Transaction } from 'types/transaction';
|
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { List } from 'react-virtualized'
|
import { List } from 'react-virtualized';
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import FileExporter from 'component/common/file-exporter';
|
import FileExporter from 'component/common/file-exporter';
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Transaction } from 'types/transaction';
|
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { buildURI } from 'lbry-redux';
|
import { buildURI } from 'lbry-redux';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
claim: Claim,
|
channelUri: ?string,
|
||||||
link: ?boolean,
|
link: ?boolean,
|
||||||
|
claim: ?StreamClaim,
|
||||||
|
channelClaim: ?ChannelClaim,
|
||||||
// Lint thinks we aren't using these, even though we are.
|
// 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?
|
// Possibly because the resolve function is an arrow function that is passed in props?
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
|
@ -32,25 +33,23 @@ class UriIndicator extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claim, link, isResolvingUri } = this.props;
|
const { link, isResolvingUri, claim } = this.props;
|
||||||
|
|
||||||
if (!claim) {
|
if (!claim) {
|
||||||
return <span className="empty">{isResolvingUri ? 'Validating...' : 'Unused'}</span>;
|
return <span className="empty">{isResolvingUri ? 'Validating...' : 'Unused'}</span>;
|
||||||
}
|
}
|
||||||
const { channel_name: channelName, signature_is_valid: signatureIsValid, value } = claim;
|
|
||||||
|
|
||||||
const channelClaimId =
|
if (!claim.signing_channel) {
|
||||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
|
||||||
|
|
||||||
if (!channelName) {
|
|
||||||
return <span className="channel-name">Anonymous</span>;
|
return <span className="channel-name">Anonymous</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { name, claim_id: claimId } = claim.signing_channel;
|
||||||
let channelLink;
|
let channelLink;
|
||||||
if (signatureIsValid) {
|
if (claim.is_channel_signature_valid) {
|
||||||
channelLink = link ? buildURI({ channelName, claimId: channelClaimId }) : false;
|
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) {
|
if (!channelLink) {
|
||||||
return inner;
|
return inner;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -15,18 +13,7 @@ import styles from './audioViewer.module.scss';
|
||||||
|
|
||||||
const isButterchurnSupported = detectButterchurnSupport();
|
const isButterchurnSupported = detectButterchurnSupport();
|
||||||
|
|
||||||
const EQ_BANDS_SIMPLE = [
|
const EQ_BANDS_SIMPLE = [55, 150, 250, 400, 500, 1000, 2000, 4000, 8000, 16000];
|
||||||
55,
|
|
||||||
150,
|
|
||||||
250,
|
|
||||||
400,
|
|
||||||
500,
|
|
||||||
1000,
|
|
||||||
2000,
|
|
||||||
4000,
|
|
||||||
8000,
|
|
||||||
16000,
|
|
||||||
]
|
|
||||||
/*
|
/*
|
||||||
const EQ_LOWSHELF = EQ_BANDS_SIMPLE.shift();
|
const EQ_LOWSHELF = EQ_BANDS_SIMPLE.shift();
|
||||||
const EQ_HIGHSHELF = EQ_BANDS_SIMPLE.pop();
|
const EQ_HIGHSHELF = EQ_BANDS_SIMPLE.pop();
|
||||||
|
@ -41,15 +28,15 @@ const eqFilters = EQ.map(function(band) {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type Props = {
|
// type Props = {
|
||||||
source: {
|
// source: {
|
||||||
downloadPath: string,
|
// downloadPath: string,
|
||||||
fileName: string,
|
// fileName: string,
|
||||||
},
|
// },
|
||||||
contentType: string,
|
// contentType: string,
|
||||||
poster?: string,
|
// poster?: string,
|
||||||
claim: Claim,
|
// claim: StreamClaim,
|
||||||
};
|
// };
|
||||||
|
|
||||||
const presets = [
|
const presets = [
|
||||||
require('butterchurn-presets/presets/converted/Flexi - when monopolies were the future [simple warp + non-reactive moebius].json'),
|
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'),
|
require('butterchurn-presets/presets/converted/Zylot - Crosshair Dimension (Light of Ages).json'),
|
||||||
];
|
];
|
||||||
|
|
||||||
class AudioVideoViewer extends React.PureComponent<Props> {
|
class AudioVideoViewer extends React.PureComponent {
|
||||||
audioNode: ?HTMLAudioElement;
|
// audioNode: ?HTMLAudioElement;
|
||||||
player: ?{ dispose: () => void };
|
// player: ?{ dispose: () => void };
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
playing: false,
|
playing: false,
|
||||||
|
@ -107,12 +94,16 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
audioSource.connect(audioContext.destination);
|
audioSource.connect(audioContext.destination);
|
||||||
|
|
||||||
if (isButterchurnSupported) {
|
if (isButterchurnSupported) {
|
||||||
const visualizer = me.visualizer = butterchurn.createVisualizer(audioContext, me.canvasNode, {
|
const visualizer = (me.visualizer = butterchurn.createVisualizer(
|
||||||
|
audioContext,
|
||||||
|
me.canvasNode,
|
||||||
|
{
|
||||||
height: canvasHeight,
|
height: canvasHeight,
|
||||||
width: canvasWidth,
|
width: canvasWidth,
|
||||||
pixelRatio: window.devicePixelRatio || 1,
|
pixelRatio: window.devicePixelRatio || 1,
|
||||||
textureRatio: 1,
|
textureRatio: 1,
|
||||||
});
|
}
|
||||||
|
));
|
||||||
|
|
||||||
visualizer.connectAudio(audioSource);
|
visualizer.connectAudio(audioSource);
|
||||||
visualizer.loadPreset(presets[Math.floor(Math.random() * presets.length)], 2.0);
|
visualizer.loadPreset(presets[Math.floor(Math.random() * presets.length)], 2.0);
|
||||||
|
@ -123,7 +114,7 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
if (me.state.enableMilkdrop === true) {
|
if (me.state.enableMilkdrop === true) {
|
||||||
visualizer.render();
|
visualizer.render();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
me._frameCycle();
|
me._frameCycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +136,7 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
jsmediatags.Config.setDisallowedXhrHeaders(['If-Modified-Since', 'Range']);
|
jsmediatags.Config.setDisallowedXhrHeaders(['If-Modified-Since', 'Range']);
|
||||||
jsmediatags.read(path, {
|
jsmediatags.read(path, {
|
||||||
onSuccess: function(result) {
|
onSuccess: function(result) {
|
||||||
const {
|
const { album, artist, title, picture } = result.tags;
|
||||||
album,
|
|
||||||
artist,
|
|
||||||
title,
|
|
||||||
picture
|
|
||||||
} = result.tags;
|
|
||||||
|
|
||||||
if (picture) {
|
if (picture) {
|
||||||
const byteArray = new Uint8Array(picture.data);
|
const byteArray = new Uint8Array(picture.data);
|
||||||
|
@ -169,7 +155,7 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
},
|
},
|
||||||
onError: function(error) {
|
onError: function(error) {
|
||||||
console.log(':(', error.type, error.info);
|
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 path = `https://api.lbry.tv/content/claims/${claim.name}/${claim.claim_id}/stream.mp4`;
|
||||||
|
|
||||||
const playButton = (
|
const playButton = (
|
||||||
<div onClick={()=>{
|
<div
|
||||||
|
onClick={() => {
|
||||||
const audioNode = this.audioNode;
|
const audioNode = this.audioNode;
|
||||||
if (audioNode.paused) {
|
if (audioNode.paused) {
|
||||||
audioNode.play();
|
audioNode.play();
|
||||||
} else {
|
} else {
|
||||||
audioNode.pause();
|
audioNode.pause();
|
||||||
}
|
}
|
||||||
}} className={playing ? styles.playButtonPause : styles.playButtonPlay}></div>
|
}}
|
||||||
|
className={playing ? styles.playButtonPause : styles.playButtonPlay}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
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 className={enableMilkdrop ? styles.containerWithMilkdrop : styles.container}>
|
||||||
<div style={{ position: 'absolute', top: 0, right: 0 }}>
|
<div style={{ position: 'absolute', top: 0, right: 0 }}>
|
||||||
<Tooltip onComponent body={__('Toggle Visualizer')}>
|
<Tooltip onComponent body={__('Toggle Visualizer')}>
|
||||||
|
@ -226,9 +220,12 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get new preset
|
// 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>
|
</Tooltip>
|
||||||
|
@ -251,24 +248,56 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</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={styles.infoContainer}>
|
||||||
<div className={renderArt ? styles.infoArtContainer : styles.infoArtContainerHidden}>
|
<div className={renderArt ? styles.infoArtContainer : styles.infoArtContainerHidden}>
|
||||||
<img className={styles.infoArtImage} ref={node => (this.artNode = node)} />
|
<img className={styles.infoArtImage} ref={node => (this.artNode = node)} />
|
||||||
{renderArt && playButton}
|
{renderArt && playButton}
|
||||||
</div>
|
</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}>
|
<div className={renderArt ? styles.songDetails : styles.songDetailsNoArt}>
|
||||||
{artist && <div className={styles.detailsLineArtist}><Button icon={ICONS.MUSIC_ARTIST} className={styles.detailsIconArtist} />{artist}</div>}
|
{artist && (
|
||||||
{title && <div className={styles.detailsLineSong}><Button icon={ICONS.MUSIC_SONG} className={styles.detailsIconSong} />{title}</div>}
|
<div className={styles.detailsLineArtist}>
|
||||||
{album && <div className={styles.detailsLineAlbum}><Button icon={ICONS.MUSIC_ALBUM} className={styles.detailsIconAlbum} />{album}</div>}
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!renderArt && <div className={styles.playButtonDetachedContainer}>{playButton}</div>}
|
{!renderArt && <div className={styles.playButtonDetachedContainer}>{playButton}</div>}
|
||||||
</div>
|
</div>
|
||||||
<canvas ref={node => (this.canvasNode = node)} className={enableMilkdrop ? styles.milkdrop : styles.milkdropDisabled} />
|
<canvas
|
||||||
<audio ref={node => (this.audioNode = node)} src={path} style={{ position: 'absolute', top: '-100px' }} onPlay={()=>this.setState({ playing: true })} onPause={()=>this.setState({ playing: false })} />
|
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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ import React, { Suspense } from 'react';
|
||||||
import LoadingScreen from 'component/common/loading-screen';
|
import LoadingScreen from 'component/common/loading-screen';
|
||||||
import MarkdownPreview from 'component/common/markdown-preview';
|
import MarkdownPreview from 'component/common/markdown-preview';
|
||||||
|
|
||||||
const LazyCodeViewer = React.lazy(() => import(
|
const LazyCodeViewer = React.lazy<*>(() =>
|
||||||
/* webpackChunkName: "codeViewer" */
|
import(/* webpackChunkName: "codeViewer" */
|
||||||
'component/viewers/codeViewer'
|
'component/viewers/codeViewer')
|
||||||
));
|
);
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
theme: string,
|
theme: string,
|
||||||
|
@ -84,7 +84,7 @@ class DocumentViewer extends React.PureComponent<Props, State> {
|
||||||
<div className="file-render__viewer document-viewer">
|
<div className="file-render__viewer document-viewer">
|
||||||
{loading && !error && <LoadingScreen status={loadingMessage} spinner />}
|
{loading && !error && <LoadingScreen status={loadingMessage} spinner />}
|
||||||
{error && <LoadingScreen status={errorMessage} spinner={!error} />}
|
{error && <LoadingScreen status={errorMessage} spinner={!error} />}
|
||||||
{isReady && <Suspense fallback={<div></div>}>{this.renderDocument()}</Suspense>}
|
{isReady && <Suspense fallback={<div />}>{this.renderDocument()}</Suspense>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import { stopContextMenu } from 'util/context-menu';
|
import { stopContextMenu } from 'util/context-menu';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
@ -14,7 +13,7 @@ type Props = {
|
||||||
},
|
},
|
||||||
contentType: string,
|
contentType: string,
|
||||||
poster?: string,
|
poster?: string,
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
};
|
};
|
||||||
|
|
||||||
class AudioVideoViewer extends React.PureComponent<Props> {
|
class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
|
@ -53,8 +52,10 @@ class AudioVideoViewer extends React.PureComponent<Props> {
|
||||||
'video.js').then(videojs => {
|
'video.js').then(videojs => {
|
||||||
if (videojs.__esModule) {
|
if (videojs.__esModule) {
|
||||||
videojs = videojs.default;
|
videojs = videojs.default;
|
||||||
}
|
|
||||||
this.player = videojs(this.videoNode, videoJsOptions, () => {});
|
this.player = videojs(this.videoNode, videoJsOptions, () => {});
|
||||||
|
} else {
|
||||||
|
throw Error('Unable to import and use videojs');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { FormField, Form } from 'component/common/form';
|
import { FormField, Form } from 'component/common/form';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
title: string,
|
title: string,
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
isPending: boolean,
|
isPending: boolean,
|
||||||
sendSupport: (number, string, string) => void,
|
sendSupport: (number, string, string) => void,
|
||||||
onCancel: () => void,
|
onCancel: () => void,
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FilePrice from 'component/filePrice';
|
import FilePrice from 'component/filePrice';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
import type { Metadata } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
closeModal: () => void,
|
closeModal: () => void,
|
||||||
loadVideo: string => void,
|
loadVideo: string => void,
|
||||||
uri: string,
|
uri: string,
|
||||||
cancelPurchase: () => void,
|
cancelPurchase: () => void,
|
||||||
metadata: Metadata,
|
metadata: StreamMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModalAffirmPurchase extends React.PureComponent<Props> {
|
class ModalAffirmPurchase extends React.PureComponent<Props> {
|
||||||
|
@ -42,7 +41,7 @@ class ModalAffirmPurchase extends React.PureComponent<Props> {
|
||||||
>
|
>
|
||||||
<section className="card__content">
|
<section className="card__content">
|
||||||
<p>
|
<p>
|
||||||
{__('This will purchase')} <strong>{`"${title}"`}</strong> {__('for')}{' '}
|
{__('This will purchase')} <strong>{title ? `"${title}"` : uri}</strong> {__('for')}{' '}
|
||||||
<strong>
|
<strong>
|
||||||
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
|
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
|
||||||
</strong>{' '}
|
</strong>{' '}
|
||||||
|
|
|
@ -1,21 +1,15 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doHideModal } from 'redux/actions/app';
|
import { doHideModal } from 'redux/actions/app';
|
||||||
import { doUploadThumbnail, doUpdatePublishForm } from 'redux/actions/publish';
|
import { doUploadThumbnail, doUpdatePublishForm } from 'redux/actions/publish';
|
||||||
import { selectPublishFormValues } from 'redux/selectors/publish';
|
|
||||||
import ModalConfirmThumbnailUpload from './view';
|
import ModalConfirmThumbnailUpload from './view';
|
||||||
|
|
||||||
const select = state => {
|
|
||||||
const publishState = selectPublishFormValues(state);
|
|
||||||
return { nsfw: publishState.nsfw };
|
|
||||||
};
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
closeModal: () => dispatch(doHideModal()),
|
closeModal: () => dispatch(doHideModal()),
|
||||||
upload: (path, nsfw = false) => dispatch(doUploadThumbnail(path, nsfw)),
|
upload: path => dispatch(doUploadThumbnail(path)),
|
||||||
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
|
updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
null,
|
||||||
perform
|
perform
|
||||||
)(ModalConfirmThumbnailUpload);
|
)(ModalConfirmThumbnailUpload);
|
||||||
|
|
|
@ -4,23 +4,22 @@ import { Modal } from 'modal/modal';
|
||||||
import { FormField } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
upload: (string, boolean) => void,
|
upload: string => void,
|
||||||
path: string,
|
path: string,
|
||||||
nsfw: boolean,
|
|
||||||
closeModal: () => void,
|
closeModal: () => void,
|
||||||
updatePublishForm: ({}) => void,
|
updatePublishForm: ({}) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
|
class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
|
||||||
upload() {
|
upload() {
|
||||||
const { upload, updatePublishForm, closeModal, path, nsfw } = this.props;
|
const { upload, updatePublishForm, closeModal, path } = this.props;
|
||||||
upload(path, nsfw);
|
upload(path);
|
||||||
updatePublishForm({ thumbnailPath: path });
|
updatePublishForm({ thumbnailPath: path });
|
||||||
closeModal();
|
closeModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { closeModal, path, updatePublishForm, nsfw } = this.props;
|
const { closeModal, path, updatePublishForm } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<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>
|
<p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p>
|
||||||
|
|
||||||
<blockquote>{path}</blockquote>
|
<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>
|
</section>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,8 +10,10 @@ type Props = {
|
||||||
|
|
||||||
class ModalError extends React.PureComponent<Props> {
|
class ModalError extends React.PureComponent<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) });
|
Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const { closeModal, error } = this.props;
|
const { closeModal, error } = this.props;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
import type { Metadata } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
metadata: Metadata,
|
uri: string,
|
||||||
|
metadata: StreamMetadata,
|
||||||
closeModal: () => void,
|
closeModal: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModalFileTimeout extends React.PureComponent<Props> {
|
class ModalFileTimeout extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
uri,
|
||||||
metadata: { title },
|
metadata: { title },
|
||||||
closeModal,
|
closeModal,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -26,7 +27,7 @@ class ModalFileTimeout extends React.PureComponent<Props> {
|
||||||
<p className="error-modal__error-list">
|
<p className="error-modal__error-list">
|
||||||
{__('LBRY was unable to download the stream')}:
|
{__('LBRY was unable to download the stream')}:
|
||||||
<div>
|
<div>
|
||||||
<b>{`"${title}"`}</b>
|
<b>{title ? `"${title}"` : uri}</b>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Transaction } from 'types/transaction';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modal } from 'modal/modal';
|
import { Modal } from 'modal/modal';
|
||||||
import * as txnTypes from 'constants/transaction_types';
|
import * as txnTypes from 'constants/transaction_types';
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { UrlLocation } from 'types/location';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import type { UrlLocation } from 'types/location';
|
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
@ -19,8 +17,8 @@ type Props = {
|
||||||
totalPages: number,
|
totalPages: number,
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
params: { page: number },
|
params: { page: number },
|
||||||
claim: Claim,
|
claim: ChannelClaim,
|
||||||
claimsInChannel: Array<Claim>,
|
claimsInChannel: Array<StreamClaim>,
|
||||||
channelIsMine: boolean,
|
channelIsMine: boolean,
|
||||||
fetchClaims: (string, number) => void,
|
fetchClaims: (string, number) => void,
|
||||||
history: { push: string => void },
|
history: { push: string => void },
|
||||||
|
@ -82,10 +80,10 @@ function ChannelPage(props: Props) {
|
||||||
{name}
|
{name}
|
||||||
{fetching && <BusyIndicator />}
|
{fetching && <BusyIndicator />}
|
||||||
</h1>
|
</h1>
|
||||||
<span>{`lbry://${permanentUrl}`}</span>
|
<span>{permanentUrl}</span>
|
||||||
|
|
||||||
<div className="channel-info__actions__group">
|
<div className="channel-info__actions__group">
|
||||||
<SubscribeButton uri={`lbry://${permanentUrl}`} channelName={name} />
|
<SubscribeButton uri={permanentUrl} channelName={name} />
|
||||||
<Button
|
<Button
|
||||||
button="alt"
|
button="alt"
|
||||||
icon={icons.SHARE}
|
icon={icons.SHARE}
|
||||||
|
|
|
@ -13,6 +13,9 @@ import {
|
||||||
makeSelectMetadataForUri,
|
makeSelectMetadataForUri,
|
||||||
makeSelectChannelForClaimUri,
|
makeSelectChannelForClaimUri,
|
||||||
selectBalance,
|
selectBalance,
|
||||||
|
makeSelectTitleForUri,
|
||||||
|
makeSelectThumbnailForUri,
|
||||||
|
makeSelectClaimIsNsfw,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doFetchViewCount,
|
doFetchViewCount,
|
||||||
|
@ -41,6 +44,9 @@ const select = (state, props) => ({
|
||||||
channelUri: makeSelectChannelForClaimUri(props.uri, true)(state),
|
channelUri: makeSelectChannelForClaimUri(props.uri, true)(state),
|
||||||
viewCount: makeSelectViewCountForUri(props.uri)(state),
|
viewCount: makeSelectViewCountForUri(props.uri)(state),
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
|
title: makeSelectTitleForUri(props.uri)(state),
|
||||||
|
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||||
|
nsfw: makeSelectClaimIsNsfw(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim, Metadata } from 'types/claim';
|
|
||||||
import type { FileInfo } from 'types/file_info';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
@ -22,9 +20,9 @@ import getMediaType from 'util/get-media-type';
|
||||||
import RecommendedContent from 'component/recommendedContent';
|
import RecommendedContent from 'component/recommendedContent';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
fileInfo: FileInfo,
|
fileInfo: FileListItem,
|
||||||
metadata: Metadata,
|
metadata: StreamMetadata,
|
||||||
contentType: string,
|
contentType: string,
|
||||||
uri: string,
|
uri: string,
|
||||||
rewardedContentClaimIds: Array<string>,
|
rewardedContentClaimIds: Array<string>,
|
||||||
|
@ -43,6 +41,9 @@ type Props = {
|
||||||
markSubscriptionRead: (string, string) => void,
|
markSubscriptionRead: (string, string) => void,
|
||||||
fetchViewCount: string => void,
|
fetchViewCount: string => void,
|
||||||
balance: number,
|
balance: number,
|
||||||
|
title: string,
|
||||||
|
thumbnail: ?string,
|
||||||
|
nsfw: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilePage extends React.Component<Props> {
|
class FilePage extends React.Component<Props> {
|
||||||
|
@ -137,21 +138,18 @@ class FilePage extends React.Component<Props> {
|
||||||
channelUri,
|
channelUri,
|
||||||
viewCount,
|
viewCount,
|
||||||
balance,
|
balance,
|
||||||
|
title,
|
||||||
|
thumbnail,
|
||||||
|
nsfw,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// File info
|
// File info
|
||||||
const { title, thumbnail } = metadata;
|
|
||||||
const {height, channel_name: channelName} = claim;
|
const {height, channel_name: channelName} = claim;
|
||||||
const {PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES} = FilePage;
|
const {PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES} = FilePage;
|
||||||
const isRewardContent = (rewardedContentClaimIds || []).includes(claim.claim_id);
|
const isRewardContent = (rewardedContentClaimIds || []).includes(claim.claim_id);
|
||||||
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
|
const shouldObscureThumbnail = obscureNsfw && nsfw;
|
||||||
const fileName = fileInfo ? fileInfo.file_name : null;
|
const fileName = fileInfo ? fileInfo.file_name : null;
|
||||||
const mediaType = getMediaType(contentType, fileName);
|
const mediaType = getMediaType(contentType, fileName);
|
||||||
console.log({
|
|
||||||
mediaType,
|
|
||||||
contentType,
|
|
||||||
fileName,
|
|
||||||
});
|
|
||||||
const showFile =
|
const showFile =
|
||||||
PLAYABLE_MEDIA_TYPES.includes(mediaType) || PREVIEW_MEDIA_TYPES.includes(mediaType);
|
PLAYABLE_MEDIA_TYPES.includes(mediaType) || PREVIEW_MEDIA_TYPES.includes(mediaType);
|
||||||
|
|
||||||
|
@ -231,7 +229,7 @@ class FilePage extends React.Component<Props> {
|
||||||
// tooltip="bottom"
|
// tooltip="bottom"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{metadata.nsfw && <div className="badge badge--nsfw">NSFW</div>}
|
{nsfw && <div className="badge badge--nsfw">MATURE</div>}
|
||||||
<FilePrice badge uri={normalizeURI(uri)} />
|
<FilePrice badge uri={normalizeURI(uri)} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import FileList from 'component/fileList';
|
import FileList from 'component/fileList';
|
||||||
|
@ -7,7 +6,7 @@ import Page from 'component/page';
|
||||||
import { PAGES } from 'lbry-redux';
|
import { PAGES } from 'lbry-redux';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claims: Array<Claim>,
|
claims: Array<StreamClaim>,
|
||||||
checkPendingPublishes: () => void,
|
checkPendingPublishes: () => void,
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
|
|
|
@ -6,7 +6,6 @@ import RewardTile from 'component/rewardTile';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { Reward } from 'types/reward';
|
|
||||||
import { rewards as REWARD_TYPES } from 'lbryinc';
|
import { rewards as REWARD_TYPES } from 'lbryinc';
|
||||||
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { UrlLocation } from 'types/location';
|
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React, { useEffect, Fragment } from 'react';
|
import React, { useEffect, Fragment } from 'react';
|
||||||
import { isURIValid, normalizeURI, parseURI } from 'lbry-redux';
|
import { isURIValid, normalizeURI, parseURI } from 'lbry-redux';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import Page from 'component/page';
|
||||||
import FileSelector from 'component/common/file-selector';
|
import FileSelector from 'component/common/file-selector';
|
||||||
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
import UnsupportedOnWeb from 'component/common/unsupported-on-web';
|
||||||
|
|
||||||
export type Price = {
|
type Price = {
|
||||||
currency: string,
|
currency: string,
|
||||||
amount: number,
|
amount: number,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { UrlLocation } from 'types/location';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import ChannelPage from 'page/channel';
|
import ChannelPage from 'page/channel';
|
||||||
import FilePage from 'page/file';
|
import FilePage from 'page/file';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
resolveUri: string => void,
|
resolveUri: string => void,
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: Claim,
|
claim: StreamClaim,
|
||||||
totalPages: number,
|
totalPages: number,
|
||||||
location: UrlLocation,
|
location: UrlLocation,
|
||||||
blackListedOutpoints: Array<{
|
blackListedOutpoints: Array<{
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { ViewMode } from 'types/subscription';
|
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import { VIEW_ALL, VIEW_LATEST_FIRST } from 'constants/subscriptions';
|
import { VIEW_ALL, VIEW_LATEST_FIRST } from 'constants/subscriptions';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -19,7 +17,7 @@ type Props = {
|
||||||
viewMode: ViewMode,
|
viewMode: ViewMode,
|
||||||
doSetViewMode: ViewMode => void,
|
doSetViewMode: ViewMode => void,
|
||||||
hasSubscriptions: boolean,
|
hasSubscriptions: boolean,
|
||||||
subscriptions: Array<{ uri: string, ...Claim }>,
|
subscriptions: Array<{ uri: string, ...StreamClaim }>,
|
||||||
autoDownload: boolean,
|
autoDownload: boolean,
|
||||||
onChangeAutoDownload: (SyntheticInputEvent<*>) => void,
|
onChangeAutoDownload: (SyntheticInputEvent<*>) => void,
|
||||||
unreadSubscriptions: Array<{ channel: string, uris: Array<string> }>,
|
unreadSubscriptions: Array<{ channel: string, uris: Array<string> }>,
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { ViewMode } from 'types/subscription';
|
|
||||||
import type { Claim } from 'types/claim';
|
|
||||||
import * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
|
@ -13,7 +11,7 @@ type Props = {
|
||||||
channel: string,
|
channel: string,
|
||||||
uris: Array<string>,
|
uris: Array<string>,
|
||||||
}>,
|
}>,
|
||||||
allSubscriptions: Array<{ uri: string, ...Claim }>,
|
allSubscriptions: Array<{ uri: string, ...StreamClaim }>,
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
autoDownload: boolean,
|
autoDownload: boolean,
|
||||||
viewMode: ViewMode,
|
viewMode: ViewMode,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Dispatch, GetState } from 'types/redux';
|
|
||||||
import * as NOTIFICATION_TYPES from 'constants/subscriptions';
|
import * as NOTIFICATION_TYPES from 'constants/subscriptions';
|
||||||
import { PAGE_SIZE } from 'constants/claim';
|
import { PAGE_SIZE } from 'constants/claim';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
|
@ -25,9 +24,7 @@ import {
|
||||||
creditsToString,
|
creditsToString,
|
||||||
doError,
|
doError,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import {
|
import { makeSelectCostInfoForUri } from 'lbryinc';
|
||||||
makeSelectCostInfoForUri,
|
|
||||||
} from 'lbryinc';
|
|
||||||
import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
import { formatLbryUriForWeb } from 'util/uri';
|
import { formatLbryUriForWeb } from 'util/uri';
|
||||||
|
@ -305,9 +302,12 @@ export function doFetchClaimsByChannel(
|
||||||
data: { uri, page },
|
data: { uri, page },
|
||||||
});
|
});
|
||||||
|
|
||||||
Lbry.claim_list_by_channel({ uri, page, page_size: pageSize }).then(result => {
|
// TODO: can we keep uri?
|
||||||
const claimResult = result[uri] || {};
|
// claim_search should accept a uri (this allows for fetching vanity channel content)
|
||||||
const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult;
|
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 (claimsInChannel && claimsInChannel.length) {
|
||||||
if (page === 1) {
|
if (page === 1) {
|
||||||
|
@ -319,7 +319,7 @@ export function doFetchClaimsByChannel(
|
||||||
uri: buildURI(
|
uri: buildURI(
|
||||||
{
|
{
|
||||||
contentName: latest.channel_name,
|
contentName: latest.channel_name,
|
||||||
claimId: latest.value.publisherSignature.certificateId,
|
claimId: latest.claim_id,
|
||||||
},
|
},
|
||||||
false
|
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) {
|
export function savePosition(claimId: string, outpoint: string, position: number) {
|
||||||
return (dispatch: Dispatch) => {
|
return (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
// @flow
|
// @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 { CC_LICENSES, COPYRIGHT, OTHER, NONE, PUBLIC_DOMAIN } from 'constants/licenses';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import {
|
import {
|
||||||
|
@ -29,9 +22,7 @@ import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH };
|
export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
|
||||||
|
|
||||||
export const doResetThumbnailStatus = () => (dispatch: Dispatch): Promise<Action> => {
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||||
data: {
|
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 });
|
dispatch({ type: ACTIONS.CLEAR_PUBLISH });
|
||||||
return dispatch(doResetThumbnailStatus());
|
return dispatch(doResetThumbnailStatus());
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => (
|
export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => (
|
||||||
dispatch: Dispatch
|
dispatch: Dispatch
|
||||||
): UpdatePublishFormAction =>
|
) =>
|
||||||
dispatch(
|
dispatch({
|
||||||
({
|
|
||||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||||
data: { ...publishFormValue },
|
data: { ...publishFormValue },
|
||||||
}: UpdatePublishFormAction)
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: Dispatch) => {
|
export const doUploadThumbnail = (filePath: string) => (dispatch: Dispatch) => {
|
||||||
const thumbnail = fs.readFileSync(filePath);
|
const thumbnail = fs.readFileSync(filePath);
|
||||||
const fileExt = path.extname(filePath);
|
const fileExt = path.extname(filePath);
|
||||||
const fileName = path.basename(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)}` });
|
const file = new File([thumbnail], fileName, { type: `image/${fileExt.slice(1)}` });
|
||||||
data.append('name', name);
|
data.append('name', name);
|
||||||
data.append('file', file);
|
data.append('file', file);
|
||||||
data.append('nsfw', nsfw.toString());
|
|
||||||
return fetch('https://spee.ch/api/claim/publish', {
|
return fetch('https://spee.ch/api/claim/publish', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: data,
|
body: data,
|
||||||
|
@ -139,15 +128,8 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch:
|
||||||
.catch(err => uploadError(err.message));
|
.catch(err => uploadError(err.message));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) => {
|
export const doPrepareEdit = (claim: StreamClaim, uri: string) => (dispatch: Dispatch) => {
|
||||||
const {
|
const { name, amount, channel_name: channelName, value } = claim;
|
||||||
name,
|
|
||||||
amount,
|
|
||||||
channel_name: channelName,
|
|
||||||
value: {
|
|
||||||
stream: { metadata },
|
|
||||||
},
|
|
||||||
} = claim;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
author,
|
author,
|
||||||
|
@ -158,26 +140,23 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) =
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: 'LBC',
|
currency: 'LBC',
|
||||||
},
|
},
|
||||||
language,
|
languages,
|
||||||
license,
|
license,
|
||||||
licenseUrl,
|
license_url: licenseUrl,
|
||||||
nsfw,
|
|
||||||
thumbnail,
|
thumbnail,
|
||||||
title,
|
title,
|
||||||
} = metadata;
|
} = value;
|
||||||
|
|
||||||
const publishData: UpdatePublishFormData = {
|
const publishData: UpdatePublishFormData = {
|
||||||
name,
|
name,
|
||||||
channel: channelName,
|
channel: channelName,
|
||||||
bid: amount,
|
bid: amount,
|
||||||
price: { amount: fee.amount, currency: fee.currency },
|
|
||||||
contentIsFree: !fee.amount,
|
contentIsFree: !fee.amount,
|
||||||
author,
|
author,
|
||||||
description,
|
description,
|
||||||
fee,
|
fee,
|
||||||
language,
|
languages,
|
||||||
nsfw,
|
thumbnail: thumbnail ? thumbnail.url : null,
|
||||||
thumbnail,
|
|
||||||
title,
|
title,
|
||||||
uri,
|
uri,
|
||||||
uploadThumbnailStatus: thumbnail ? THUMBNAIL_STATUSES.MANUAL : undefined,
|
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: () => {}) => {
|
export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => {
|
||||||
|
dispatch({ type: ACTIONS.PUBLISH_START });
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const myChannels = selectMyChannelClaims(state);
|
const myChannels = selectMyChannelClaims(state);
|
||||||
const myClaims = selectMyClaimsWithoutChannels(state);
|
const myClaims = selectMyClaimsWithoutChannels(state);
|
||||||
|
@ -217,55 +198,63 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
|
||||||
license,
|
license,
|
||||||
licenseUrl,
|
licenseUrl,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
nsfw,
|
|
||||||
channel,
|
channel,
|
||||||
title,
|
title,
|
||||||
contentIsFree,
|
contentIsFree,
|
||||||
price,
|
fee,
|
||||||
uri,
|
uri,
|
||||||
|
nsfw,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
// get the claim id from the channel name, we will use that instead
|
// get the claim id from the channel name, we will use that instead
|
||||||
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
|
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
|
||||||
const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';
|
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: {
|
const publishPayload: {
|
||||||
name: ?string,
|
name: ?string,
|
||||||
channel_id: string,
|
channel_id?: string,
|
||||||
bid: ?number,
|
bid: number,
|
||||||
metadata: ?Metadata,
|
|
||||||
file_path?: string,
|
file_path?: string,
|
||||||
|
fee?: { amount: string, currency: string },
|
||||||
|
tags: Array<string>,
|
||||||
} = {
|
} = {
|
||||||
name,
|
name,
|
||||||
channel_id: channelId,
|
|
||||||
bid: creditsToString(bid),
|
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) {
|
if (fee) {
|
||||||
metadata.fee = {
|
publishPayload.fee = {
|
||||||
currency: fee.currency,
|
currency: fee.currency,
|
||||||
amount: creditsToString(fee.amount),
|
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;
|
if (filePath) publishPayload.file_path = filePath;
|
||||||
|
|
||||||
dispatch({ type: ACTIONS.PUBLISH_START });
|
const success = successResponse => {
|
||||||
|
|
||||||
const success = pendingClaim => {
|
|
||||||
analytics.apiLogPublish();
|
analytics.apiLogPublish();
|
||||||
|
|
||||||
|
const pendingClaim = successResponse.outputs[0];
|
||||||
const actions = [];
|
const actions = [];
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
|
@ -280,8 +269,8 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
|
||||||
const isMatch = claim => claim.claim_id === pendingClaim.claim_id;
|
const isMatch = claim => claim.claim_id === pendingClaim.claim_id;
|
||||||
const isEdit = myClaims.some(isMatch);
|
const isEdit = myClaims.some(isMatch);
|
||||||
const myNewClaims = isEdit
|
const myNewClaims = isEdit
|
||||||
? myClaims.map(claim => (isMatch(claim) ? pendingClaim.output : claim))
|
? myClaims.map(claim => (isMatch(claim) ? pendingClaim : claim))
|
||||||
: myClaims.concat(pendingClaim.output);
|
: myClaims.concat(pendingClaim);
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
||||||
|
@ -313,7 +302,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS
|
||||||
let publishCheckInterval;
|
let publishCheckInterval;
|
||||||
|
|
||||||
const checkFileList = () => {
|
const checkFileList = () => {
|
||||||
Lbry.claim_list_mine().then(claims => {
|
Lbry.claim_list().then(claims => {
|
||||||
claims.forEach(claim => {
|
claims.forEach(claim => {
|
||||||
// If it's confirmed, check if it was pending previously
|
// If it's confirmed, check if it was pending previously
|
||||||
if (claim.confirmations > 0 && pendingById[claim.claim_id]) {
|
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 it's confirmed, check if we should notify the user
|
||||||
if (selectosNotificationsEnabled(getState())) {
|
if (selectosNotificationsEnabled(getState())) {
|
||||||
const notif = new window.Notification('LBRY Publish Complete', {
|
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
|
claim.name
|
||||||
}. Click here to view it`,
|
}. Click here to view it`,
|
||||||
silent: false,
|
silent: false,
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
// @flow
|
// @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 { PAGE_SIZE } from 'constants/claim';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as SETTINGS from 'constants/settings';
|
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?
|
// 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 => {
|
claimListByChannel => {
|
||||||
const claimResult = claimListByChannel[subscriptionUri] || {};
|
const claimResult = claimListByChannel[subscriptionUri] || {};
|
||||||
const { claims_in_channel: claimsInChannel } = claimResult;
|
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 uri = buildURI({ contentName: claim.name, claimId: claim.claim_id }, true);
|
||||||
const shouldDownload =
|
const shouldDownload =
|
||||||
shouldAutoDownload &&
|
shouldAutoDownload &&
|
||||||
Boolean(
|
Boolean(downloadCount < SUBSCRIPTION_DOWNLOAD_LIMIT && !claim.value.stream.fee);
|
||||||
downloadCount < SUBSCRIPTION_DOWNLOAD_LIMIT && !claim.value.stream.metadata.fee
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the new content to the list of "un-read" subscriptions
|
// Add the new content to the list of "un-read" subscriptions
|
||||||
if (shouldNotify) {
|
if (shouldNotify) {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { buildURI } from 'lbry-redux';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
||||||
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
||||||
import type { Source } from 'types/claim';
|
|
||||||
|
|
||||||
type PublishState = {
|
type PublishState = {
|
||||||
editingURI: ?string,
|
editingURI: ?string,
|
||||||
|
@ -15,7 +14,7 @@ type PublishState = {
|
||||||
currency: string,
|
currency: string,
|
||||||
},
|
},
|
||||||
title: string,
|
title: string,
|
||||||
thumbnail: string,
|
thumbnail_url: string,
|
||||||
thumbnailPath: string,
|
thumbnailPath: string,
|
||||||
uploadThumbnailStatus: string,
|
uploadThumbnailStatus: string,
|
||||||
description: string,
|
description: string,
|
||||||
|
@ -30,60 +29,6 @@ type PublishState = {
|
||||||
licenseUrl: string,
|
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 = {
|
const defaultState: PublishState = {
|
||||||
editingURI: undefined,
|
editingURI: undefined,
|
||||||
filePath: undefined,
|
filePath: undefined,
|
||||||
|
@ -93,7 +38,7 @@ const defaultState: PublishState = {
|
||||||
currency: 'LBC',
|
currency: 'LBC',
|
||||||
},
|
},
|
||||||
title: '',
|
title: '',
|
||||||
thumbnail: '',
|
thumbnail_url: '',
|
||||||
thumbnailPath: '',
|
thumbnailPath: '',
|
||||||
uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN,
|
uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN,
|
||||||
description: '',
|
description: '',
|
||||||
|
|
|
@ -2,18 +2,6 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { VIEW_ALL } from 'constants/subscriptions';
|
import { VIEW_ALL } from 'constants/subscriptions';
|
||||||
import { handleActions } from 'util/redux-utils';
|
import { handleActions } from 'util/redux-utils';
|
||||||
import type {
|
|
||||||
SubscriptionState,
|
|
||||||
Subscription,
|
|
||||||
DoChannelSubscribe,
|
|
||||||
DoChannelUnsubscribe,
|
|
||||||
SetSubscriptionLatest,
|
|
||||||
DoUpdateSubscriptionUnreads,
|
|
||||||
DoRemoveSubscriptionUnreads,
|
|
||||||
FetchedSubscriptionsSucess,
|
|
||||||
SetViewMode,
|
|
||||||
GetSuggestedSubscriptionsSuccess,
|
|
||||||
} from 'types/subscription';
|
|
||||||
|
|
||||||
const defaultState: SubscriptionState = {
|
const defaultState: SubscriptionState = {
|
||||||
subscriptions: [],
|
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>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>lbry.tv</title>
|
|
||||||
<meta charset="utf-8" />
|
<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:url" content="https://beta.lbry.tv" />
|
||||||
<meta property="og:title" content="LBRY On The Web" />
|
<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:description" content="All your favorite LBRY content in your browser." />
|
||||||
<meta property="og:image" content="/og.png" />
|
<meta property="og:image" content="/og.png" />
|
||||||
|
<!-- @endif -->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -56,12 +56,7 @@ let baseConfig = {
|
||||||
{
|
{
|
||||||
test: /\.s?css$/,
|
test: /\.s?css$/,
|
||||||
exclude: /\.module.scss$/,
|
exclude: /\.module.scss$/,
|
||||||
use: [
|
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
|
||||||
'style-loader',
|
|
||||||
'css-loader',
|
|
||||||
'postcss-loader',
|
|
||||||
'sass-loader',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(png|svg|gif)$/,
|
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"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
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:
|
eslint-config-prettier@^2.9.0:
|
||||||
version "2.10.0"
|
version "2.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.10.0.tgz#ec07bc1d01f87d09f61d3840d112dc8a9791e30b"
|
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"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c"
|
||||||
integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==
|
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:
|
eslint-scope@3.7.1:
|
||||||
version "3.7.1"
|
version "3.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
|
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"
|
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
|
||||||
integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=
|
integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=
|
||||||
|
|
||||||
flow-bin@^0.94.0:
|
flow-bin@^0.97.0:
|
||||||
version "0.94.0"
|
version "0.97.0"
|
||||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.94.0.tgz#b5d58fe7559705b73a18229f97edfc3ab6ffffcb"
|
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.97.0.tgz#036ffcfc27503367a9d906ec9d843a0aa6f6bb83"
|
||||||
integrity sha512-DYF7r9CJ/AksfmmB4+q+TyLMoeQPRnqtF1Pk7KY3zgfkB/nVuA3nXyzqgsIPIvnMSiFEXQcFK4z+iPxSLckZhQ==
|
integrity sha512-jXjD05gkatLuC4+e28frH1hZoRwr1iASP6oJr61Q64+kR4kmzaS+AdFBhYgoYS5kpoe4UzwDebWK8ETQFNh00w==
|
||||||
|
|
||||||
flow-typed@^2.3.0:
|
flow-typed@^2.3.0:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
|
@ -6475,17 +6456,17 @@ lazy-val@^1.0.3, lazy-val@^1.0.4:
|
||||||
yargs "^13.2.2"
|
yargs "^13.2.2"
|
||||||
zstd-codec "^0.1.1"
|
zstd-codec "^0.1.1"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#d4c7dea65f7179974e9b96c863022fe7b049ff7d:
|
lbry-redux@lbryio/lbry-redux#cc42856676541120b088e4228c04246ba8ff3274:
|
||||||
version "0.0.1"
|
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:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
lbryinc@lbryio/lbryinc#4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02:
|
lbryinc@lbryio/lbryinc#9665f2d1c818f1a86b2e5daab642f6879746f25f:
|
||||||
version "0.0.1"
|
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:
|
dependencies:
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue