diff --git a/.flowconfig b/.flowconfig index 02fd318db..e7c44c7e9 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,10 +1,10 @@ [ignore] -node_modules/ [include] [libs] ./flow-typed +node_modules/lbry-redux/flow-typed/ [lints] diff --git a/src/ui/types/location.js b/flow-typed/location.js similarity index 90% rename from src/ui/types/location.js rename to flow-typed/location.js index 5ec91da94..2e49c2165 100644 --- a/src/ui/types/location.js +++ b/flow-typed/location.js @@ -1,6 +1,6 @@ // @flow -export type UrlLocation = { +declare type UrlLocation = { search: string, hash: string, host: string, diff --git a/flow-typed/npm/redux_v3.x.x.js b/flow-typed/npm/redux_v3.x.x.js deleted file mode 100644 index 7bc662368..000000000 --- a/flow-typed/npm/redux_v3.x.x.js +++ /dev/null @@ -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 = (action: A) => A; - declare export type Dispatch }> = DispatchAPI; - - declare export type MiddlewareAPI> = { - dispatch: D; - getState(): S; - }; - - declare export type Store> = { - // 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): void - }; - - declare export type Reducer = (state: S | void, action: A) => S; - - declare export type CombinedReducer = (state: $Shape & {} | void, action: A) => S; - - declare export type Middleware> = - (api: MiddlewareAPI) => - (next: D) => D; - - declare export type StoreCreator> = { - (reducer: Reducer, enhancer?: StoreEnhancer): Store; - (reducer: Reducer, preloadedState: S, enhancer?: StoreEnhancer): Store; - }; - - declare export type StoreEnhancer> = (next: StoreCreator) => StoreCreator; - - declare export function createStore(reducer: Reducer, enhancer?: StoreEnhancer): Store; - declare export function createStore(reducer: Reducer, preloadedState?: S, enhancer?: StoreEnhancer): Store; - - declare export function applyMiddleware(...middlewares: Array>): StoreEnhancer; - - declare export type ActionCreator = (...args: Array) => A; - declare export type ActionCreators = { [key: K]: ActionCreator }; - - declare export function bindActionCreators, D: DispatchAPI>(actionCreator: C, dispatch: D): C; - declare export function bindActionCreators, D: DispatchAPI>(actionCreators: C, dispatch: D): C; - - declare export function combineReducers(reducers: O): CombinedReducer<$ObjMap(r: Reducer) => S>, A>; - - declare export var compose: $Compose; -} diff --git a/flow-typed/publish.js b/flow-typed/publish.js new file mode 100644 index 000000000..7791303e6 --- /dev/null +++ b/flow-typed/publish.js @@ -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, +}; diff --git a/src/ui/types/reward.js b/flow-typed/reward.js similarity index 92% rename from src/ui/types/reward.js rename to flow-typed/reward.js index e25bba5cf..d77e3568f 100644 --- a/src/ui/types/reward.js +++ b/flow-typed/reward.js @@ -1,6 +1,6 @@ // @flow -export type Reward = { +declare type Reward = { created_at: string, id: number, reward_amount: number, diff --git a/src/ui/types/subscription.js b/flow-typed/subscription.js similarity index 67% rename from src/ui/types/subscription.js rename to flow-typed/subscription.js index e7a0bfe2a..ccdfc4ed9 100644 --- a/src/ui/types/subscription.js +++ b/flow-typed/subscription.js @@ -1,5 +1,4 @@ // @flow -import type { Dispatch as ReduxDispatch } from 'types/redux'; import * as ACTIONS from 'constants/action_types'; import { DOWNLOADED, @@ -12,7 +11,7 @@ import { SUGGESTED_FEATURED, } from 'constants/subscriptions'; -export type Subscription = { +declare type Subscription = { channelName: string, // @CryptoCandor, uri: string, // lbry://@CryptoCandor#9152f3b054f692076a6882d1b58a30e8781cc8e6 latest?: string, // substratum#b0ab143243020e7831fd070d9f871e1fda948620 @@ -21,26 +20,26 @@ export type Subscription = { // Tracking for new content // i.e. If a subscription has a DOWNLOADING type, we will trigger an OS notification // to tell users there is new content from their subscriptions -export type SubscriptionNotificationType = DOWNLOADED | DOWNLOADING | NOTIFY_ONLY; +declare type SubscriptionNotificationType = DOWNLOADED | DOWNLOADING | NOTIFY_ONLY; -export type UnreadSubscription = { +declare type UnreadSubscription = { type: SubscriptionNotificationType, uris: Array, }; -export type UnreadSubscriptions = { +declare type UnreadSubscriptions = { [string]: UnreadSubscription, }; -export type ViewMode = VIEW_LATEST_FIRST | VIEW_ALL; +declare type ViewMode = VIEW_LATEST_FIRST | VIEW_ALL; -export type SuggestedType = SUGGESTED_TOP_BID | SUGGESTED_TOP_SUBSCRIBED | SUGGESTED_FEATURED; +declare type SuggestedType = SUGGESTED_TOP_BID | SUGGESTED_TOP_SUBSCRIBED | SUGGESTED_FEATURED; -export type SuggestedSubscriptions = { +declare type SuggestedSubscriptions = { [SuggestedType]: string, }; -export type SubscriptionState = { +declare type SubscriptionState = { subscriptions: Array, unread: UnreadSubscriptions, loading: boolean, @@ -54,17 +53,17 @@ export type SubscriptionState = { // // Action types // -export type DoChannelSubscribe = { +declare type DoChannelSubscribe = { type: ACTIONS.CHANNEL_SUBSCRIBE, data: Subscription, }; -export type DoChannelUnsubscribe = { +declare type DoChannelUnsubscribe = { type: ACTIONS.CHANNEL_UNSUBSCRIBE, data: Subscription, }; -export type DoUpdateSubscriptionUnreads = { +declare type DoUpdateSubscriptionUnreads = { type: ACTIONS.UPDATE_SUBSCRIPTION_UNREADS, data: { channel: string, @@ -73,7 +72,7 @@ export type DoUpdateSubscriptionUnreads = { }, }; -export type DoRemoveSubscriptionUnreads = { +declare type DoRemoveSubscriptionUnreads = { type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS, data: { channel: string, @@ -81,7 +80,7 @@ export type DoRemoveSubscriptionUnreads = { }, }; -export type SetSubscriptionLatest = { +declare type SetSubscriptionLatest = { type: ACTIONS.SET_SUBSCRIPTION_LATEST, data: { subscription: Subscription, @@ -89,25 +88,25 @@ export type SetSubscriptionLatest = { }, }; -export type CheckSubscriptionStarted = { +declare type CheckSubscriptionStarted = { type: ACTIONS.CHECK_SUBSCRIPTION_STARTED, }; -export type CheckSubscriptionCompleted = { +declare type CheckSubscriptionCompleted = { type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED, }; -export type FetchedSubscriptionsSucess = { +declare type FetchedSubscriptionsSucess = { type: ACTIONS.FETCH_SUBSCRIPTIONS_SUCCESS, data: Array, }; -export type SetViewMode = { +declare type SetViewMode = { type: ACTIONS.SET_VIEW_MODE, data: ViewMode, }; -export type GetSuggestedSubscriptionsSuccess = { +declare type GetSuggestedSubscriptionsSuccess = { type: ACTIONS.GET_SUGGESTED_SUBSCRIPTIONS_START, data: SuggestedSubscriptions, }; diff --git a/package.json b/package.json index d99ae413b..4f85df2f1 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,6 @@ "electron-webpack": "^2.6.2", "electron-window-state": "^4.1.1", "eslint": "^5.15.2", - "eslint-config-airbnb": "^16.1.0", "eslint-config-prettier": "^2.9.0", "eslint-config-standard": "^12.0.0", "eslint-config-standard-jsx": "^6.0.2", @@ -106,7 +105,7 @@ "eslint-plugin-promise": "^4.0.1", "eslint-plugin-react": "^7.7.0", "eslint-plugin-standard": "^4.0.0", - "flow-bin": "^0.94.0", + "flow-bin": "^0.97.0", "flow-typed": "^2.3.0", "formik": "^0.10.4", "hast-util-sanitize": "^1.1.2", @@ -115,8 +114,8 @@ "jsmediatags": "^3.8.1", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#d4c7dea65f7179974e9b96c863022fe7b049ff7d", - "lbryinc": "lbryio/lbryinc#4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02", + "lbry-redux": "lbryio/lbry-redux#cc42856676541120b088e4228c04246ba8ff3274", + "lbryinc": "lbryio/lbryinc#9665f2d1c818f1a86b2e5daab642f6879746f25f", "lint-staged": "^7.0.2", "localforage": "^1.7.1", "lodash-es": "^4.17.11", @@ -186,7 +185,7 @@ "yarn": "^1.3" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.34.0", + "lbrynetDaemonVersion": "0.36.0", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip", "lbrynetDaemonDir": "static/daemon", "lbrynetDaemonFileName": "lbrynet" diff --git a/src/ui/component/button/view.jsx b/src/ui/component/button/view.jsx index 9ca8a04ef..2005bc78d 100644 --- a/src/ui/component/button/view.jsx +++ b/src/ui/component/button/view.jsx @@ -113,7 +113,12 @@ class Button extends React.PureComponent { exact to={path} title={title} - onClick={e => e.stopPropagation()} + onClick={e => { + e.stopPropagation(); + if (onClick) { + onClick(); + } + }} className={combinedClassName} activeClassName={activeClass} > diff --git a/src/ui/component/channelTile/view.jsx b/src/ui/component/channelTile/view.jsx index 9e1563d3d..ef57bbbaa 100644 --- a/src/ui/component/channelTile/view.jsx +++ b/src/ui/component/channelTile/view.jsx @@ -4,7 +4,6 @@ import CardMedia from 'component/cardMedia'; import TruncatedText from 'component/common/truncated-text'; import classnames from 'classnames'; import SubscribeButton from 'component/subscribeButton'; -import type { Claim } from 'types/claim'; import { withRouter } from 'react-router-dom'; import { formatLbryUriForWeb } from 'util/uri'; @@ -13,7 +12,7 @@ type Props = { isResolvingUri: boolean, totalItems: number, size: string, - claim: ?Claim, + claim: ?ChannelClaim, resolveUri: string => void, history: { push: string => void }, }; @@ -44,7 +43,7 @@ class ChannelTile extends React.PureComponent { let subscriptionUri; if (claim) { channelName = claim.name; - subscriptionUri = `lbry://${claim.permanent_url}`; + subscriptionUri = claim.permanent_url; } const onClick = () => history.push(formatLbryUriForWeb(uri)); diff --git a/src/ui/component/common/form-components/form-field-price.jsx b/src/ui/component/common/form-components/form-field-price.jsx index 6b82e1c34..0ba7a842a 100644 --- a/src/ui/component/common/form-components/form-field-price.jsx +++ b/src/ui/component/common/form-components/form-field-price.jsx @@ -1,11 +1,15 @@ // @flow import * as React from 'react'; -import type { Price } from 'page/settings'; import { FormField } from './form-field'; +type FormPrice = { + amount: ?number, + currency: string, +}; + type Props = { - price: Price, - onChange: Price => void, + price: FormPrice, + onChange: FormPrice => void, placeholder: number, min: number, disabled: boolean, @@ -23,7 +27,7 @@ export class FormFieldPrice extends React.PureComponent { handleAmountChange(event: SyntheticInputEvent<*>) { const { price, onChange } = this.props; - const amount = event.target.value ? parseFloat(event.target.value) : ''; + const amount = event.target.value ? parseFloat(event.target.value) : undefined; onChange({ currency: price.currency, amount, diff --git a/src/ui/component/common/form-components/form-field.jsx b/src/ui/component/common/form-components/form-field.jsx index 5fd77eb3b..e6862c182 100644 --- a/src/ui/component/common/form-components/form-field.jsx +++ b/src/ui/component/common/form-components/form-field.jsx @@ -1,4 +1,5 @@ // @flow +import type { ElementRef } from 'react'; import React, { Suspense } from 'react'; import ReactDOMServer from 'react-dom/server'; import MarkdownPreview from 'component/common/markdown-preview'; @@ -6,24 +7,24 @@ import 'easymde/dist/easymde.min.css'; import Toggle from 'react-toggle'; import { openEditorMenu, stopContextMenu } from 'util/context-menu'; -const SimpleMDE = React.lazy(() => import( - /* webpackChunkName: "SimpleMDE" */ - 'react-simplemde-editor' -)); +const SimpleMDE = React.lazy(() => + import(/* webpackChunkName: "SimpleMDE" */ + 'react-simplemde-editor') +); type Props = { name: string, label?: string, - render?: () => React.Node, + render?: () => React$Node, prefix?: string, postfix?: string, error?: string | boolean, - helper?: string | React.Node, + helper?: string | React$Node, type?: string, onChange?: any => any, defaultValue?: string | number, placeholder?: string | number, - children?: React.Node, + children?: React$Node, stretch?: boolean, affixClass?: string, // class applied to prefix/postfix label firstInList?: boolean, // at the top of a list, no padding top @@ -32,7 +33,7 @@ type Props = { inputProps?: { disabled?: boolean, }, - inputButton?: React.Node, + inputButton?: React$Node, blockWrap: boolean, }; @@ -42,7 +43,7 @@ export class FormField extends React.PureComponent { blockWrap: true, }; - input: { current: React.ElementRef }; + input: { current: ElementRef }; constructor(props: Props) { super(props); @@ -136,7 +137,7 @@ export class FormField extends React.PureComponent {
-
}> + }> (props: IconProps) => { +const buildIcon = (iconStrokes: React$Node, options?: {} = {}) => (props: IconProps) => { const { size = 24, color = 'currentColor', ...otherProps } = props; return ( , + children: React$Node | Array, }; type State = { diff --git a/src/ui/component/fileCard/index.js b/src/ui/component/fileCard/index.js index ff5a478f2..86cc6200d 100644 --- a/src/ui/component/fileCard/index.js +++ b/src/ui/component/fileCard/index.js @@ -7,6 +7,9 @@ import { makeSelectIsUriResolving, makeSelectClaimIsMine, makeSelectClaimIsPending, + makeSelectThumbnailForUri, + makeSelectTitleForUri, + makeSelectClaimIsNsfw, } from 'lbry-redux'; import { selectRewardContentClaimIds } from 'lbryinc'; import { makeSelectContentPositionForUri } from 'redux/selectors/content'; @@ -27,6 +30,9 @@ const select = (state, props) => ({ position: makeSelectContentPositionForUri(props.uri)(state), isSubscribed: makeSelectIsSubscribed(props.uri)(state), isNew: makeSelectIsNew(props.uri)(state), + thumbnail: makeSelectThumbnailForUri(props.uri)(state), + title: makeSelectTitleForUri(props.uri)(state), + nsfw: makeSelectClaimIsNsfw(props.uri)(state), }); const perform = dispatch => ({ diff --git a/src/ui/component/fileCard/view.jsx b/src/ui/component/fileCard/view.jsx index 8702cbecf..2d1237855 100644 --- a/src/ui/component/fileCard/view.jsx +++ b/src/ui/component/fileCard/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Claim, Metadata } from 'types/claim'; import * as icons from 'constants/icons'; import * as React from 'react'; import { normalizeURI, convertToShareLink } from 'lbry-redux'; @@ -13,12 +12,13 @@ import { openCopyLinkMenu } from 'util/context-menu'; import DateTime from 'component/dateTime'; import { withRouter } from 'react-router-dom'; import { formatLbryUriForWeb } from 'util/uri'; +import get from 'lodash.get'; type Props = { uri: string, - claim: ?Claim, + claim: ?StreamClaim, fileInfo: ?{}, - metadata: ?Metadata, + metadata: ?StreamMetadata, rewardedContentClaimIds: Array, obscureNsfw: boolean, claimIsMine: boolean, @@ -30,6 +30,9 @@ type Props = { placeholder: boolean, preventResolve: boolean, history: { push: string => void }, + thumbnail: string, + title: string, + nsfw: boolean, }; class FileCard extends React.PureComponent { @@ -72,6 +75,9 @@ class FileCard extends React.PureComponent { isResolvingUri, placeholder, history, + thumbnail, + title, + nsfw, } = this.props; const abandoned = !isResolvingUri && !claim && !pending && !placeholder; @@ -92,14 +98,13 @@ class FileCard extends React.PureComponent { ); } - const shouldHide = !claimIsMine && !pending && obscureNsfw && metadata && metadata.nsfw; + // fix to use tags - one of many nsfw tags... + const shouldHide = !claimIsMine && !pending && obscureNsfw && nsfw; if (shouldHide) { return null; } const uri = !pending ? normalizeURI(this.props.uri) : this.props.uri; - const title = metadata && metadata.title ? metadata.title : uri; - const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null; const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id); const height = claim && claim.height; const handleContextMenu = event => { diff --git a/src/ui/component/fileDetails/view.jsx b/src/ui/component/fileDetails/view.jsx index 72bdee683..9d6be1e31 100644 --- a/src/ui/component/fileDetails/view.jsx +++ b/src/ui/component/fileDetails/view.jsx @@ -1,7 +1,4 @@ // @flow -import type { Claim, Metadata } from 'types/claim'; -import type { FileInfo } from 'types/file_info'; -import type { Node } from 'react'; import React, { Fragment, PureComponent } from 'react'; import { Lbryio } from 'lbryinc'; import MarkdownPreview from 'component/common/markdown-preview'; @@ -10,13 +7,13 @@ import Expandable from 'component/expandable'; import path from 'path'; type Props = { - claim: Claim, - fileInfo: FileInfo, - metadata: Metadata, + claim: StreamClaim, + fileInfo: FileListItem, + metadata: StreamMetadata, openFolder: string => void, contentType: string, clickCommentButton: () => void, - showSnackBar: Node => void, + showSnackBar: React$Node => void, hasClickedComment: boolean, user: ?any, }; @@ -59,7 +56,7 @@ class FileDetails extends PureComponent { ); } - const { description, language, license } = metadata; + const { description, languages, license } = metadata; const mediaType = contentType || 'unknown'; let downloadPath = @@ -90,9 +87,9 @@ class FileDetails extends PureComponent { {mediaType}
- {__('Language')} + {__('Languages')} {': '} - {language} + {languages ? languages.join(' ') : null}
{__('License')} @@ -106,7 +103,11 @@ class FileDetails extends PureComponent {
diff --git a/src/ui/component/fileDownloadLink/view.jsx b/src/ui/component/fileDownloadLink/view.jsx index 349f14ff7..ba661c660 100644 --- a/src/ui/component/fileDownloadLink/view.jsx +++ b/src/ui/component/fileDownloadLink/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Claim } from 'types/claim'; import * as ICONS from 'constants/icons'; import React from 'react'; import Button from 'component/button'; @@ -7,7 +6,7 @@ import ToolTip from 'component/common/tooltip'; import analytics from 'analytics'; type Props = { - claim: Claim, + claim: StreamClaim, uri: string, downloading: boolean, fileInfo: ?{ diff --git a/src/ui/component/fileList/view.jsx b/src/ui/component/fileList/view.jsx index 55363131e..34a321939 100644 --- a/src/ui/component/fileList/view.jsx +++ b/src/ui/component/fileList/view.jsx @@ -3,13 +3,12 @@ import * as React from 'react'; import { buildURI, SORT_OPTIONS } from 'lbry-redux'; import { FormField, Form } from 'component/common/form'; import FileCard from 'component/fileCard'; -import type { FileInfo } from 'types/file_info'; type Props = { hideFilter: boolean, sortByHeight?: boolean, - claimsById: Array<{}>, - fileInfos: Array, + claimsById: Array, + fileInfos: Array, sortBy: string, page?: string, setFileListSort: (?string, string) => void, @@ -29,47 +28,47 @@ class FileList extends React.PureComponent { [SORT_OPTIONS.DATE_NEW]: fileInfos => this.props.sortByHeight ? fileInfos.sort((fileInfo1, fileInfo2) => { - if (fileInfo1.confirmations < 1) { - return -1; - } else if (fileInfo2.confirmations < 1) { - return 1; - } + if (fileInfo1.confirmations < 1) { + return -1; + } else if (fileInfo2.confirmations < 1) { + return 1; + } - const height1 = this.props.claimsById[fileInfo1.claim_id] - ? this.props.claimsById[fileInfo1.claim_id].height - : 0; - const height2 = this.props.claimsById[fileInfo2.claim_id] - ? this.props.claimsById[fileInfo2.claim_id].height - : 0; + const height1 = this.props.claimsById[fileInfo1.claim_id] + ? this.props.claimsById[fileInfo1.claim_id].height + : 0; + const height2 = this.props.claimsById[fileInfo2.claim_id] + ? this.props.claimsById[fileInfo2.claim_id].height + : 0; - if (height1 !== height2) { - // flipped because heigher block height is newer - return height2 - height1; - } + if (height1 !== height2) { + // flipped because heigher block height is newer + return height2 - height1; + } - if (fileInfo1.absolute_channel_position && fileInfo2.absolute_channel_position) { - return fileInfo1.absolute_channel_position - fileInfo2.absolute_channel_position; - } + if (fileInfo1.absolute_channel_position && fileInfo2.absolute_channel_position) { + return fileInfo1.absolute_channel_position - fileInfo2.absolute_channel_position; + } - return 0; - }) + return 0; + }) : [...fileInfos].reverse(), [SORT_OPTIONS.DATE_OLD]: fileInfos => this.props.sortByHeight ? fileInfos.slice().sort((fileInfo1, fileInfo2) => { - const height1 = this.props.claimsById[fileInfo1.claim_id] - ? this.props.claimsById[fileInfo1.claim_id].height - : 999999; - const height2 = this.props.claimsById[fileInfo2.claim_id] - ? this.props.claimsById[fileInfo2.claim_id].height - : 999999; - if (height1 < height2) { - return -1; - } else if (height1 > height2) { - return 1; - } - return 0; - }) + const height1 = this.props.claimsById[fileInfo1.claim_id] + ? this.props.claimsById[fileInfo1.claim_id].height + : 999999; + const height2 = this.props.claimsById[fileInfo2.claim_id] + ? this.props.claimsById[fileInfo2.claim_id].height + : 999999; + if (height1 < height2) { + return -1; + } else if (height1 > height2) { + return 1; + } + return 0; + }) : fileInfos, [SORT_OPTIONS.TITLE]: fileInfos => fileInfos.slice().sort((fileInfo1, fileInfo2) => { @@ -80,7 +79,7 @@ class FileList extends React.PureComponent { return metadata.title || claimName; } else if (value) { // published claim - const { title } = value.stream.metadata; + const { title } = value.stream; return title || name; } // Invalid claim @@ -109,14 +108,11 @@ class FileList extends React.PureComponent { }; } - getChannelSignature = (fileInfo: FileInfo) => { + getChannelSignature = (fileInfo: { pending: boolean } & FileListItem) => { if (fileInfo.pending) { return undefined; } - if (fileInfo.value) { - return fileInfo.value.publisherSignature.certificateId; - } return fileInfo.channel_claim_id; }; diff --git a/src/ui/component/fileRender/view.jsx b/src/ui/component/fileRender/view.jsx index f73224fe1..1c32311f3 100644 --- a/src/ui/component/fileRender/view.jsx +++ b/src/ui/component/fileRender/view.jsx @@ -1,46 +1,45 @@ // @flow -import type { Claim } from 'types/claim'; import { remote } from 'electron'; import React, { Suspense } from 'react'; import LoadingScreen from 'component/common/loading-screen'; import VideoViewer from 'component/viewers/videoViewer'; -const AudioViewer = React.lazy(() => import( - /* webpackChunkName: "audioViewer" */ - 'component/viewers/audioViewer' -)); +const AudioViewer = React.lazy<*>(() => + import(/* webpackChunkName: "audioViewer" */ + 'component/viewers/audioViewer') +); -const DocumentViewer = React.lazy(() => import( - /* webpackChunkName: "documentViewer" */ - 'component/viewers/documentViewer' -)); +const DocumentViewer = React.lazy<*>(() => + import(/* webpackChunkName: "documentViewer" */ + 'component/viewers/documentViewer') +); -const DocxViewer = React.lazy(() => import( - /* webpackChunkName: "docxViewer" */ - 'component/viewers/docxViewer' -)); +const DocxViewer = React.lazy<*>(() => + import(/* webpackChunkName: "docxViewer" */ + 'component/viewers/docxViewer') +); -const HtmlViewer = React.lazy(() => import( - /* webpackChunkName: "htmlViewer" */ - 'component/viewers/htmlViewer' -)); +const HtmlViewer = React.lazy<*>(() => + import(/* webpackChunkName: "htmlViewer" */ + 'component/viewers/htmlViewer') +); -const PdfViewer = React.lazy(() => import( - /* webpackChunkName: "pdfViewer" */ - 'component/viewers/pdfViewer' -)); +const PdfViewer = React.lazy<*>(() => + import(/* webpackChunkName: "pdfViewer" */ + 'component/viewers/pdfViewer') +); // @if TARGET='app' -const ThreeViewer = React.lazy(() => import( - /* webpackChunkName: "threeViewer" */ - 'component/viewers/threeViewer' -)); +const ThreeViewer = React.lazy<*>(() => + import(/* webpackChunkName: "threeViewer" */ + 'component/viewers/threeViewer') +); // @endif type Props = { mediaType: string, poster?: string, - claim: Claim, + claim: StreamClaim, source: { stream: string => void, fileName: string, @@ -119,8 +118,6 @@ class FileRender extends React.PureComponent { renderViewer() { const { source, mediaType, currentTheme, poster, claim } = this.props; - console.log('mediaType', mediaType); - // Extract relevant data to render file const { stream, fileType, contentType, downloadPath, fileName } = source; @@ -155,11 +152,7 @@ class FileRender extends React.PureComponent { /> ), audio: ( - + ), // Add routes to viewer... }; @@ -182,7 +175,7 @@ class FileRender extends React.PureComponent { // @if TARGET='web' // temp workaround to disabled paid content on web - if (claim && claim.value.stream.metadata.fee && claim.value.stream.metadata.fee.amount > 0) { + if (claim && claim.value.fee && claim.value.fee.amount > 0) { const paidMessage = __( 'Currently, only free content is available on lbry.tv. Try viewing it in the desktop app.' ); @@ -200,12 +193,9 @@ class FileRender extends React.PureComponent { } render() { - console.log('RENDER') return (
-
}> - {this.renderViewer()} - + }>{this.renderViewer()} ); } diff --git a/src/ui/component/fileTile/index.js b/src/ui/component/fileTile/index.js index 09723ac49..63004d6d7 100644 --- a/src/ui/component/fileTile/index.js +++ b/src/ui/component/fileTile/index.js @@ -6,6 +6,9 @@ import { makeSelectFileInfoForUri, makeSelectIsUriResolving, makeSelectClaimIsMine, + makeSelectThumbnailForUri, + makeSelectTitleForUri, + makeSelectClaimIsNsfw, } from 'lbry-redux'; import { selectRewardContentClaimIds } from 'lbryinc'; import { selectShowNsfw } from 'redux/selectors/settings'; @@ -23,6 +26,9 @@ const select = (state, props) => ({ claimIsMine: makeSelectClaimIsMine(props.uri)(state), isSubscribed: makeSelectIsSubscribed(props.uri)(state), isNew: makeSelectIsNew(props.uri)(state), + thumbnail: makeSelectThumbnailForUri(props.uri)(state), + title: makeSelectTitleForUri(props.uri)(state), + nsfw: makeSelectClaimIsNsfw(props.uri)(state), }); const perform = dispatch => ({ diff --git a/src/ui/component/fileTile/view.jsx b/src/ui/component/fileTile/view.jsx index 55c6c1334..976ca9d91 100644 --- a/src/ui/component/fileTile/view.jsx +++ b/src/ui/component/fileTile/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Claim, Metadata } from 'types/claim'; import * as ICONS from 'constants/icons'; import React, { Fragment } from 'react'; import { normalizeURI, parseURI } from 'lbry-redux'; @@ -22,8 +21,8 @@ type Props = { uri: string, isResolvingUri: boolean, rewardedContentClaimIds: Array, - claim: ?Claim, - metadata: ?Metadata, + claim: ?StreamClaim, + metadata: ?StreamMetadata, resolveUri: string => void, clearPublish: () => void, updatePublishForm: ({}) => void, @@ -33,6 +32,9 @@ type Props = { isSubscribed: boolean, isNew: boolean, history: { push: string => void }, + thumbnail: ?string, + title: ?string, + nsfw: boolean, }; class FileTile extends React.PureComponent { @@ -93,6 +95,9 @@ class FileTile extends React.PureComponent { displayHiddenMessage, size, history, + thumbnail, + title, + nsfw, } = this.props; if (!claim && isResolvingUri) { @@ -112,7 +117,7 @@ class FileTile extends React.PureComponent { ); } - const shouldHide = !claimIsMine && obscureNsfw && metadata && metadata.nsfw; + const shouldHide = !claimIsMine && obscureNsfw && nsfw; if (shouldHide) { return displayHiddenMessage ? ( @@ -126,9 +131,6 @@ class FileTile extends React.PureComponent { const uri = normalizeURI(this.props.uri); const isClaimed = !!claim; const description = isClaimed && metadata && metadata.description ? metadata.description : ''; - const title = - isClaimed && metadata && metadata.title ? metadata.title : parseURI(uri).contentName; - const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null; let height; let name; @@ -211,7 +213,7 @@ class FileTile extends React.PureComponent { clearPublish(); // to remove any existing publish data updatePublishForm({ name: claimName }); // to populate the name - history.push('/publish'); + history.push('/$/publish'); }} /> } diff --git a/src/ui/component/fileViewer/index.js b/src/ui/component/fileViewer/index.js index 5b15333af..a673137ea 100644 --- a/src/ui/component/fileViewer/index.js +++ b/src/ui/component/fileViewer/index.js @@ -13,6 +13,8 @@ import { makeSelectDownloadingForUri, selectSearchBarFocused, makeSelectFirstRecommendedFileForUri, + makeSelectClaimIsNsfw, + makeSelectThumbnailForUri, } from 'lbry-redux'; import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings'; import { selectPlayingUri, makeSelectContentPositionForUri } from 'redux/selectors/content'; @@ -35,6 +37,8 @@ const select = (state, props) => ({ searchBarFocused: selectSearchBarFocused(state), fileInfoErrors: selectFileInfoErrors(state), nextFileToPlay: makeSelectFirstRecommendedFileForUri(props.uri)(state), + nsfw: makeSelectClaimIsNsfw(props.uri)(state), + thumbnail: makeSelectThumbnailForUri(props.uri)(state), }); const perform = dispatch => ({ diff --git a/src/ui/component/fileViewer/internal/player.jsx b/src/ui/component/fileViewer/internal/player.jsx index c34467814..298be8189 100644 --- a/src/ui/component/fileViewer/internal/player.jsx +++ b/src/ui/component/fileViewer/internal/player.jsx @@ -1,6 +1,5 @@ // @flow import 'babel-polyfill'; -import type { Claim } from 'types/claim'; import * as React from 'react'; // @if TARGET='app' import { remote } from 'electron'; @@ -19,7 +18,7 @@ type Props = { position: ?number, downloadPath: string, fileName: string, - claim: Claim, + claim: StreamClaim, onStartCb: ?() => void, onFinishCb: ?() => void, savePosition: number => void, @@ -263,11 +262,6 @@ class MediaPlayer extends React.PureComponent { // This files are supported using a custom viewer const { mediaType, contentType } = this.props; - console.log({ - mediaType, - contentType - }) - return ( MediaPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1 || MediaPlayer.SANDBOX_TYPES.indexOf(contentType) > -1 @@ -362,13 +356,6 @@ class MediaPlayer extends React.PureComponent { const isPlayableType = this.playableType(); const { isLoading, loadingStatus } = this.showLoadingScreen(isFileType, isPlayableType); - console.log({ - mediaType, - fileSource, - isFileReady, - isFileType - }) - return ( {loadingStatus && } diff --git a/src/ui/component/fileViewer/view.jsx b/src/ui/component/fileViewer/view.jsx index 02e05996d..9642788a9 100644 --- a/src/ui/component/fileViewer/view.jsx +++ b/src/ui/component/fileViewer/view.jsx @@ -3,14 +3,13 @@ import * as PAGES from 'constants/pages'; import React, { Suspense } from 'react'; import classnames from 'classnames'; import analytics from 'analytics'; -import type { Claim } from 'types/claim'; import LoadingScreen from 'component/common/loading-screen'; import PlayButton from './internal/play-button'; -const Player = React.lazy(() => import( - /* webpackChunkName: "player-legacy" */ - './internal/player' -)); +const Player = React.lazy(() => + import(/* webpackChunkName: "player-legacy" */ + './internal/player') +); const SPACE_BAR_KEYCODE = 32; @@ -27,10 +26,6 @@ type Props = { fileInfoErrors: ?{ [string]: boolean, }, - metadata: ?{ - nsfw: boolean, - thumbnail: string, - }, autoplay: boolean, isLoading: boolean, isDownloading: boolean, @@ -38,7 +33,7 @@ type Props = { contentType: string, changeVolume: number => void, volume: number, - claim: Claim, + claim: StreamClaim, uri: string, savePosition: (string, string, number) => void, position: ?number, @@ -52,6 +47,8 @@ type Props = { navigate: (string, {}) => void, costInfo: ?{ cost: number }, insufficientCredits: boolean, + nsfw: boolean, + thumbnail: ?string, }; class FileViewer extends React.PureComponent { @@ -135,9 +132,9 @@ class FileViewer extends React.PureComponent { } handleAutoplay = (props: Props) => { - const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, metadata } = props; + const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, nsfw } = props; - const playable = autoplay && playingUri !== uri && metadata && !metadata.nsfw; + const playable = autoplay && playingUri !== uri && !nsfw; if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) { this.playContent(); @@ -184,7 +181,7 @@ class FileViewer extends React.PureComponent { } } - fireAnalyticsEvent(claim: Claim, startTime: ?number, playTime: ?number) { + fireAnalyticsEvent(claim: StreamClaim, startTime: ?number, playTime: ?number) { const { claimRewards } = this.props; const { name, claim_id: claimId, txid, nout } = claim; @@ -214,7 +211,6 @@ class FileViewer extends React.PureComponent { render() { const { - metadata, isLoading, isDownloading, playingUri, @@ -230,19 +226,21 @@ class FileViewer extends React.PureComponent { obscureNsfw, mediaType, insufficientCredits, + thumbnail, + nsfw, } = this.props; const isPlaying = playingUri === uri; + let isReadyToPlay = false; // @if TARGET='app' - const isReadyToPlay = fileInfo && fileInfo.download_path && fileInfo.written_bytes > 0; + isReadyToPlay = fileInfo && fileInfo.download_path && fileInfo.written_bytes > 0; // @endif // @if TARGET='web' // try to play immediately on web, we don't need to call file_list since we are streaming from reflector - // $FlowFixMe - const isReadyToPlay = isPlaying; + isReadyToPlay = isPlaying; // @endif - const shouldObscureNsfw = obscureNsfw && metadata && metadata.nsfw; + const shouldObscureNsfw = obscureNsfw && nsfw; let loadStatusMessage = ''; if (fileInfo && fileInfo.completed && (!fileInfo.download_path || !fileInfo.written_bytes)) { @@ -255,14 +253,13 @@ class FileViewer extends React.PureComponent { loadStatusMessage = __('Downloading stream... not long left now!'); } - const poster = metadata && metadata.thumbnail; const layoverClass = classnames('content__cover', { 'card__media--nsfw': shouldObscureNsfw, 'card__media--disabled': insufficientCredits, }); const layoverStyle = - !shouldObscureNsfw && poster ? { backgroundImage: `url("${poster}")` } : {}; + !shouldObscureNsfw && thumbnail ? { backgroundImage: `url("${thumbnail}")` } : {}; return (
@@ -273,10 +270,10 @@ class FileViewer extends React.PureComponent {
) : ( - }> + }> void, resolveUri: string => void, @@ -37,9 +36,9 @@ class NavigationHistoryItem extends React.PureComponent { let name; let title; - if (claim && claim.value && claim.value.stream) { + if (claim && claim.value) { ({ name } = claim); - ({ title } = claim.value.stream.metadata); + ({ title } = claim.value); } const navigatePath = formatLbryUriForWeb(uri); diff --git a/src/ui/component/publishForm/internal/name-help-text.jsx b/src/ui/component/publishForm/internal/name-help-text.jsx index 6d66895ae..ea9d107de 100644 --- a/src/ui/component/publishForm/internal/name-help-text.jsx +++ b/src/ui/component/publishForm/internal/name-help-text.jsx @@ -2,11 +2,10 @@ import * as React from 'react'; import Button from 'component/button'; import { buildURI } from 'lbry-redux'; -import type { Claim } from 'types/claim'; type Props = { uri: ?string, - myClaimForUri: ?Claim, + myClaimForUri: ?StreamClaim, isStillEditing: boolean, onEditMyClaim: (any, string) => void, }; diff --git a/src/ui/component/publishForm/view.jsx b/src/ui/component/publishForm/view.jsx index 1c8a4a954..1bebb745d 100644 --- a/src/ui/component/publishForm/view.jsx +++ b/src/ui/component/publishForm/view.jsx @@ -1,6 +1,4 @@ // @flow -import type { Claim } from 'types/claim'; -import type { PublishParams, UpdatePublishFormData } from 'redux/reducers/publish'; import { COPYRIGHT, OTHER } from 'constants/licenses'; import { CHANNEL_NEW, CHANNEL_ANONYMOUS, MINIMUM_PUBLISH_BID } from 'constants/claim'; import * as ICONS from 'constants/icons'; @@ -40,7 +38,7 @@ type Props = { nameError: ?string, isResolvingUri: boolean, winningBidForClaimUri: number, - myClaimForUri: ?Claim, + myClaimForUri: ?StreamClaim, licenseType: string, otherLicenseDescription: ?string, licenseUrl: ?string, @@ -232,12 +230,6 @@ class PublishForm extends React.PureComponent { isStillEditing: this.props.isStillEditing, }; - // Editing a claim - if (!filePath && myClaimForUri && myClaimForUri.value) { - const { source } = myClaimForUri.value.stream; - publishParams.sources = source; - } - publish(publishParams); } diff --git a/src/ui/component/recommendedContent/view.jsx b/src/ui/component/recommendedContent/view.jsx index 80488e75d..47186d69e 100644 --- a/src/ui/component/recommendedContent/view.jsx +++ b/src/ui/component/recommendedContent/view.jsx @@ -1,11 +1,10 @@ // @flow import React from 'react'; import FileTile from 'component/fileTile'; -import type { Claim } from 'types/claim'; type Props = { uri: string, - claim: ?Claim, + claim: ?StreamClaim, recommendedContent: Array, isSearching: boolean, search: string => void, @@ -37,10 +36,12 @@ export default class RecommendedContent extends React.PureComponent { getRecommendedContent() { const { claim, search } = this.props; - if (claim && claim.value && claim.value.stream && claim.value.stream.metadata) { - const { title } = claim.value.stream.metadata; - search(title); - this.didSearch = true; + if (claim && claim.value && claim.value) { + const { title } = claim.value; + if (title) { + search(title); + this.didSearch = true; + } } } diff --git a/src/ui/component/selectChannel/index.js b/src/ui/component/selectChannel/index.js index 0d082aee5..eec1756c4 100644 --- a/src/ui/component/selectChannel/index.js +++ b/src/ui/component/selectChannel/index.js @@ -1,7 +1,12 @@ import { connect } from 'react-redux'; import SelectChannel from './view'; -import { selectBalance, selectMyChannelClaims, selectFetchingMyChannels } from 'lbry-redux'; -import { doFetchChannelListMine, doCreateChannel } from 'redux/actions/content'; +import { + selectBalance, + selectMyChannelClaims, + selectFetchingMyChannels, + doFetchChannelListMine, + doCreateChannel, +} from 'lbry-redux'; const select = state => ({ channels: selectMyChannelClaims(state), diff --git a/src/ui/component/socialShare/view.jsx b/src/ui/component/socialShare/view.jsx index 63edcf65d..5771747b5 100644 --- a/src/ui/component/socialShare/view.jsx +++ b/src/ui/component/socialShare/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Claim } from 'types/claim'; import * as ICONS from 'constants/icons'; import React from 'react'; import Button from 'component/button'; @@ -7,7 +6,7 @@ import CopyableText from 'component/copyableText'; import ToolTip from 'component/common/tooltip'; type Props = { - claim: Claim, + claim: StreamClaim, onDone: () => void, speechShareable: boolean, isChannel: boolean, @@ -31,8 +30,7 @@ class SocialShare extends React.PureComponent { const { claim_id: claimId, name: claimName, channel_name: channelName, value } = claim; const { speechShareable, onDone } = this.props; - const channelClaimId = - value && value.publisherSignature && value.publisherSignature.certificateId; + const channelClaimId = claim.signing_channel && claim.signing_channel.claim_id; const getSpeechUri = (): string => { if (isChannel) { diff --git a/src/ui/component/splash/view.jsx b/src/ui/component/splash/view.jsx index be536f593..b3cca9599 100644 --- a/src/ui/component/splash/view.jsx +++ b/src/ui/component/splash/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Status } from 'types/status'; import * as React from 'react'; import * as MODALS from 'constants/modal_types'; import { Lbry } from 'lbry-redux'; @@ -97,11 +96,11 @@ export default class SplashScreen extends React.PureComponent { }); } - updateStatusCallback(status: Status) { + updateStatusCallback(status: StatusResponse) { const { notifyUnlockWallet, authenticate, modal } = this.props; const { launchedModal } = this.state; - if (status.error) { + if (status.connection_status.code !== 'connected') { this.setState({ error: true }); return; } diff --git a/src/ui/component/transactionList/internal/transaction-list-item.jsx b/src/ui/component/transactionList/internal/transaction-list-item.jsx index 78b0c7b79..8f38a08e8 100644 --- a/src/ui/component/transactionList/internal/transaction-list-item.jsx +++ b/src/ui/component/transactionList/internal/transaction-list-item.jsx @@ -1,5 +1,4 @@ // @flow -import type { Transaction } from 'types/transaction'; import * as TXN_TYPES from 'constants/transaction_types'; import * as ICONS from 'constants/icons'; import React from 'react'; diff --git a/src/ui/component/transactionList/view.jsx b/src/ui/component/transactionList/view.jsx index 262bee7a4..7bfa99722 100644 --- a/src/ui/component/transactionList/view.jsx +++ b/src/ui/component/transactionList/view.jsx @@ -1,9 +1,8 @@ // @flow -import type { Transaction } from 'types/transaction'; import * as icons from 'constants/icons'; import * as MODALS from 'constants/modal_types'; import * as React from 'react'; -import { List } from 'react-virtualized' +import { List } from 'react-virtualized'; import { FormField, Form } from 'component/common/form'; import Button from 'component/button'; import FileExporter from 'component/common/file-exporter'; diff --git a/src/ui/component/transactionListRecent/view.jsx b/src/ui/component/transactionListRecent/view.jsx index c2b1e9ad9..26b0c9b62 100644 --- a/src/ui/component/transactionListRecent/view.jsx +++ b/src/ui/component/transactionListRecent/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Transaction } from 'types/transaction'; import * as icons from 'constants/icons'; import React, { Fragment } from 'react'; import BusyIndicator from 'component/common/busy-indicator'; diff --git a/src/ui/component/uriIndicator/view.jsx b/src/ui/component/uriIndicator/view.jsx index 1f5dc7ca2..d09c4b3a7 100644 --- a/src/ui/component/uriIndicator/view.jsx +++ b/src/ui/component/uriIndicator/view.jsx @@ -2,12 +2,13 @@ import React from 'react'; import Button from 'component/button'; import { buildURI } from 'lbry-redux'; -import type { Claim } from 'types/claim'; type Props = { isResolvingUri: boolean, - claim: Claim, + channelUri: ?string, link: ?boolean, + claim: ?StreamClaim, + channelClaim: ?ChannelClaim, // Lint thinks we aren't using these, even though we are. // Possibly because the resolve function is an arrow function that is passed in props? resolveUri: string => void, @@ -32,25 +33,23 @@ class UriIndicator extends React.PureComponent { }; render() { - const { claim, link, isResolvingUri } = this.props; + const { link, isResolvingUri, claim } = this.props; + if (!claim) { return {isResolvingUri ? 'Validating...' : 'Unused'}; } - const { channel_name: channelName, signature_is_valid: signatureIsValid, value } = claim; - const channelClaimId = - value && value.publisherSignature && value.publisherSignature.certificateId; - - if (!channelName) { + if (!claim.signing_channel) { return Anonymous; } + const { name, claim_id: claimId } = claim.signing_channel; let channelLink; - if (signatureIsValid) { - channelLink = link ? buildURI({ channelName, claimId: channelClaimId }) : false; + if (claim.is_channel_signature_valid) { + channelLink = link ? buildURI({ channelName: name, claimId }) : false; } - const inner = {channelName}; + const inner = {name}; if (!channelLink) { return inner; diff --git a/src/ui/component/viewers/audioViewer.jsx b/src/ui/component/viewers/audioViewer.jsx index db2e81301..22c878722 100644 --- a/src/ui/component/viewers/audioViewer.jsx +++ b/src/ui/component/viewers/audioViewer.jsx @@ -1,5 +1,3 @@ -// @flow -import type { Claim } from 'types/claim'; import React from 'react'; import * as ICONS from 'constants/icons'; import Button from 'component/button'; @@ -15,18 +13,7 @@ import styles from './audioViewer.module.scss'; const isButterchurnSupported = detectButterchurnSupport(); -const EQ_BANDS_SIMPLE = [ - 55, - 150, - 250, - 400, - 500, - 1000, - 2000, - 4000, - 8000, - 16000, -] +const EQ_BANDS_SIMPLE = [55, 150, 250, 400, 500, 1000, 2000, 4000, 8000, 16000]; /* const EQ_LOWSHELF = EQ_BANDS_SIMPLE.shift(); const EQ_HIGHSHELF = EQ_BANDS_SIMPLE.pop(); @@ -41,15 +28,15 @@ const eqFilters = EQ.map(function(band) { }); */ -type Props = { - source: { - downloadPath: string, - fileName: string, - }, - contentType: string, - poster?: string, - claim: Claim, -}; +// type Props = { +// source: { +// downloadPath: string, +// fileName: string, +// }, +// contentType: string, +// poster?: string, +// claim: StreamClaim, +// }; const presets = [ require('butterchurn-presets/presets/converted/Flexi - when monopolies were the future [simple warp + non-reactive moebius].json'), @@ -61,9 +48,9 @@ const presets = [ require('butterchurn-presets/presets/converted/Zylot - Crosshair Dimension (Light of Ages).json'), ]; -class AudioVideoViewer extends React.PureComponent { - audioNode: ?HTMLAudioElement; - player: ?{ dispose: () => void }; +class AudioVideoViewer extends React.PureComponent { + // audioNode: ?HTMLAudioElement; + // player: ?{ dispose: () => void }; state = { playing: false, @@ -107,12 +94,16 @@ class AudioVideoViewer extends React.PureComponent { audioSource.connect(audioContext.destination); if (isButterchurnSupported) { - const visualizer = me.visualizer = butterchurn.createVisualizer(audioContext, me.canvasNode, { - height: canvasHeight, - width: canvasWidth, - pixelRatio: window.devicePixelRatio || 1, - textureRatio: 1, - }); + const visualizer = (me.visualizer = butterchurn.createVisualizer( + audioContext, + me.canvasNode, + { + height: canvasHeight, + width: canvasWidth, + pixelRatio: window.devicePixelRatio || 1, + textureRatio: 1, + } + )); visualizer.connectAudio(audioSource); visualizer.loadPreset(presets[Math.floor(Math.random() * presets.length)], 2.0); @@ -120,10 +111,10 @@ class AudioVideoViewer extends React.PureComponent { me._frameCycle = () => { requestAnimationFrame(me._frameCycle); - if(me.state.enableMilkdrop === true) { + if (me.state.enableMilkdrop === true) { visualizer.render(); } - } + }; me._frameCycle(); } @@ -145,12 +136,7 @@ class AudioVideoViewer extends React.PureComponent { jsmediatags.Config.setDisallowedXhrHeaders(['If-Modified-Since', 'Range']); jsmediatags.read(path, { onSuccess: function(result) { - const { - album, - artist, - title, - picture - } = result.tags; + const { album, artist, title, picture } = result.tags; if (picture) { const byteArray = new Uint8Array(picture.data); @@ -169,7 +155,7 @@ class AudioVideoViewer extends React.PureComponent { }, onError: function(error) { console.log(':(', error.type, error.info); - } + }, }); } @@ -203,18 +189,26 @@ class AudioVideoViewer extends React.PureComponent { const path = `https://api.lbry.tv/content/claims/${claim.name}/${claim.claim_id}/stream.mp4`; const playButton = ( -
{ +
{ const audioNode = this.audioNode; if (audioNode.paused) { audioNode.play(); } else { audioNode.pause(); } - }} className={playing ? styles.playButtonPause : styles.playButtonPlay}>
+ }} + className={playing ? styles.playButtonPause : styles.playButtonPlay} + /> ); return ( -
me.setState({ userActive: true })} onMouseLeave={()=>me.setState({ userActive: false })} onContextMenu={stopContextMenu}> +
me.setState({ userActive: true })} + onMouseLeave={() => me.setState({ userActive: false })} + onContextMenu={stopContextMenu} + >
@@ -226,9 +220,12 @@ class AudioVideoViewer extends React.PureComponent { } // 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 }); }} /> @@ -251,24 +248,56 @@ class AudioVideoViewer extends React.PureComponent { />
-
(this.waveNode = node)} className={styles.wave}>
+
(this.waveNode = node)} className={styles.wave} />
(this.artNode = node)} /> {renderArt && playButton}
-
+
- {artist &&
} - {title &&
} - {album &&
} + {artist && ( +
+
+ )} + {title && ( +
+
+ )} + {album && ( +
+
+ )}
{!renderArt &&
{playButton}
}
- (this.canvasNode = node)} className={enableMilkdrop ? styles.milkdrop : styles.milkdropDisabled} /> -
); } diff --git a/src/ui/component/viewers/documentViewer.jsx b/src/ui/component/viewers/documentViewer.jsx index ce8a7992e..27e825d0d 100644 --- a/src/ui/component/viewers/documentViewer.jsx +++ b/src/ui/component/viewers/documentViewer.jsx @@ -4,10 +4,10 @@ import React, { Suspense } from 'react'; import LoadingScreen from 'component/common/loading-screen'; import MarkdownPreview from 'component/common/markdown-preview'; -const LazyCodeViewer = React.lazy(() => import( - /* webpackChunkName: "codeViewer" */ - 'component/viewers/codeViewer' -)); +const LazyCodeViewer = React.lazy<*>(() => + import(/* webpackChunkName: "codeViewer" */ + 'component/viewers/codeViewer') +); type Props = { theme: string, @@ -84,7 +84,7 @@ class DocumentViewer extends React.PureComponent {
{loading && !error && } {error && } - {isReady &&
}>{this.renderDocument()}} + {isReady && }>{this.renderDocument()}}
); } diff --git a/src/ui/component/viewers/videoViewer.jsx b/src/ui/component/viewers/videoViewer.jsx index e0d6f8739..0c756a416 100644 --- a/src/ui/component/viewers/videoViewer.jsx +++ b/src/ui/component/viewers/videoViewer.jsx @@ -1,11 +1,10 @@ // @flow -import type { Claim } from 'types/claim'; import React, { Suspense } from 'react'; import { stopContextMenu } from 'util/context-menu'; import analytics from 'analytics'; import(/* webpackChunkName: "videojs" */ /* webpackPreload: true */ -'video.js/dist/video-js.css'); + 'video.js/dist/video-js.css'); type Props = { source: { @@ -14,7 +13,7 @@ type Props = { }, contentType: string, poster?: string, - claim: Claim, + claim: StreamClaim, }; class AudioVideoViewer extends React.PureComponent { @@ -50,11 +49,13 @@ class AudioVideoViewer extends React.PureComponent { import(/* webpackChunkName: "videojs" */ /* webpackMode: "lazy" */ /* webpackPreload: true */ - 'video.js').then(videojs => { + 'video.js').then(videojs => { if (videojs.__esModule) { videojs = videojs.default; + this.player = videojs(this.videoNode, videoJsOptions, () => {}); + } else { + throw Error('Unable to import and use videojs'); } - this.player = videojs(this.videoNode, videoJsOptions, () => {}); }); } diff --git a/src/ui/component/walletSendTip/view.jsx b/src/ui/component/walletSendTip/view.jsx index 032a18097..cf5b35c5c 100644 --- a/src/ui/component/walletSendTip/view.jsx +++ b/src/ui/component/walletSendTip/view.jsx @@ -2,12 +2,11 @@ import React from 'react'; import Button from 'component/button'; import { FormField, Form } from 'component/common/form'; -import type { Claim } from 'types/claim'; type Props = { uri: string, title: string, - claim: Claim, + claim: StreamClaim, isPending: boolean, sendSupport: (number, string, string) => void, onCancel: () => void, diff --git a/src/ui/modal/modalAffirmPurchase/view.jsx b/src/ui/modal/modalAffirmPurchase/view.jsx index a2fbd68cf..1f7083e1a 100644 --- a/src/ui/modal/modalAffirmPurchase/view.jsx +++ b/src/ui/modal/modalAffirmPurchase/view.jsx @@ -2,14 +2,13 @@ import React from 'react'; import FilePrice from 'component/filePrice'; import { Modal } from 'modal/modal'; -import type { Metadata } from 'types/claim'; type Props = { closeModal: () => void, loadVideo: string => void, uri: string, cancelPurchase: () => void, - metadata: Metadata, + metadata: StreamMetadata, }; class ModalAffirmPurchase extends React.PureComponent { @@ -42,7 +41,7 @@ class ModalAffirmPurchase extends React.PureComponent { >

- {__('This will purchase')} {`"${title}"`} {__('for')}{' '} + {__('This will purchase')} {title ? `"${title}"` : uri} {__('for')}{' '} {' '} diff --git a/src/ui/modal/modalConfirmThumbnailUpload/index.js b/src/ui/modal/modalConfirmThumbnailUpload/index.js index 78a6699a4..6e60f6520 100644 --- a/src/ui/modal/modalConfirmThumbnailUpload/index.js +++ b/src/ui/modal/modalConfirmThumbnailUpload/index.js @@ -1,21 +1,15 @@ import { connect } from 'react-redux'; import { doHideModal } from 'redux/actions/app'; import { doUploadThumbnail, doUpdatePublishForm } from 'redux/actions/publish'; -import { selectPublishFormValues } from 'redux/selectors/publish'; import ModalConfirmThumbnailUpload from './view'; -const select = state => { - const publishState = selectPublishFormValues(state); - return { nsfw: publishState.nsfw }; -}; - const perform = dispatch => ({ closeModal: () => dispatch(doHideModal()), - upload: (path, nsfw = false) => dispatch(doUploadThumbnail(path, nsfw)), + upload: path => dispatch(doUploadThumbnail(path)), updatePublishForm: value => dispatch(doUpdatePublishForm(value)), }); export default connect( - select, + null, perform )(ModalConfirmThumbnailUpload); diff --git a/src/ui/modal/modalConfirmThumbnailUpload/view.jsx b/src/ui/modal/modalConfirmThumbnailUpload/view.jsx index 7bd335ada..d0bf24dd7 100644 --- a/src/ui/modal/modalConfirmThumbnailUpload/view.jsx +++ b/src/ui/modal/modalConfirmThumbnailUpload/view.jsx @@ -4,23 +4,22 @@ import { Modal } from 'modal/modal'; import { FormField } from 'component/common/form'; type Props = { - upload: (string, boolean) => void, + upload: string => void, path: string, - nsfw: boolean, closeModal: () => void, updatePublishForm: ({}) => void, }; class ModalConfirmThumbnailUpload extends React.PureComponent { upload() { - const { upload, updatePublishForm, closeModal, path, nsfw } = this.props; - upload(path, nsfw); + const { upload, updatePublishForm, closeModal, path } = this.props; + upload(path); updatePublishForm({ thumbnailPath: path }); closeModal(); } render() { - const { closeModal, path, updatePublishForm, nsfw } = this.props; + const { closeModal, path, updatePublishForm } = this.props; return ( {

{__('Are you sure you want to upload this thumbnail to spee.ch')}?

{path}
- - updatePublishForm({ nsfw: event.target.checked })} - />
); diff --git a/src/ui/modal/modalError/view.jsx b/src/ui/modal/modalError/view.jsx index 5e1b666a8..ffabe4b8d 100644 --- a/src/ui/modal/modalError/view.jsx +++ b/src/ui/modal/modalError/view.jsx @@ -10,7 +10,9 @@ type Props = { class ModalError extends React.PureComponent { componentDidMount() { - Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) }); + if (process.env.NODE_ENV === 'production') { + Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) }); + } } render() { const { closeModal, error } = this.props; diff --git a/src/ui/modal/modalFileTimeout/view.jsx b/src/ui/modal/modalFileTimeout/view.jsx index 22c5d7c4e..67a94ed49 100644 --- a/src/ui/modal/modalFileTimeout/view.jsx +++ b/src/ui/modal/modalFileTimeout/view.jsx @@ -1,16 +1,17 @@ // @flow import React from 'react'; import { Modal } from 'modal/modal'; -import type { Metadata } from 'types/claim'; type Props = { - metadata: Metadata, + uri: string, + metadata: StreamMetadata, closeModal: () => void, }; class ModalFileTimeout extends React.PureComponent { render() { const { + uri, metadata: { title }, closeModal, } = this.props; @@ -26,7 +27,7 @@ class ModalFileTimeout extends React.PureComponent {

{__('LBRY was unable to download the stream')}:

- {`"${title}"`} + {title ? `"${title}"` : uri}

diff --git a/src/ui/modal/modalRevokeClaim/view.jsx b/src/ui/modal/modalRevokeClaim/view.jsx index 9178df215..ffc53d868 100644 --- a/src/ui/modal/modalRevokeClaim/view.jsx +++ b/src/ui/modal/modalRevokeClaim/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Transaction } from 'types/transaction'; import React from 'react'; import { Modal } from 'modal/modal'; import * as txnTypes from 'constants/transaction_types'; diff --git a/src/ui/page/auth/view.jsx b/src/ui/page/auth/view.jsx index 13637e304..294f7311d 100644 --- a/src/ui/page/auth/view.jsx +++ b/src/ui/page/auth/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { UrlLocation } from 'types/location'; import React from 'react'; import BusyIndicator from 'component/common/busy-indicator'; import Button from 'component/button'; diff --git a/src/ui/page/channel/view.jsx b/src/ui/page/channel/view.jsx index 88d84da30..7171bd64d 100644 --- a/src/ui/page/channel/view.jsx +++ b/src/ui/page/channel/view.jsx @@ -1,6 +1,4 @@ // @flow -import type { Claim } from 'types/claim'; -import type { UrlLocation } from 'types/location'; import * as icons from 'constants/icons'; import * as MODALS from 'constants/modal_types'; import React, { useEffect } from 'react'; @@ -19,8 +17,8 @@ type Props = { totalPages: number, fetching: boolean, params: { page: number }, - claim: Claim, - claimsInChannel: Array, + claim: ChannelClaim, + claimsInChannel: Array, channelIsMine: boolean, fetchClaims: (string, number) => void, history: { push: string => void }, @@ -82,10 +80,10 @@ function ChannelPage(props: Props) { {name} {fetching && } - {`lbry://${permanentUrl}`} + {permanentUrl}
- +
diff --git a/src/ui/page/fileListPublished/view.jsx b/src/ui/page/fileListPublished/view.jsx index b4009d790..2871286fc 100644 --- a/src/ui/page/fileListPublished/view.jsx +++ b/src/ui/page/fileListPublished/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { Claim } from 'types/claim'; import React from 'react'; import Button from 'component/button'; import FileList from 'component/fileList'; @@ -7,7 +6,7 @@ import Page from 'component/page'; import { PAGES } from 'lbry-redux'; type Props = { - claims: Array, + claims: Array, checkPendingPublishes: () => void, fetching: boolean, sortBy: string, diff --git a/src/ui/page/rewards/view.jsx b/src/ui/page/rewards/view.jsx index 91ac446d3..163cd9a33 100644 --- a/src/ui/page/rewards/view.jsx +++ b/src/ui/page/rewards/view.jsx @@ -6,7 +6,6 @@ import RewardTile from 'component/rewardTile'; import Button from 'component/button'; import Page from 'component/page'; import classnames from 'classnames'; -import type { Reward } from 'types/reward'; import { rewards as REWARD_TYPES } from 'lbryinc'; import UnsupportedOnWeb from 'component/common/unsupported-on-web'; diff --git a/src/ui/page/search/view.jsx b/src/ui/page/search/view.jsx index 97e80f753..ddf7264e5 100644 --- a/src/ui/page/search/view.jsx +++ b/src/ui/page/search/view.jsx @@ -1,5 +1,4 @@ // @flow -import type { UrlLocation } from 'types/location'; import * as ICONS from 'constants/icons'; import React, { useEffect, Fragment } from 'react'; import { isURIValid, normalizeURI, parseURI } from 'lbry-redux'; diff --git a/src/ui/page/settings/view.jsx b/src/ui/page/settings/view.jsx index fee72b638..8360cbf8a 100644 --- a/src/ui/page/settings/view.jsx +++ b/src/ui/page/settings/view.jsx @@ -9,7 +9,7 @@ import Page from 'component/page'; import FileSelector from 'component/common/file-selector'; import UnsupportedOnWeb from 'component/common/unsupported-on-web'; -export type Price = { +type Price = { currency: string, amount: number, }; diff --git a/src/ui/page/show/view.jsx b/src/ui/page/show/view.jsx index 3a99bcf61..c2c23116c 100644 --- a/src/ui/page/show/view.jsx +++ b/src/ui/page/show/view.jsx @@ -1,18 +1,16 @@ // @flow -import type { UrlLocation } from 'types/location'; import React from 'react'; import BusyIndicator from 'component/common/busy-indicator'; import ChannelPage from 'page/channel'; import FilePage from 'page/file'; import Page from 'component/page'; import Button from 'component/button'; -import type { Claim } from 'types/claim'; type Props = { isResolvingUri: boolean, resolveUri: string => void, uri: string, - claim: Claim, + claim: StreamClaim, totalPages: number, location: UrlLocation, blackListedOutpoints: Array<{ diff --git a/src/ui/page/subscriptions/internal/user-subscriptions.jsx b/src/ui/page/subscriptions/internal/user-subscriptions.jsx index 5676060ca..1d86789d1 100644 --- a/src/ui/page/subscriptions/internal/user-subscriptions.jsx +++ b/src/ui/page/subscriptions/internal/user-subscriptions.jsx @@ -1,6 +1,4 @@ // @flow -import type { ViewMode } from 'types/subscription'; -import type { Claim } from 'types/claim'; import { VIEW_ALL, VIEW_LATEST_FIRST } from 'constants/subscriptions'; import React, { Fragment } from 'react'; import Button from 'component/button'; @@ -19,7 +17,7 @@ type Props = { viewMode: ViewMode, doSetViewMode: ViewMode => void, hasSubscriptions: boolean, - subscriptions: Array<{ uri: string, ...Claim }>, + subscriptions: Array<{ uri: string, ...StreamClaim }>, autoDownload: boolean, onChangeAutoDownload: (SyntheticInputEvent<*>) => void, unreadSubscriptions: Array<{ channel: string, uris: Array }>, diff --git a/src/ui/page/subscriptions/view.jsx b/src/ui/page/subscriptions/view.jsx index 4ec2f524d..b359f8c17 100644 --- a/src/ui/page/subscriptions/view.jsx +++ b/src/ui/page/subscriptions/view.jsx @@ -1,6 +1,4 @@ // @flow -import type { ViewMode } from 'types/subscription'; -import type { Claim } from 'types/claim'; import * as SETTINGS from 'constants/settings'; import React, { PureComponent } from 'react'; import Page from 'component/page'; @@ -13,7 +11,7 @@ type Props = { channel: string, uris: Array, }>, - allSubscriptions: Array<{ uri: string, ...Claim }>, + allSubscriptions: Array<{ uri: string, ...StreamClaim }>, loading: boolean, autoDownload: boolean, viewMode: ViewMode, diff --git a/src/ui/redux/actions/content.js b/src/ui/redux/actions/content.js index 1c0934e0d..ed26bfa4e 100644 --- a/src/ui/redux/actions/content.js +++ b/src/ui/redux/actions/content.js @@ -1,5 +1,4 @@ // @flow -import type { Dispatch, GetState } from 'types/redux'; import * as NOTIFICATION_TYPES from 'constants/subscriptions'; import { PAGE_SIZE } from 'constants/claim'; import * as MODALS from 'constants/modal_types'; @@ -25,9 +24,7 @@ import { creditsToString, doError, } from 'lbry-redux'; -import { - makeSelectCostInfoForUri, -} from 'lbryinc'; +import { makeSelectCostInfoForUri } from 'lbryinc'; import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings'; import analytics from 'analytics'; import { formatLbryUriForWeb } from 'util/uri'; @@ -305,9 +302,12 @@ export function doFetchClaimsByChannel( data: { uri, page }, }); - Lbry.claim_list_by_channel({ uri, page, page_size: pageSize }).then(result => { - const claimResult = result[uri] || {}; - const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult; + // TODO: can we keep uri? + // claim_search should accept a uri (this allows for fetching vanity channel content) + const { claimId } = parseURI(uri); + + Lbry.claim_search({ channel_id: claimId, page, page_size: pageSize }).then(result => { + const { items: claimsInChannel, page: returnedPage } = result; if (claimsInChannel && claimsInChannel.length) { if (page === 1) { @@ -319,7 +319,7 @@ export function doFetchClaimsByChannel( uri: buildURI( { contentName: latest.channel_name, - claimId: latest.value.publisherSignature.certificateId, + claimId: latest.claim_id, }, false ), @@ -351,51 +351,6 @@ export function doPlayUri(uri: string) { }; } -export function doFetchChannelListMine() { - return (dispatch: Dispatch) => { - dispatch({ - type: ACTIONS.FETCH_CHANNEL_LIST_STARTED, - }); - - const callback = channels => { - dispatch({ - type: ACTIONS.FETCH_CHANNEL_LIST_COMPLETED, - data: { claims: channels }, - }); - }; - - Lbry.channel_list().then(callback); - }; -} - -export function doCreateChannel(name: string, amount: number) { - return (dispatch: Dispatch) => { - dispatch({ - type: ACTIONS.CREATE_CHANNEL_STARTED, - }); - - return new Promise((resolve, reject) => { - Lbry.channel_new({ - channel_name: name, - amount: creditsToString(amount), - }).then( - newChannelClaim => { - const channelClaim = newChannelClaim; - channelClaim.name = name; - dispatch({ - type: ACTIONS.CREATE_CHANNEL_COMPLETED, - data: { channelClaim }, - }); - resolve(channelClaim); - }, - error => { - reject(error); - } - ); - }); - }; -} - export function savePosition(claimId: string, outpoint: string, position: number) { return (dispatch: Dispatch) => { dispatch({ diff --git a/src/ui/redux/actions/publish.js b/src/ui/redux/actions/publish.js index e6fd36843..39a980957 100644 --- a/src/ui/redux/actions/publish.js +++ b/src/ui/redux/actions/publish.js @@ -1,11 +1,4 @@ // @flow -import type { Dispatch, GetState } from 'types/redux'; -import type { Metadata } from 'types/claim'; -import type { - UpdatePublishFormData, - UpdatePublishFormAction, - PublishParams, -} from 'redux/reducers/publish'; import { CC_LICENSES, COPYRIGHT, OTHER, NONE, PUBLIC_DOMAIN } from 'constants/licenses'; import * as MODALS from 'constants/modal_types'; import { @@ -29,9 +22,7 @@ import fs from 'fs'; import path from 'path'; // @endif -type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH }; - -export const doResetThumbnailStatus = () => (dispatch: Dispatch): Promise => { +export const doResetThumbnailStatus = () => (dispatch: Dispatch) => { dispatch({ type: ACTIONS.UPDATE_PUBLISH_FORM, data: { @@ -67,22 +58,20 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch): Promise (dispatch: Dispatch): Promise => { +export const doClearPublish = () => (dispatch: Dispatch) => { dispatch({ type: ACTIONS.CLEAR_PUBLISH }); return dispatch(doResetThumbnailStatus()); }; export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => ( dispatch: Dispatch -): UpdatePublishFormAction => - dispatch( - ({ - type: ACTIONS.UPDATE_PUBLISH_FORM, - data: { ...publishFormValue }, - }: UpdatePublishFormAction) - ); +) => + dispatch({ + type: ACTIONS.UPDATE_PUBLISH_FORM, + data: { ...publishFormValue }, + }); -export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: Dispatch) => { +export const doUploadThumbnail = (filePath: string) => (dispatch: Dispatch) => { const thumbnail = fs.readFileSync(filePath); const fileExt = path.extname(filePath); const fileName = path.basename(filePath); @@ -119,7 +108,7 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: const file = new File([thumbnail], fileName, { type: `image/${fileExt.slice(1)}` }); data.append('name', name); data.append('file', file); - data.append('nsfw', nsfw.toString()); + return fetch('https://spee.ch/api/claim/publish', { method: 'POST', body: data, @@ -139,15 +128,8 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: .catch(err => uploadError(err.message)); }; -export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) => { - const { - name, - amount, - channel_name: channelName, - value: { - stream: { metadata }, - }, - } = claim; +export const doPrepareEdit = (claim: StreamClaim, uri: string) => (dispatch: Dispatch) => { + const { name, amount, channel_name: channelName, value } = claim; const { author, @@ -158,26 +140,23 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) = amount: 0, currency: 'LBC', }, - language, + languages, license, - licenseUrl, - nsfw, + license_url: licenseUrl, thumbnail, title, - } = metadata; + } = value; const publishData: UpdatePublishFormData = { name, channel: channelName, bid: amount, - price: { amount: fee.amount, currency: fee.currency }, contentIsFree: !fee.amount, author, description, fee, - language, - nsfw, - thumbnail, + languages, + thumbnail: thumbnail ? thumbnail.url : null, title, uri, uploadThumbnailStatus: thumbnail ? THUMBNAIL_STATUSES.MANUAL : undefined, @@ -204,6 +183,8 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) = }; export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => { + dispatch({ type: ACTIONS.PUBLISH_START }); + const state = getState(); const myChannels = selectMyChannelClaims(state); const myClaims = selectMyClaimsWithoutChannels(state); @@ -217,55 +198,63 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat license, licenseUrl, thumbnail, - nsfw, channel, title, contentIsFree, - price, + fee, uri, + nsfw, } = params; // get the claim id from the channel name, we will use that instead const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel); const channelId = namedChannelClaim ? namedChannelClaim.claim_id : ''; - const fee = contentIsFree || !price.amount ? undefined : { ...price }; - - const metadata: Metadata = { - title, - nsfw, - license, - licenseUrl, - language, - thumbnail, - description: description || undefined, - }; const publishPayload: { name: ?string, - channel_id: string, - bid: ?number, - metadata: ?Metadata, + channel_id?: string, + bid: number, file_path?: string, + fee?: { amount: string, currency: string }, + tags: Array, } = { name, - channel_id: channelId, bid: creditsToString(bid), - metadata, + title, + license, + license_url: licenseUrl, + languages: [language], + description, + thumbnail_url: thumbnail, + tags: [], }; + // Temporary solution to keep the same publish flow with the new tags api + // Eventually we will allow users to enter their own tags on publish + // `nsfw` will probably be removed + if (nsfw) { + publishPayload.tags.push('mature'); + } + + if (channelId) { + publishPayload.channel_id = channelId; + } + if (fee) { - metadata.fee = { + publishPayload.fee = { currency: fee.currency, amount: creditsToString(fee.amount), }; } - // only pass file on new uploads, not metadata only edits. + + // Only pass file on new uploads, not metadata only edits. + // The sdk will figure it out if (filePath) publishPayload.file_path = filePath; - dispatch({ type: ACTIONS.PUBLISH_START }); - - const success = pendingClaim => { + const success = successResponse => { analytics.apiLogPublish(); + + const pendingClaim = successResponse.outputs[0]; const actions = []; actions.push({ @@ -280,8 +269,8 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat const isMatch = claim => claim.claim_id === pendingClaim.claim_id; const isEdit = myClaims.some(isMatch); const myNewClaims = isEdit - ? myClaims.map(claim => (isMatch(claim) ? pendingClaim.output : claim)) - : myClaims.concat(pendingClaim.output); + ? myClaims.map(claim => (isMatch(claim) ? pendingClaim : claim)) + : myClaims.concat(pendingClaim); actions.push({ type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED, @@ -313,7 +302,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS let publishCheckInterval; const checkFileList = () => { - Lbry.claim_list_mine().then(claims => { + Lbry.claim_list().then(claims => { claims.forEach(claim => { // If it's confirmed, check if it was pending previously if (claim.confirmations > 0 && pendingById[claim.claim_id]) { @@ -322,7 +311,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS // If it's confirmed, check if we should notify the user if (selectosNotificationsEnabled(getState())) { const notif = new window.Notification('LBRY Publish Complete', { - body: `${claim.value.stream.metadata.title} has been published to lbry://${ + body: `${claim.value.stream.title} has been published to lbry://${ claim.name }. Click here to view it`, silent: false, diff --git a/src/ui/redux/actions/subscriptions.js b/src/ui/redux/actions/subscriptions.js index deaeae1c3..80fa5d098 100644 --- a/src/ui/redux/actions/subscriptions.js +++ b/src/ui/redux/actions/subscriptions.js @@ -1,12 +1,4 @@ // @flow -import type { Dispatch, GetState } from 'types/redux'; -import type { - SubscriptionState, - Subscription, - SubscriptionNotificationType, - ViewMode, - UnreadSubscription, -} from 'types/subscription'; import { PAGE_SIZE } from 'constants/claim'; import * as ACTIONS from 'constants/action_types'; import * as SETTINGS from 'constants/settings'; @@ -239,8 +231,10 @@ export const doCheckSubscription = (subscriptionUri: string, shouldNotify?: bool ); } + const { claimId } = parseURI(subscriptionUri); + // We may be duplicating calls here. Can this logic be baked into doFetchClaimsByChannel? - Lbry.claim_list_by_channel({ uri: subscriptionUri, page: 1, page_size: PAGE_SIZE }).then( + Lbry.claim_search({ channel_id: claimId, page: 1, page_size: PAGE_SIZE }).then( claimListByChannel => { const claimResult = claimListByChannel[subscriptionUri] || {}; const { claims_in_channel: claimsInChannel } = claimResult; @@ -268,9 +262,7 @@ export const doCheckSubscription = (subscriptionUri: string, shouldNotify?: bool const uri = buildURI({ contentName: claim.name, claimId: claim.claim_id }, true); const shouldDownload = shouldAutoDownload && - Boolean( - downloadCount < SUBSCRIPTION_DOWNLOAD_LIMIT && !claim.value.stream.metadata.fee - ); + Boolean(downloadCount < SUBSCRIPTION_DOWNLOAD_LIMIT && !claim.value.stream.fee); // Add the new content to the list of "un-read" subscriptions if (shouldNotify) { diff --git a/src/ui/redux/reducers/publish.js b/src/ui/redux/reducers/publish.js index 0bae74065..43b70d66c 100644 --- a/src/ui/redux/reducers/publish.js +++ b/src/ui/redux/reducers/publish.js @@ -4,7 +4,6 @@ import { buildURI } from 'lbry-redux'; import * as ACTIONS from 'constants/action_types'; import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses'; import { CHANNEL_ANONYMOUS } from 'constants/claim'; -import type { Source } from 'types/claim'; type PublishState = { editingURI: ?string, @@ -15,7 +14,7 @@ type PublishState = { currency: string, }, title: string, - thumbnail: string, + thumbnail_url: string, thumbnailPath: string, uploadThumbnailStatus: string, description: string, @@ -30,60 +29,6 @@ type PublishState = { licenseUrl: string, }; -export type UpdatePublishFormData = { - filePath?: string, - contentIsFree?: boolean, - price?: { - amount: number, - currency: string, - }, - title?: string, - thumbnail?: string, - uploadThumbnailStatus?: string, - thumbnailPath?: string, - description?: string, - language?: string, - channel?: string, - channelId?: string, - name?: string, - nameError?: string, - bid?: number, - bidError?: string, - otherLicenseDescription?: string, - licenseUrl?: string, - licenseType?: string, - uri?: string, -}; - -export type UpdatePublishFormAction = { - type: ACTIONS.UPDATE_PUBLISH_FORM | ACTIONS.DO_PREPARE_EDIT, - data: UpdatePublishFormData, -}; - -export type PublishParams = { - name?: string, - bid?: number, - filePath?: string, - description: ?string, - language: string, - publishingLicense?: string, - publishingLicenseUrl?: string, - thumbnail: ?string, - nsfw: boolean, - channel: string, - channelId?: string, - title: string, - contentIsFree: boolean, - uri?: string, - license: ?string, - licenseUrl: ?string, - price: { - currency: string, - amount: number, - }, - sources?: Source, -}; - const defaultState: PublishState = { editingURI: undefined, filePath: undefined, @@ -93,7 +38,7 @@ const defaultState: PublishState = { currency: 'LBC', }, title: '', - thumbnail: '', + thumbnail_url: '', thumbnailPath: '', uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN, description: '', diff --git a/src/ui/redux/reducers/subscriptions.js b/src/ui/redux/reducers/subscriptions.js index fb7f8b4d0..5b1bedfad 100644 --- a/src/ui/redux/reducers/subscriptions.js +++ b/src/ui/redux/reducers/subscriptions.js @@ -2,18 +2,6 @@ import * as ACTIONS from 'constants/action_types'; import { VIEW_ALL } from 'constants/subscriptions'; import { handleActions } from 'util/redux-utils'; -import type { - SubscriptionState, - Subscription, - DoChannelSubscribe, - DoChannelUnsubscribe, - SetSubscriptionLatest, - DoUpdateSubscriptionUnreads, - DoRemoveSubscriptionUnreads, - FetchedSubscriptionsSucess, - SetViewMode, - GetSuggestedSubscriptionsSuccess, -} from 'types/subscription'; const defaultState: SubscriptionState = { subscriptions: [], diff --git a/src/ui/types/claim.js b/src/ui/types/claim.js deleted file mode 100644 index 7db1d7e28..000000000 --- a/src/ui/types/claim.js +++ /dev/null @@ -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, - }, - }, -}; diff --git a/src/ui/types/common.js b/src/ui/types/common.js deleted file mode 100644 index 5f3636de3..000000000 --- a/src/ui/types/common.js +++ /dev/null @@ -1,5 +0,0 @@ -// @flow - -export type FormikActions = { - setSubmitting: boolean => mixed, -}; diff --git a/src/ui/types/file_info.js b/src/ui/types/file_info.js deleted file mode 100644 index 07efda975..000000000 --- a/src/ui/types/file_info.js +++ /dev/null @@ -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, - }, - }, -}; diff --git a/src/ui/types/redux.js b/src/ui/types/redux.js deleted file mode 100644 index 9040b8345..000000000 --- a/src/ui/types/redux.js +++ /dev/null @@ -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 */ diff --git a/src/ui/types/status.js b/src/ui/types/status.js deleted file mode 100644 index 87c3e777e..000000000 --- a/src/ui/types/status.js +++ /dev/null @@ -1,48 +0,0 @@ -// @flow - -export type Status = { - error?: {}, - is_running: boolean, - is_first_run: boolean, - installation_id: string, - skipped_components: Array, - 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, - }, -}; diff --git a/src/ui/types/transaction.js b/src/ui/types/transaction.js deleted file mode 100644 index 37cd5f4b2..000000000 --- a/src/ui/types/transaction.js +++ /dev/null @@ -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, -}; diff --git a/static/index.html b/static/index.html index 669af8c45..4b01c9183 100644 --- a/static/index.html +++ b/static/index.html @@ -1,12 +1,17 @@ - lbry.tv + + LBRY + + + lbry.tv + diff --git a/webpack.base.config.js b/webpack.base.config.js index 234d25283..167716858 100644 --- a/webpack.base.config.js +++ b/webpack.base.config.js @@ -56,12 +56,7 @@ let baseConfig = { { test: /\.s?css$/, exclude: /\.module.scss$/, - use: [ - 'style-loader', - 'css-loader', - 'postcss-loader', - 'sass-loader', - ], + use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'], }, { test: /\.(png|svg|gif)$/, diff --git a/yarn.lock b/yarn.lock index 7c5102272..2575aa67e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3973,20 +3973,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-airbnb-base@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz#386441e54a12ccd957b0a92564a4bafebd747944" - integrity sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA== - dependencies: - eslint-restricted-globals "^0.1.1" - -eslint-config-airbnb@^16.1.0: - version "16.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz#2546bfb02cc9fe92284bf1723ccf2e87bc45ca46" - integrity sha512-zLyOhVWhzB/jwbz7IPSbkUuj7X2ox4PHXTcZkEmDqTvd0baJmJyuxlFPDlZOE/Y5bC+HQRaEkT3FoHo9wIdRiw== - dependencies: - eslint-config-airbnb-base "^12.1.0" - eslint-config-prettier@^2.9.0: version "2.10.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.10.0.tgz#ec07bc1d01f87d09f61d3840d112dc8a9791e30b" @@ -4124,11 +4110,6 @@ eslint-plugin-standard@^4.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA== -eslint-restricted-globals@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" - integrity sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc= - eslint-scope@3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" @@ -4702,10 +4683,10 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= -flow-bin@^0.94.0: - version "0.94.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.94.0.tgz#b5d58fe7559705b73a18229f97edfc3ab6ffffcb" - integrity sha512-DYF7r9CJ/AksfmmB4+q+TyLMoeQPRnqtF1Pk7KY3zgfkB/nVuA3nXyzqgsIPIvnMSiFEXQcFK4z+iPxSLckZhQ== +flow-bin@^0.97.0: + version "0.97.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.97.0.tgz#036ffcfc27503367a9d906ec9d843a0aa6f6bb83" + integrity sha512-jXjD05gkatLuC4+e28frH1hZoRwr1iASP6oJr61Q64+kR4kmzaS+AdFBhYgoYS5kpoe4UzwDebWK8ETQFNh00w== flow-typed@^2.3.0: version "2.5.1" @@ -6475,17 +6456,17 @@ lazy-val@^1.0.3, lazy-val@^1.0.4: yargs "^13.2.2" zstd-codec "^0.1.1" -lbry-redux@lbryio/lbry-redux#d4c7dea65f7179974e9b96c863022fe7b049ff7d: +lbry-redux@lbryio/lbry-redux#cc42856676541120b088e4228c04246ba8ff3274: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/d4c7dea65f7179974e9b96c863022fe7b049ff7d" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/cc42856676541120b088e4228c04246ba8ff3274" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0" uuid "^3.3.2" -lbryinc@lbryio/lbryinc#4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02: +lbryinc@lbryio/lbryinc#9665f2d1c818f1a86b2e5daab642f6879746f25f: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/4f2d4a50986bffab0b05d9f6cd7c2f0a856a0e02" + resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/9665f2d1c818f1a86b2e5daab642f6879746f25f" dependencies: reselect "^3.0.0"