Merge branch 'master' into master

This commit is contained in:
Tiago 2018-10-14 16:18:12 -03:00 committed by GitHub
commit 57fa8330e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 115 additions and 75 deletions

View file

@ -10,7 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Focus on search bar with {cmd,ctrl} + "l" ([#2003](https://github.com/lbryio/lbry-desktop/pull/2003)) * Focus on search bar with {cmd,ctrl} + "l" ([#2003](https://github.com/lbryio/lbry-desktop/pull/2003))
* Add support for clickable channel names on explore page headings ([#2023](https://github.com/lbryio/lbry-desktop/pull/2023)) * Add support for clickable channel names on explore page headings ([#2023](https://github.com/lbryio/lbry-desktop/pull/2023))
* Content loading placeholder styles on FileCard/FileTile ([#2022](https://github.com/lbryio/lbry-desktop/pull/2022)) * Content loading placeholder styles on FileCard/FileTile ([#2022](https://github.com/lbryio/lbry-desktop/pull/2022))
### Changed ### Changed
* Make tooltip smarter ([#1979](https://github.com/lbryio/lbry-desktop/pull/1979)) * Make tooltip smarter ([#1979](https://github.com/lbryio/lbry-desktop/pull/1979))
* Change channel pages to have 48 items instead of 10 ([#2002](https://github.com/lbryio/lbry-desktop/pull/2002)) * Change channel pages to have 48 items instead of 10 ([#2002](https://github.com/lbryio/lbry-desktop/pull/2002))
@ -18,6 +18,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Simplify FileCard and FileTile component styling ([#2011](https://github.com/lbryio/lbry-desktop/pull/2011)) * Simplify FileCard and FileTile component styling ([#2011](https://github.com/lbryio/lbry-desktop/pull/2011))
* Credit card verification messaging ([#2025](https://github.com/lbryio/lbry-desktop/pull/2025)) * Credit card verification messaging ([#2025](https://github.com/lbryio/lbry-desktop/pull/2025))
* Reverse Order & Use System/Location Time/Date ([#2036]https://github.com/lbryio/lbry-desktop/pull/2036) * Reverse Order & Use System/Location Time/Date ([#2036]https://github.com/lbryio/lbry-desktop/pull/2036)
* Limit file type can be uploaded as thumbnail for publishing ([#2034](https://github.com/lbryio/lbry-desktop/pull/2034))
### Fixed ### Fixed
* Fixed Transactions filter menu collides with transaction table ([#2005](https://github.com/lbryio/lbry-desktop/pull/2005)) * Fixed Transactions filter menu collides with transaction table ([#2005](https://github.com/lbryio/lbry-desktop/pull/2005))

View file

@ -5,12 +5,18 @@ import Button from 'component/button';
import { FormRow } from 'component/common/form'; import { FormRow } from 'component/common/form';
import path from 'path'; import path from 'path';
type FileFilters = {
name: string,
extensions: string[],
};
type Props = { type Props = {
type: string, type: string,
currentPath: ?string, currentPath: ?string,
onFileChosen: (string, string) => void, onFileChosen: (string, string) => void,
fileLabel?: string, fileLabel?: string,
directoryLabel?: string, directoryLabel?: string,
filters?: FileFilters[],
}; };
class FileSelector extends React.PureComponent<Props> { class FileSelector extends React.PureComponent<Props> {
@ -29,6 +35,7 @@ class FileSelector extends React.PureComponent<Props> {
{ {
properties: properties:
this.props.type === 'file' ? ['openFile'] : ['openDirectory', 'createDirectory'], this.props.type === 'file' ? ['openFile'] : ['openDirectory', 'createDirectory'],
filters: this.props.filters,
}, },
paths => { paths => {
if (!paths) { if (!paths) {

View file

@ -52,7 +52,7 @@ type Props = {
clearPublish: () => void, clearPublish: () => void,
resolveUri: string => void, resolveUri: string => void,
scrollToTop: () => void, scrollToTop: () => void,
prepareEdit: ({}) => void, prepareEdit: (claim: any, uri: string) => void,
resetThumbnailStatus: () => void, resetThumbnailStatus: () => void,
amountNeededForTakeover: ?number, amountNeededForTakeover: ?number,
}; };
@ -107,11 +107,7 @@ class PublishForm extends React.PureComponent<Props> {
handleFileChange(filePath: string, fileName: string) { handleFileChange(filePath: string, fileName: string) {
const { updatePublishForm, channel, name } = this.props; const { updatePublishForm, channel, name } = this.props;
const newFileParams: { const newFileParams: UpdatePublishFormData = { filePath };
filePath: string,
name?: string,
uri?: string,
} = { filePath };
if (!name) { if (!name) {
const parsedFileName = fileName.replace(regexInvalidURI, ''); const parsedFileName = fileName.replace(regexInvalidURI, '');
@ -127,7 +123,7 @@ class PublishForm extends React.PureComponent<Props> {
const { channel, updatePublishForm } = this.props; const { channel, updatePublishForm } = this.props;
if (!name) { if (!name) {
updatePublishForm({ name, nameError: undefined }); updatePublishForm({ nameError: undefined });
return; return;
} }
@ -149,7 +145,7 @@ class PublishForm extends React.PureComponent<Props> {
handleChannelChange(channelName: string) { handleChannelChange(channelName: string) {
const { name, updatePublishForm } = this.props; const { name, updatePublishForm } = this.props;
const form = { channel: channelName }; const form: UpdatePublishFormData = { channel: channelName };
if (name) { if (name) {
form.uri = this.getNewUri(name, channelName); form.uri = this.getNewUri(name, channelName);
@ -217,10 +213,10 @@ class PublishForm extends React.PureComponent<Props> {
const publishingLicenseUrl = licenseType === COPYRIGHT ? '' : licenseUrl; const publishingLicenseUrl = licenseType === COPYRIGHT ? '' : licenseUrl;
const publishParams = { const publishParams: PublishParams = {
filePath, filePath: filePath || undefined,
bid: this.props.bid, bid: this.props.bid || undefined,
title: this.props.title, title: this.props.title || '',
thumbnail: this.props.thumbnail, thumbnail: this.props.thumbnail,
description: this.props.description, description: this.props.description,
language: this.props.language, language: this.props.language,
@ -228,16 +224,16 @@ class PublishForm extends React.PureComponent<Props> {
license: publishingLicense, license: publishingLicense,
licenseUrl: publishingLicenseUrl, licenseUrl: publishingLicenseUrl,
otherLicenseDescription, otherLicenseDescription,
name: this.props.name, name: this.props.name || undefined,
contentIsFree: this.props.contentIsFree, contentIsFree: this.props.contentIsFree,
price: this.props.price, price: this.props.price,
uri: this.props.uri, uri: this.props.uri || undefined,
channel: this.props.channel, channel: this.props.channel,
isStillEditing: this.props.isStillEditing, isStillEditing: this.props.isStillEditing,
}; };
// Editing a claim // Editing a claim
if (!filePath && myClaimForUri) { if (!filePath && myClaimForUri && myClaimForUri.value) {
const { source } = myClaimForUri.value.stream; const { source } = myClaimForUri.value.stream;
publishParams.sources = source; publishParams.sources = source;
} }

View file

@ -51,6 +51,12 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
thumbnailPath, thumbnailPath,
resetThumbnailStatus, resetThumbnailStatus,
} = this.props; } = this.props;
const filters = [
{
name: __('Thumbnail Image'),
extensions: ['png', 'jpg', 'jpeg', 'gif'],
},
];
const { thumbnailError, thumbnailErrorImage } = this.state; const { thumbnailError, thumbnailErrorImage } = this.state;
const thumbnailSrc = const thumbnailSrc =
!thumbnail || thumbnailError ? Native.imagePath(thumbnailErrorImage) : thumbnail; !thumbnail || thumbnailError ? Native.imagePath(thumbnailErrorImage) : thumbnail;
@ -67,7 +73,7 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? ( {status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
<div className="column"> <div className="column">
<div <div
className="column__item thumbnail-preview card__media" className="column__item thumbnail-preview"
style={{ backgroundImage: `url(${thumbnailSrc})` }} style={{ backgroundImage: `url(${thumbnailSrc})` }}
> >
<img <img
@ -111,6 +117,7 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
<FileSelector <FileSelector
currentPath={thumbnailPath} currentPath={thumbnailPath}
fileLabel={__('Choose Thumbnail')} fileLabel={__('Choose Thumbnail')}
filters={filters}
onFileChosen={path => openModal({ id: MODALS.CONFIRM_THUMBNAIL_UPLOAD }, { path })} onFileChosen={path => openModal({ id: MODALS.CONFIRM_THUMBNAIL_UPLOAD }, { path })}
/> />
)} )}

View file

@ -16,6 +16,7 @@ type DaemonSettings = {
download_directory: string, download_directory: string,
disable_max_key_fee: boolean, disable_max_key_fee: boolean,
share_usage_data: boolean, share_usage_data: boolean,
max_key_fee?: Price,
}; };
type Props = { type Props = {
@ -34,6 +35,7 @@ type Props = {
autoDownload: boolean, autoDownload: boolean,
encryptWallet: () => void, encryptWallet: () => void,
decryptWallet: () => void, decryptWallet: () => void,
updateWalletStatus: () => void,
walletEncrypted: boolean, walletEncrypted: boolean,
osNotificationsEnabled: boolean, osNotificationsEnabled: boolean,
}; };
@ -65,10 +67,8 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
componentDidMount() { componentDidMount() {
const { props } = this; this.props.getThemes();
this.props.updateWalletStatus();
props.getThemes();
props.updateWalletStatus();
} }
onRunOnStartChange(event: SyntheticInputEvent<*>) { onRunOnStartChange(event: SyntheticInputEvent<*>) {
@ -126,18 +126,22 @@ class SettingsPage extends React.PureComponent<Props, State> {
} }
onChangeEncryptWallet() { onChangeEncryptWallet() {
const { props } = this; const { decryptWallet, walletEncrypted, encryptWallet } = this.props;
props.walletEncrypted ? props.decryptWallet() : props.encryptWallet(); if (walletEncrypted) {
} decryptWallet();
} else {
setDaemonSetting(name: string, value: boolean | string | Price) { encryptWallet();
this.props.setDaemonSetting(name, value); }
} }
onDesktopNotificationsChange(event: SyntheticInputEvent<*>) { onDesktopNotificationsChange(event: SyntheticInputEvent<*>) {
this.props.setClientSetting(settings.OS_NOTIFICATIONS_ENABLED, event.target.checked); this.props.setClientSetting(settings.OS_NOTIFICATIONS_ENABLED, event.target.checked);
} }
setDaemonSetting(name: string, value: boolean | string | Price) {
this.props.setDaemonSetting(name, value);
}
clearCache() { clearCache() {
this.setState({ this.setState({
clearingCache: true, clearingCache: true,
@ -346,7 +350,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
<FormField <FormField
type="checkbox" type="checkbox"
name="encrypt_wallet" name="encrypt_wallet"
onChange={e => this.onChangeEncryptWallet(e)} onChange={() => this.onChangeEncryptWallet()}
checked={walletEncrypted} checked={walletEncrypted}
postfix={__('Encrypt my wallet with a custom password.')} postfix={__('Encrypt my wallet with a custom password.')}
helper={ helper={

View file

@ -19,13 +19,12 @@ import { doNavigate } from 'redux/actions/navigation';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { CC_LICENSES, COPYRIGHT, OTHER } from 'constants/licenses'; import { CC_LICENSES, COPYRIGHT, OTHER } from 'constants/licenses';
import type { Dispatch, GetState } from 'types/redux';
import type { Source } from 'types/claim';
type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH }; type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH };
type PromiseAction = Promise<Action>;
type Dispatch = (action: Action | PromiseAction | Array<Action>) => any;
type GetState = () => {};
export const doResetThumbnailStatus = () => (dispatch: Dispatch): PromiseAction => { export const doResetThumbnailStatus = () => (dispatch: Dispatch<Action>): Promise<Action> => {
dispatch({ dispatch({
type: ACTIONS.UPDATE_PUBLISH_FORM, type: ACTIONS.UPDATE_PUBLISH_FORM,
data: { data: {
@ -61,20 +60,24 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch): PromiseAction
); );
}; };
export const doClearPublish = () => (dispatch: Dispatch): PromiseAction => { export const doClearPublish = () => (dispatch: Dispatch<Action>): Promise<Action> => {
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<Action>
): UpdatePublishFormAction => ): UpdatePublishFormAction =>
dispatch({ dispatch(
type: ACTIONS.UPDATE_PUBLISH_FORM, ({
data: { ...publishFormValue }, type: ACTIONS.UPDATE_PUBLISH_FORM,
}); data: { ...publishFormValue },
}: UpdatePublishFormAction)
);
export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: Dispatch) => { export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (
dispatch: Dispatch<Action>
) => {
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);
@ -128,7 +131,7 @@ 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: any, uri: string) => (dispatch: Dispatch<Action>) => {
const { const {
name, name,
amount, amount,
@ -155,7 +158,7 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) =
title, title,
} = metadata; } = metadata;
const publishData = { const publishData: UpdatePublishFormData = {
name, name,
channel: channelName, channel: channelName,
bid: amount, bid: amount,
@ -189,7 +192,10 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) =
dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData }); dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData });
}; };
export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => { export const doPublish = (params: PublishParams) => (
dispatch: Dispatch<Action>,
getState: () => {}
) => {
const state = getState(); const state = getState();
const myChannels = selectMyChannelClaims(state); const myChannels = selectMyChannelClaims(state);
@ -223,17 +229,18 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
licenseUrl, licenseUrl,
language, language,
thumbnail, thumbnail,
fee: fee || undefined,
description: description || undefined,
}; };
if (fee) { const publishPayload: {
metadata.fee = fee; name: ?string,
} channel_id: string,
bid: ?number,
if (description) { metadata: ?any,
metadata.description = description; file_path?: string,
} sources?: Source,
} = {
const publishPayload = {
name, name,
channel_id: channelId, channel_id: channelId,
bid, bid,
@ -265,7 +272,7 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
}; };
// Calls claim_list_mine until any pending publishes are confirmed // Calls claim_list_mine until any pending publishes are confirmed
export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetState) => { export const doCheckPendingPublishes = () => (dispatch: Dispatch<Action>, getState: GetState) => {
const state = getState(); const state = getState();
const pendingPublishes = selectPendingPublishes(state); const pendingPublishes = selectPendingPublishes(state);

View file

@ -14,6 +14,7 @@ import type {
GetActiveShiftFail, GetActiveShiftFail,
} from 'redux/reducers/shape_shift'; } from 'redux/reducers/shape_shift';
import type { FormikActions } from 'types/common'; import type { FormikActions } from 'types/common';
import type { Dispatch, ThunkAction } from 'types/redux';
// use promise chains instead of callbacks for shapeshift api // use promise chains instead of callbacks for shapeshift api
const shapeShift = Promise.promisifyAll(require('shapeshift.io')); const shapeShift = Promise.promisifyAll(require('shapeshift.io'));
@ -38,9 +39,6 @@ export type Action =
// Basic thunk types // Basic thunk types
// It would be nice to import these from types/common // It would be nice to import these from types/common
// Not sure how that would work since they rely on the Action type // Not sure how that would work since they rely on the Action type
type PromiseAction = Promise<Action>;
export type Dispatch = (action: Action | PromiseAction | Array<Action>) => any;
type ThunkAction = (dispatch: Dispatch) => any;
// ShapeShift form values // ShapeShift form values
export type ShapeShiftFormValues = { export type ShapeShiftFormValues = {
@ -49,7 +47,7 @@ export type ShapeShiftFormValues = {
receiveAddress: string, receiveAddress: string,
}; };
export const getCoinStats = (coin: string) => (dispatch: Dispatch): ThunkAction => { export const getCoinStats = (coin: string) => (dispatch: Dispatch<Action>): ThunkAction<Action> => {
const pair = `${coin.toLowerCase()}_lbc`; const pair = `${coin.toLowerCase()}_lbc`;
dispatch({ type: ACTIONS.GET_COIN_STATS_START, data: coin }); dispatch({ type: ACTIONS.GET_COIN_STATS_START, data: coin });
@ -60,7 +58,7 @@ export const getCoinStats = (coin: string) => (dispatch: Dispatch): ThunkAction
.catch(err => dispatch({ type: ACTIONS.GET_COIN_STATS_FAIL, data: err })); .catch(err => dispatch({ type: ACTIONS.GET_COIN_STATS_FAIL, data: err }));
}; };
export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => { export const shapeShiftInit = () => (dispatch: Dispatch<Action>): ThunkAction<Action> => {
dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_START }); dispatch({ type: ACTIONS.GET_SUPPORTED_COINS_START });
return shapeShift return shapeShift
@ -94,8 +92,8 @@ export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
}; };
export const createShapeShift = (values: ShapeShiftFormValues, actions: FormikActions) => ( export const createShapeShift = (values: ShapeShiftFormValues, actions: FormikActions) => (
dispatch: Dispatch dispatch: Dispatch<Action>
): ThunkAction => { ): ThunkAction<Action> => {
const { originCoin, returnAddress, receiveAddress: withdrawalAddress } = values; const { originCoin, returnAddress, receiveAddress: withdrawalAddress } = values;
const pair = `${originCoin.toLowerCase()}_lbc`; const pair = `${originCoin.toLowerCase()}_lbc`;
@ -114,7 +112,9 @@ export const createShapeShift = (values: ShapeShiftFormValues, actions: FormikAc
}); });
}; };
export const getActiveShift = (depositAddress: string) => (dispatch: Dispatch): ThunkAction => { export const getActiveShift = (depositAddress: string) => (
dispatch: Dispatch<Action>
): ThunkAction<Action> => {
dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_START }); dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_START });
return shapeShift return shapeShift
@ -123,5 +123,5 @@ export const getActiveShift = (depositAddress: string) => (dispatch: Dispatch):
.catch(err => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_FAIL, data: err })); .catch(err => dispatch({ type: ACTIONS.GET_ACTIVE_SHIFT_FAIL, data: err }));
}; };
export const clearShapeShift = () => (dispatch: Dispatch): Action => export const clearShapeShift = () => (dispatch: Dispatch<Action>): Action =>
dispatch({ type: ACTIONS.CLEAR_SHAPE_SHIFT }); dispatch({ type: ACTIONS.CLEAR_SHAPE_SHIFT });

View file

@ -4,6 +4,7 @@ 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,
@ -53,6 +54,8 @@ export type UpdatePublishFormData = {
bidError?: string, bidError?: string,
otherLicenseDescription?: string, otherLicenseDescription?: string,
licenseUrl?: string, licenseUrl?: string,
licenseType?: string,
uri?: string,
}; };
export type UpdatePublishFormAction = { export type UpdatePublishFormAction = {
@ -61,32 +64,27 @@ export type UpdatePublishFormAction = {
}; };
export type PublishParams = { export type PublishParams = {
name: string, name?: string,
bid: number, bid?: number,
filePath: string, filePath?: string,
description: ?string, description: ?string,
language: string, language: string,
publishingLicense: string, publishingLicense?: string,
publishingLicenseUrl: string, publishingLicenseUrl?: string,
thumbnail: ?string, thumbnail: ?string,
nsfw: boolean, nsfw: boolean,
channel: string, channel: string,
channelId: string, channelId?: string,
title: string, title: string,
contentIsFree: boolean, contentIsFree: boolean,
uri: string, uri?: string,
license: ?string, license: ?string,
licenseUrl: ?string, licenseUrl: ?string,
price: { price: {
currency: string, currency: string,
amount: number, amount: number,
}, },
source?: { sources?: Source,
contentType: string,
source: string,
sourceType: string,
version: string,
},
}; };
const defaultState: PublishState = { const defaultState: PublishState = {

View file

@ -3,6 +3,7 @@ import * as ACTIONS from 'constants/action_types';
import * as NOTIFICATION_TYPES from 'constants/notification_types'; import * as NOTIFICATION_TYPES from 'constants/notification_types';
import { handleActions } from 'util/redux-utils'; import { handleActions } from 'util/redux-utils';
import type { Subscription } from 'types/subscription'; import type { Subscription } from 'types/subscription';
import type { Dispatch as ReduxDispatch } from 'types/redux';
export type NotificationType = export type NotificationType =
| NOTIFICATION_TYPES.DOWNLOADING | NOTIFICATION_TYPES.DOWNLOADING
@ -79,7 +80,7 @@ export type Action =
| CheckSubscriptionStarted | CheckSubscriptionStarted
| CheckSubscriptionCompleted | CheckSubscriptionCompleted
| Function; | Function;
export type Dispatch = (action: Action) => any; export type Dispatch = ReduxDispatch<Action>;
const defaultState = { const defaultState = {
subscriptions: [], subscriptions: [],

View file

@ -382,4 +382,7 @@ p {
.thumbnail-preview { .thumbnail-preview {
height: var(--thumbnail-preview-height); height: var(--thumbnail-preview-height);
width: var(--thumbnail-preview-width); width: var(--thumbnail-preview-width);
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
} }

View file

@ -1,6 +1,14 @@
// @flow // @flow
// Currently incomplete // Currently incomplete
export type Source = {
contentType: string,
source: string,
sourceType: string,
version: string,
};
export type Metadata = { export type Metadata = {
nsfw: boolean, nsfw: boolean,
title: string, title: string,
@ -36,6 +44,7 @@ export type Claim = {
}, },
stream: { stream: {
metadata: Metadata, metadata: Metadata,
source: Source,
}, },
}, },
}; };

View file

@ -0,0 +1,6 @@
// @flow
// eslint-disable-next-line no-use-before-define
export type Dispatch<T> = (action: T | Promise<T> | Array<T> | ThunkAction<T>) => any; // Need to refer to ThunkAction
export type GetState = () => {};
export type ThunkAction<T> = (dispatch: Dispatch<T>, getState: GetState) => any;