commit
5ce7152bba
26 changed files with 215 additions and 151 deletions
|
@ -50,7 +50,7 @@
|
||||||
"hast-util-sanitize": "^1.1.2",
|
"hast-util-sanitize": "^1.1.2",
|
||||||
"keytar": "^4.2.1",
|
"keytar": "^4.2.1",
|
||||||
"lbry-redux": "lbryio/lbry-redux#1ed2ea8b2de99bbcba652aa7b00478d02df4a290",
|
"lbry-redux": "lbryio/lbry-redux#1ed2ea8b2de99bbcba652aa7b00478d02df4a290",
|
||||||
"lbryinc": "lbryio/lbryinc#82308ece97188747adbf6d71d55b6e7a6fa0bd95",
|
"lbryinc": "lbryio/lbryinc#e9508e259fa9bce3b69915b91534516cf5937075",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"mammoth": "^1.4.6",
|
"mammoth": "^1.4.6",
|
||||||
"mime": "^2.3.1",
|
"mime": "^2.3.1",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Claim } from 'types/claim';
|
import type { Claim } from 'types/claim';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as React from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { normalizeURI } from 'lbry-redux';
|
import { normalizeURI } from 'lbry-redux';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
import FileCard from 'component/fileCard';
|
import FileCard from 'component/fileCard';
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
text: string,
|
text: ?string,
|
||||||
lines: number,
|
lines: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {
|
||||||
makeSelectCostInfoForUri,
|
makeSelectCostInfoForUri,
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
doOpenModal,
|
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import FileActions from './view';
|
import FileActions from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
makeSelectContentPositionForUri,
|
makeSelectContentPositionForUri,
|
||||||
} from 'redux/selectors/content';
|
} from 'redux/selectors/content';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
import { makeSelectIsSubscribed, makeSelectIsNew } from 'redux/selectors/subscriptions';
|
||||||
import { doClearContentHistoryUri } from 'redux/actions/content';
|
import { doClearContentHistoryUri } from 'redux/actions/content';
|
||||||
import FileCard from './view';
|
import FileCard from './view';
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ const select = (state, props) => ({
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
position: makeSelectContentPositionForUri(props.uri)(state),
|
position: makeSelectContentPositionForUri(props.uri)(state),
|
||||||
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||||
|
isNew: makeSelectIsNew(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -23,7 +23,7 @@ const select = (state, props) => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
openFolder: path => dispatch(doOpenFileInFolder(path)),
|
openFolder: path => dispatch(doOpenFileInFolder(path)),
|
||||||
showSnackBar: message => dispatch(doToast(message)),
|
showSnackBar: message => dispatch(doToast({ message })),
|
||||||
clickCommentButton: () => dispatch(doClickCommentButton()),
|
clickCommentButton: () => dispatch(doClickCommentButton()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doClearPublish, doUpdatePublishForm } from 'redux/actions/publish';
|
import { doClearPublish, doUpdatePublishForm } from 'redux/actions/publish';
|
||||||
import { selectRewardContentClaimIds } from 'redux/selectors/content';
|
import { selectRewardContentClaimIds } from 'redux/selectors/content';
|
||||||
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
import { makeSelectIsSubscribed, makeSelectIsNew } from 'redux/selectors/subscriptions';
|
||||||
import FileTile from './view';
|
import FileTile from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
@ -23,6 +23,7 @@ const select = (state, props) => ({
|
||||||
obscureNsfw: !selectShowNsfw(state),
|
obscureNsfw: !selectShowNsfw(state),
|
||||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
isSubscribed: makeSelectIsSubscribed(props.uri)(state),
|
||||||
|
isNew: makeSelectIsNew(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -30,6 +30,7 @@ type Props = {
|
||||||
displayDescription?: boolean,
|
displayDescription?: boolean,
|
||||||
size: string,
|
size: string,
|
||||||
isSubscribed: boolean,
|
isSubscribed: boolean,
|
||||||
|
isNew: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileTile extends React.PureComponent<Props> {
|
class FileTile extends React.PureComponent<Props> {
|
||||||
|
@ -49,12 +50,21 @@ class FileTile extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFileProperties() {
|
renderFileProperties() {
|
||||||
const { isSubscribed, isDownloaded, claim, uri, rewardedContentClaimIds, size } = this.props;
|
const {
|
||||||
|
isSubscribed,
|
||||||
|
isDownloaded,
|
||||||
|
claim,
|
||||||
|
uri,
|
||||||
|
rewardedContentClaimIds,
|
||||||
|
size,
|
||||||
|
isNew,
|
||||||
|
} = this.props;
|
||||||
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames('card__file-properties', { card__subtitle: size === 'large' })}>
|
<div className={classnames('card__file-properties', { card__subtitle: size === 'large' })}>
|
||||||
<FilePrice hideFree uri={uri} />
|
<FilePrice hideFree uri={uri} />
|
||||||
|
{isNew && <span className="badge badge--alert icon">{__('NEW')}</span>}
|
||||||
{isSubscribed && <Icon icon={ICONS.HEART} />}
|
{isSubscribed && <Icon icon={ICONS.HEART} />}
|
||||||
{isRewardContent && <Icon iconColor="red" icon={ICONS.FEATURED} />}
|
{isRewardContent && <Icon iconColor="red" icon={ICONS.FEATURED} />}
|
||||||
{isDownloaded && <Icon icon={ICONS.LOCAL} />}
|
{isDownloaded && <Icon icon={ICONS.LOCAL} />}
|
||||||
|
|
10
src/renderer/component/subscribeMarkAsRead/index.js
Normal file
10
src/renderer/component/subscribeMarkAsRead/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { doRemoveUnreadSubscriptions } from 'redux/actions/subscriptions';
|
||||||
|
import MarkAsRead from './view';
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
doRemoveUnreadSubscriptions,
|
||||||
|
}
|
||||||
|
)(MarkAsRead);
|
42
src/renderer/component/subscribeMarkAsRead/view.jsx
Normal file
42
src/renderer/component/subscribeMarkAsRead/view.jsx
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// @flow
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import Button from 'component/button';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
channel: ?string,
|
||||||
|
doRemoveUnreadSubscriptions: (?string) => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class MarkAsRead extends PureComponent<Props> {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
(this: any).handleClick = this.handleClick.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick() {
|
||||||
|
const { channel, doRemoveUnreadSubscriptions } = this.props;
|
||||||
|
|
||||||
|
// If there is no channel, mark all as read
|
||||||
|
// If there is a channel, only mark that channel as read
|
||||||
|
if (channel) {
|
||||||
|
doRemoveUnreadSubscriptions(channel);
|
||||||
|
} else {
|
||||||
|
doRemoveUnreadSubscriptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { channel } = this.props;
|
||||||
|
const label = channel ? __('Mark as read') : __('Mark all as read');
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
noPadding
|
||||||
|
button="inverse"
|
||||||
|
icon={ICONS.CHECK_SIMPLE}
|
||||||
|
label={label}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,8 @@ export default function doLogWarningConsoleMessage(activeOnDev = false) {
|
||||||
if (isDev && !activeOnDev) return;
|
if (isDev && !activeOnDev) return;
|
||||||
const style = {
|
const style = {
|
||||||
redTitle:
|
redTitle:
|
||||||
'color: red; font-size: 50px; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;, font-weight: bold;',
|
'color: red; font-size: 36px; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;, font-weight: bold;',
|
||||||
normalText: 'font-size: 24px;',
|
normalText: 'font-size: 18px;',
|
||||||
redText:
|
redText:
|
||||||
'color: red; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; font-size: 24px;',
|
'color: red; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; font-size: 24px;',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchClaimsByChannel, doFetchClaimCountByChannel } from 'redux/actions/content';
|
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
||||||
import { PAGE_SIZE } from 'constants/claim';
|
import { PAGE_SIZE } from 'constants/claim';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
|
@ -26,7 +26,6 @@ const select = (state, props) => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
|
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
|
||||||
fetchClaimCount: uri => dispatch(doFetchClaimCountByChannel(uri)),
|
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,28 +22,22 @@ type Props = {
|
||||||
claimsInChannel: Array<Claim>,
|
claimsInChannel: Array<Claim>,
|
||||||
channelIsMine: boolean,
|
channelIsMine: boolean,
|
||||||
fetchClaims: (string, number) => void,
|
fetchClaims: (string, number) => void,
|
||||||
fetchClaimCount: string => void,
|
|
||||||
navigate: (string, {}) => void,
|
navigate: (string, {}) => void,
|
||||||
openModal: ({ id: string }, { uri: string }) => void,
|
openModal: ({ id: string }, { uri: string }) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChannelPage extends React.PureComponent<Props> {
|
class ChannelPage extends React.PureComponent<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { uri, page, fetchClaims, fetchClaimCount } = this.props;
|
const { uri, page, fetchClaims } = this.props;
|
||||||
|
|
||||||
fetchClaims(uri, page || 1);
|
fetchClaims(uri, page || 1);
|
||||||
fetchClaimCount(uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: Props) {
|
componentWillReceiveProps(nextProps: Props) {
|
||||||
const { page, uri, fetchClaims, fetchClaimCount } = this.props;
|
const { page, fetchClaims } = this.props;
|
||||||
|
|
||||||
if (nextProps.page && page !== nextProps.page) {
|
if (nextProps.page && page !== nextProps.page) {
|
||||||
fetchClaims(nextProps.uri, nextProps.page);
|
fetchClaims(nextProps.uri, nextProps.page);
|
||||||
}
|
}
|
||||||
if (nextProps.uri !== uri) {
|
|
||||||
fetchClaimCount(uri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changePage(pageNumber: number) {
|
changePage(pageNumber: number) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import FileCard from 'component/fileCard';
|
||||||
import { parseURI } from 'lbry-redux';
|
import { parseURI } from 'lbry-redux';
|
||||||
import Native from 'native';
|
import Native from 'native';
|
||||||
import SuggestedSubscriptions from 'component/subscribeSuggested';
|
import SuggestedSubscriptions from 'component/subscribeSuggested';
|
||||||
|
import MarkAsRead from 'component/subscribeMarkAsRead';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
viewMode: ViewMode,
|
viewMode: ViewMode,
|
||||||
|
@ -90,7 +91,10 @@ export default (props: Props) => {
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
{viewMode === VIEW_ALL && (
|
{viewMode === VIEW_ALL && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="card__title">{__('Your subscriptions')}</div>
|
<div className="card__title card__actions card__actions--no-margin">
|
||||||
|
{__('Your subscriptions')}
|
||||||
|
{unreadSubscriptions.length > 0 && <MarkAsRead />}
|
||||||
|
</div>
|
||||||
<FileList hideFilter sortByHeight fileInfos={subscriptions} />
|
<FileList hideFilter sortByHeight fileInfos={subscriptions} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
@ -102,16 +106,17 @@ export default (props: Props) => {
|
||||||
const { claimName } = parseURI(channel);
|
const { claimName } = parseURI(channel);
|
||||||
return (
|
return (
|
||||||
<section key={channel}>
|
<section key={channel}>
|
||||||
<div className="card__title">
|
<div className="card__title card__actions card__actions--no-margin">
|
||||||
<Button
|
<Button
|
||||||
button="link"
|
button="link"
|
||||||
navigate="/show"
|
navigate="/show"
|
||||||
navigateParams={{ uri: channel }}
|
navigateParams={{ uri: channel }}
|
||||||
label={claimName}
|
label={claimName}
|
||||||
/>
|
/>
|
||||||
|
<MarkAsRead channel={channel} />
|
||||||
</div>
|
</div>
|
||||||
<div className="card__list card__content">
|
<div className="card__list card__content">
|
||||||
{uris.map(uri => <FileCard isNew key={uri} uri={uri} />)}
|
{uris.map(uri => <FileCard key={uri} uri={uri} />)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -120,7 +125,7 @@ export default (props: Props) => {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="page__empty">
|
<div className="page__empty">
|
||||||
<h3 className="card__title">{__('All caught up!')}</h3>
|
<h3 className="card__title">{__('All caught up!')}</h3>
|
||||||
<p className="card__subtitle">{__('You might like these channels.')}</p>
|
<p className="card__subtitle">{__('You might like these channels below.')}</p>
|
||||||
</div>
|
</div>
|
||||||
<SuggestedSubscriptions />
|
<SuggestedSubscriptions />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -4,12 +4,7 @@ import path from 'path';
|
||||||
import { ipcRenderer, remote } from 'electron';
|
import { ipcRenderer, remote } from 'electron';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import {
|
import { Lbry, doBalanceSubscribe, doFetchFileInfosAndPublishedClaims, doError } from 'lbry-redux';
|
||||||
Lbry,
|
|
||||||
doBalanceSubscribe,
|
|
||||||
doFetchFileInfosAndPublishedClaims,
|
|
||||||
selectNotification,
|
|
||||||
} from 'lbry-redux';
|
|
||||||
import Native from 'native';
|
import Native from 'native';
|
||||||
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
||||||
import { doAuthNavigate } from 'redux/actions/navigation';
|
import { doAuthNavigate } from 'redux/actions/navigation';
|
||||||
|
@ -23,8 +18,9 @@ import {
|
||||||
selectAutoUpdateDeclined,
|
selectAutoUpdateDeclined,
|
||||||
selectRemoteVersion,
|
selectRemoteVersion,
|
||||||
selectUpgradeTimer,
|
selectUpgradeTimer,
|
||||||
|
selectModal,
|
||||||
} from 'redux/selectors/app';
|
} from 'redux/selectors/app';
|
||||||
import { doAuthenticate, doFetchRewardedContent } from 'lbryinc';
|
import { doAuthenticate } from 'lbryinc';
|
||||||
import { lbrySettings as config, version as appVersion } from 'package.json';
|
import { lbrySettings as config, version as appVersion } from 'package.json';
|
||||||
|
|
||||||
const { autoUpdater } = remote.require('electron-updater');
|
const { autoUpdater } = remote.require('electron-updater');
|
||||||
|
@ -33,6 +29,22 @@ const Fs = remote.require('fs');
|
||||||
|
|
||||||
const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000;
|
const CHECK_UPGRADE_INTERVAL = 10 * 60 * 1000;
|
||||||
|
|
||||||
|
export function doOpenModal(id, modalProps = {}) {
|
||||||
|
return {
|
||||||
|
type: ACTIONS.SHOW_MODAL,
|
||||||
|
data: {
|
||||||
|
id,
|
||||||
|
modalProps,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doHideModal() {
|
||||||
|
return {
|
||||||
|
type: ACTIONS.HIDE_MODAL,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function doUpdateDownloadProgress(percent) {
|
export function doUpdateDownloadProgress(percent) {
|
||||||
return {
|
return {
|
||||||
type: ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED,
|
type: ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED,
|
||||||
|
@ -88,9 +100,7 @@ export function doDownloadUpgrade() {
|
||||||
type: ACTIONS.UPGRADE_DOWNLOAD_STARTED,
|
type: ACTIONS.UPGRADE_DOWNLOAD_STARTED,
|
||||||
});
|
});
|
||||||
dispatch(doHideModal());
|
dispatch(doHideModal());
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.DOWNLOADING));
|
||||||
doOpenModal(MODALS.DOWNLOADING)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,15 +119,11 @@ export function doDownloadUpgradeRequested() {
|
||||||
// electron-updater behavior
|
// electron-updater behavior
|
||||||
if (autoUpdateDeclined) {
|
if (autoUpdateDeclined) {
|
||||||
// The user declined an update before, so show the "confirm" dialog
|
// The user declined an update before, so show the "confirm" dialog
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.AUTO_UPDATE_CONFIRM));
|
||||||
doOpenModal(MODALS.AUTO_UPDATE_CONFIRM)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
// The user was never shown the original update dialog (e.g. because they were
|
// The user was never shown the original update dialog (e.g. because they were
|
||||||
// watching a video). So show the inital "update downloaded" dialog.
|
// watching a video). So show the inital "update downloaded" dialog.
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.AUTO_UPDATE_DOWNLOADED));
|
||||||
doOpenModal(MODALS.AUTO_UPDATE_DOWNLOADED)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Old behavior for Linux
|
// Old behavior for Linux
|
||||||
|
@ -145,9 +151,7 @@ export function doAutoUpdate() {
|
||||||
type: ACTIONS.AUTO_UPDATE_DOWNLOADED,
|
type: ACTIONS.AUTO_UPDATE_DOWNLOADED,
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.AUTO_UPDATE_DOWNLOADED));
|
||||||
doOpenModal(MODALS.AUTO_UPDATE_DOWNLOADED)
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch(doClearUpgradeTimer());
|
dispatch(doClearUpgradeTimer());
|
||||||
};
|
};
|
||||||
|
@ -216,12 +220,10 @@ export function doCheckUpgradeAvailable() {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
upgradeAvailable &&
|
upgradeAvailable &&
|
||||||
!selectNotification(state) &&
|
!selectModal(state) &&
|
||||||
(!selectIsUpgradeSkipped(state) || remoteVersion !== selectRemoteVersion(state))
|
(!selectIsUpgradeSkipped(state) || remoteVersion !== selectRemoteVersion(state))
|
||||||
) {
|
) {
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.UPGRADE));
|
||||||
doOpenModal(MODALS.UPGRADE)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -266,42 +268,32 @@ export function doCheckDaemonVersion() {
|
||||||
type: ACTIONS.DAEMON_VERSION_MISMATCH,
|
type: ACTIONS.DAEMON_VERSION_MISMATCH,
|
||||||
});
|
});
|
||||||
|
|
||||||
return dispatch(
|
return dispatch(doOpenModal(MODALS.INCOMPATIBLE_DAEMON));
|
||||||
doOpenModal(MODALS.INCOMPATIBLE_DAEMON)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doNotifyEncryptWallet() {
|
export function doNotifyEncryptWallet() {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.WALLET_ENCRYPT));
|
||||||
doOpenModal(MODALS.WALLET_ENCRYPT)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doNotifyDecryptWallet() {
|
export function doNotifyDecryptWallet() {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.WALLET_DECRYPT));
|
||||||
doOpenModal(MODALS.WALLET_DECRYPT)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doNotifyUnlockWallet() {
|
export function doNotifyUnlockWallet() {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(
|
dispatch(doOpenModal(MODALS.WALLET_UNLOCK));
|
||||||
doOpenModal(MODALS.WALLET_UNLOCK)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doAlertError(errorList) {
|
export function doAlertError(errorList) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(
|
dispatch(doError(errorList));
|
||||||
doError(errorList)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +306,6 @@ export function doDaemonReady() {
|
||||||
dispatch(doFetchDaemonSettings());
|
dispatch(doFetchDaemonSettings());
|
||||||
dispatch(doBalanceSubscribe());
|
dispatch(doBalanceSubscribe());
|
||||||
dispatch(doFetchFileInfosAndPublishedClaims());
|
dispatch(doFetchFileInfosAndPublishedClaims());
|
||||||
dispatch(doFetchRewardedContent());
|
|
||||||
if (!selectIsUpgradeSkipped(state)) {
|
if (!selectIsUpgradeSkipped(state)) {
|
||||||
dispatch(doCheckUpgradeAvailable());
|
dispatch(doCheckUpgradeAvailable());
|
||||||
}
|
}
|
||||||
|
@ -373,26 +364,10 @@ export function doClickCommentButton() {
|
||||||
export function doConditionalAuthNavigate(newSession) {
|
export function doConditionalAuthNavigate(newSession) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const notification = selectNotification(state);
|
const notification = selectModal(state);
|
||||||
|
|
||||||
if (newSession || (notification && notification.id !== 'email_collection')) {
|
if (newSession || (notification && notification.id !== 'email_collection')) {
|
||||||
dispatch(doAuthNavigate());
|
dispatch(doAuthNavigate());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doOpenModal(id, modalProps = {}) {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.SHOW_MODAL,
|
|
||||||
data: {
|
|
||||||
id,
|
|
||||||
modalProps,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doHideModal() {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.HIDE_MODAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import {
|
||||||
Lbry,
|
Lbry,
|
||||||
Lbryapi,
|
Lbryapi,
|
||||||
buildURI,
|
buildURI,
|
||||||
doFetchClaimListMine,
|
|
||||||
makeSelectCostInfoForUri,
|
makeSelectCostInfoForUri,
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
selectFileInfosByOutpoint,
|
selectFileInfosByOutpoint,
|
||||||
|
@ -331,28 +330,6 @@ export function doFetchClaimsByChannel(uri, page, pageSize) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchClaimCountByChannel(uri) {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_STARTED,
|
|
||||||
data: { uri },
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.claim_list_by_channel({ uri }).then(result => {
|
|
||||||
const claimResult = result[uri];
|
|
||||||
const totalClaims = claimResult ? claimResult.claims_in_channel : 0;
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED,
|
|
||||||
data: {
|
|
||||||
uri,
|
|
||||||
totalClaims,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doPlayUri(uri) {
|
export function doPlayUri(uri) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(doSetPlayingUri(uri));
|
dispatch(doSetPlayingUri(uri));
|
||||||
|
@ -405,24 +382,6 @@ export function doCreateChannel(name: string, amount: number) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doPublish(params) {
|
|
||||||
return dispatch =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
const success = claim => {
|
|
||||||
resolve(claim);
|
|
||||||
|
|
||||||
if (claim === true) dispatch(doFetchClaimListMine());
|
|
||||||
else
|
|
||||||
setTimeout(() => dispatch(doFetchClaimListMine()), 20000, {
|
|
||||||
once: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const failure = err => reject(err);
|
|
||||||
|
|
||||||
Lbry.publishDeprecated(params, null, success, failure);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function savePosition(claimId: string, outpoint: string, position: number) {
|
export function savePosition(claimId: string, outpoint: string, position: number) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -15,7 +15,7 @@ import * as NOTIFICATION_TYPES from 'constants/subscriptions';
|
||||||
import { Lbryio, rewards, doClaimRewardType } from 'lbryinc';
|
import { Lbryio, rewards, doClaimRewardType } from 'lbryinc';
|
||||||
import { selectSubscriptions, selectUnreadByChannel } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions, selectUnreadByChannel } from 'redux/selectors/subscriptions';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { Lbry, buildURI, parseURI } from 'lbry-redux';
|
import { Lbry, buildURI, parseURI, doResolveUris } from 'lbry-redux';
|
||||||
import { doPurchaseUri, doFetchClaimsByChannel } from 'redux/actions/content';
|
import { doPurchaseUri, doFetchClaimsByChannel } from 'redux/actions/content';
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ export const doFetchMySubscriptions = () => (dispatch: ReduxDispatch, getState:
|
||||||
data: subscriptions,
|
data: subscriptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dispatch(doResolveUris(subscriptions.map(({ uri }) => uri)));
|
||||||
subscriptions.forEach(({ uri }) => dispatch(doFetchClaimsByChannel(uri, 1)));
|
subscriptions.forEach(({ uri }) => dispatch(doFetchClaimsByChannel(uri, 1)));
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
@ -167,28 +168,44 @@ export const doUpdateUnreadSubscriptions = (
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove multiple files (or all) from a channels unread subscriptions
|
// Remove multiple files (or all) from a channels unread subscriptions
|
||||||
export const doRemoveUnreadSubscriptions = (channelUri: string, readUris: Array<string>) => (
|
export const doRemoveUnreadSubscriptions = (channelUri: ?string, readUris: ?Array<string>) => (
|
||||||
dispatch: ReduxDispatch,
|
dispatch: ReduxDispatch,
|
||||||
getState: GetState
|
getState: GetState
|
||||||
) => {
|
) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const unreadByChannel = selectUnreadByChannel(state);
|
const unreadByChannel = selectUnreadByChannel(state);
|
||||||
|
|
||||||
|
// If no channel is passed in, remove all unread subscriptions from all channels
|
||||||
|
if (!channelUri) {
|
||||||
|
return dispatch({
|
||||||
|
type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS,
|
||||||
|
data: { channel: null },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const currentChannelUnread = unreadByChannel[channelUri];
|
const currentChannelUnread = unreadByChannel[channelUri];
|
||||||
if (!currentChannelUnread || !currentChannelUnread.uris) {
|
if (!currentChannelUnread || !currentChannelUnread.uris) {
|
||||||
|
// Channel passed in doesn't have any unreads
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each uri passed in, remove it from the list of unread uris
|
// For each uri passed in, remove it from the list of unread uris
|
||||||
const urisToRemoveMap = readUris.reduce(
|
// If no uris are passed in, remove them all
|
||||||
(acc, val) => ({
|
let newUris;
|
||||||
...acc,
|
if (readUris) {
|
||||||
[val]: true,
|
const urisToRemoveMap = readUris.reduce(
|
||||||
}),
|
(acc, val) => ({
|
||||||
{}
|
...acc,
|
||||||
);
|
[val]: true,
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
const filteredUris = currentChannelUnread.uris.filter(uri => !urisToRemoveMap[uri]);
|
const filteredUris = currentChannelUnread.uris.filter(uri => !urisToRemoveMap[uri]);
|
||||||
const newUris = filteredUris.length ? filteredUris : null;
|
newUris = filteredUris.length ? filteredUris : null;
|
||||||
|
} else {
|
||||||
|
newUris = null;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS,
|
type: ACTIONS.REMOVE_SUBSCRIPTION_UNREADS,
|
||||||
|
|
|
@ -66,10 +66,11 @@ export default handleActions(
|
||||||
action: SetSubscriptionLatest
|
action: SetSubscriptionLatest
|
||||||
): SubscriptionState => ({
|
): SubscriptionState => ({
|
||||||
...state,
|
...state,
|
||||||
subscriptions: state.subscriptions.map(subscription =>
|
subscriptions: state.subscriptions.map(
|
||||||
subscription.channelName === action.data.subscription.channelName
|
subscription =>
|
||||||
? { ...subscription, latest: action.data.uri }
|
subscription.channelName === action.data.subscription.channelName
|
||||||
: subscription
|
? { ...subscription, latest: action.data.uri }
|
||||||
|
: subscription
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
[ACTIONS.UPDATE_SUBSCRIPTION_UNREADS]: (
|
[ACTIONS.UPDATE_SUBSCRIPTION_UNREADS]: (
|
||||||
|
@ -94,12 +95,19 @@ export default handleActions(
|
||||||
action: DoRemoveSubscriptionUnreads
|
action: DoRemoveSubscriptionUnreads
|
||||||
): SubscriptionState => {
|
): SubscriptionState => {
|
||||||
const { channel, uris } = action.data;
|
const { channel, uris } = action.data;
|
||||||
const newUnread = { ...state.unread };
|
|
||||||
|
|
||||||
if (!uris) {
|
// If no channel is passed in, remove all unreads
|
||||||
delete newUnread[channel];
|
let newUnread;
|
||||||
|
if (channel) {
|
||||||
|
newUnread = { ...state.unread };
|
||||||
|
|
||||||
|
if (!uris) {
|
||||||
|
delete newUnread[channel];
|
||||||
|
} else {
|
||||||
|
newUnread[channel].uris = uris;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
newUnread[channel].uris = uris;
|
newUnread = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -253,3 +253,23 @@ export const makeSelectIsSubscribed = uri =>
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const makeSelectIsNew = uri =>
|
||||||
|
createSelector(
|
||||||
|
makeSelectIsSubscribed(uri),
|
||||||
|
makeSelectChannelForClaimUri(uri),
|
||||||
|
selectUnreadByChannel,
|
||||||
|
(isSubscribed, channel, unreadByChannel) => {
|
||||||
|
if (!isSubscribed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unreadForChannel = unreadByChannel[`lbry://${channel}`];
|
||||||
|
if (unreadForChannel) {
|
||||||
|
return unreadForChannel.uris.includes(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
// If they are subscribed, check to see if this uri is in the list of unreads
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// component specific styling should go in the component scss file
|
// component specific styling should go in the component scss file
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background-color: $lbry-white;
|
background-color: $lbry-teal-5;
|
||||||
font-family: 'Inter UI', sans-serif;
|
font-family: 'Inter UI', sans-serif;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.btn--no-padding {
|
||||||
|
.btn__content {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.btn--alt {
|
&.btn--alt {
|
||||||
&:not(:disabled) {
|
&:not(:disabled) {
|
||||||
background-color: $lbry-white;
|
background-color: $lbry-white;
|
||||||
|
|
|
@ -324,6 +324,7 @@
|
||||||
|
|
||||||
.card-row__scrollhouse {
|
.card-row__scrollhouse {
|
||||||
padding-top: $spacing-vertical * 2/3;
|
padding-top: $spacing-vertical * 2/3;
|
||||||
|
padding-bottom: $spacing-vertical * 1/6;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
html[data-theme='dark'] {
|
html[data-theme='dark'] {
|
||||||
|
//
|
||||||
|
// HTML Elements
|
||||||
|
//
|
||||||
|
blockquote {
|
||||||
|
background-color: rgba($lbry-black, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
background-color: rgba($lbry-black, 0.9);
|
background-color: rgba($lbry-black, 0.9);
|
||||||
}
|
}
|
||||||
|
@ -203,4 +210,11 @@ html[data-theme='dark'] {
|
||||||
.expandable--closed::after {
|
.expandable--closed::after {
|
||||||
background-image: linear-gradient(to bottom, transparent 0%, $lbry-black 90%);
|
background-image: linear-gradient(to bottom, transparent 0%, $lbry-black 90%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// File Viewer
|
||||||
|
//
|
||||||
|
.document-viewer {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 180 KiB |
Binary file not shown.
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 181 KiB |
20
yarn.lock
20
yarn.lock
|
@ -5663,6 +5663,14 @@ lazy-val@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
||||||
|
|
||||||
|
lbry-redux@lbryio/lbry-redux#1ed2ea8b2de99bbcba652aa7b00478d02df4a290:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/1ed2ea8b2de99bbcba652aa7b00478d02df4a290"
|
||||||
|
dependencies:
|
||||||
|
proxy-polyfill "0.1.6"
|
||||||
|
reselect "^3.0.0"
|
||||||
|
uuid "^3.3.2"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2:
|
lbry-redux@lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/2375860d6269d0369418879c2531b1d48c4e47f2"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/2375860d6269d0369418879c2531b1d48c4e47f2"
|
||||||
|
@ -5670,17 +5678,9 @@ lbry-redux@lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#df8e8c6b44718f8de36aabb9222e74ca9433e13c:
|
lbryinc@lbryio/lbryinc#e9508e259fa9bce3b69915b91534516cf5937075:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/df8e8c6b44718f8de36aabb9222e74ca9433e13c"
|
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/e9508e259fa9bce3b69915b91534516cf5937075"
|
||||||
dependencies:
|
|
||||||
proxy-polyfill "0.1.6"
|
|
||||||
reselect "^3.0.0"
|
|
||||||
uuid "^3.3.2"
|
|
||||||
|
|
||||||
lbryinc@lbryio/lbryinc#82308ece97188747adbf6d71d55b6e7a6fa0bd95:
|
|
||||||
version "0.0.1"
|
|
||||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/82308ece97188747adbf6d71d55b6e7a6fa0bd95"
|
|
||||||
dependencies:
|
dependencies:
|
||||||
lbry-redux lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2
|
lbry-redux lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Add table
Reference in a new issue