diff --git a/src/renderer/component/subHeader/index.js b/src/renderer/component/subHeader/index.js index f445734c5..e550952c2 100644 --- a/src/renderer/component/subHeader/index.js +++ b/src/renderer/component/subHeader/index.js @@ -2,13 +2,11 @@ import React from 'react'; import { connect } from 'react-redux'; import { selectCurrentPage, selectHeaderLinks } from 'redux/selectors/navigation'; import { doNavigate } from 'redux/actions/navigation'; -import { selectNotifications } from 'redux/selectors/subscriptions'; import SubHeader from './view'; const select = (state, props) => ({ currentPage: selectCurrentPage(state), subLinks: selectHeaderLinks(state), - notifications: selectNotifications(state), }); const perform = dispatch => ({ diff --git a/src/renderer/component/subHeader/view.jsx b/src/renderer/component/subHeader/view.jsx index 8ede92169..65227dc72 100644 --- a/src/renderer/component/subHeader/view.jsx +++ b/src/renderer/component/subHeader/view.jsx @@ -1,15 +1,9 @@ import React from 'react'; import Link from 'component/link'; import classnames from 'classnames'; -import * as NOTIFICATION_TYPES from 'constants/notification_types'; const SubHeader = props => { - const { subLinks, currentPage, navigate, fullWidth, smallMargin, notifications } = props; - - const badges = Object.keys(notifications).reduce( - (acc, cur) => (notifications[cur].type === NOTIFICATION_TYPES.DOWNLOADING ? acc : acc + 1), - 0 - ); + const { subLinks, currentPage, navigate, fullWidth, smallMargin } = props; const links = []; @@ -20,9 +14,7 @@ const SubHeader = props => { key={link} className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected'} > - {subLinks[link] === 'Subscriptions' && badges - ? `Subscriptions (${badges})` - : subLinks[link]} + {subLinks[link]} ); } diff --git a/src/renderer/constants/action_types.js b/src/renderer/constants/action_types.js index 43594a8ce..f4a993143 100644 --- a/src/renderer/constants/action_types.js +++ b/src/renderer/constants/action_types.js @@ -165,8 +165,6 @@ export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE'; export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE'; export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS'; export const SET_SUBSCRIPTION_LATEST = 'SET_SUBSCRIPTION_LATEST'; -export const SET_SUBSCRIPTION_NOTIFICATION = 'SET_SUBSCRIPTION_NOTIFICATION'; -export const SET_SUBSCRIPTION_NOTIFICATIONS = 'SET_SUBSCRIPTION_NOTIFICATIONS'; export const CHECK_SUBSCRIPTION_STARTED = 'CHECK_SUBSCRIPTION_STARTED'; export const CHECK_SUBSCRIPTION_COMPLETED = 'CHECK_SUBSCRIPTION_COMPLETED'; export const CHECK_SUBSCRIPTIONS_SUBSCRIBE = 'CHECK_SUBSCRIPTIONS_SUBSCRIBE'; diff --git a/src/renderer/constants/notification_types.js b/src/renderer/constants/notification_types.js deleted file mode 100644 index 4b1dd975a..000000000 --- a/src/renderer/constants/notification_types.js +++ /dev/null @@ -1,3 +0,0 @@ -export const DOWNLOADING = 'DOWNLOADING'; -export const DOWNLOADED = 'DOWNLOADED'; -export const NOTIFY_ONLY = 'NOTIFY_ONLY;'; diff --git a/src/renderer/index.js b/src/renderer/index.js index b81edfd2c..631e42af1 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -15,7 +15,7 @@ import { } from 'redux/actions/app'; import { doNavigate } from 'redux/actions/navigation'; import { doDownloadLanguages, doUpdateIsNightAsync } from 'redux/actions/settings'; -import { doUserEmailVerify } from 'redux/actions/user'; +import { doUserEmailVerify, doAuthenticate } from 'redux/actions/user'; import 'scss/all.scss'; import store from 'store'; import app from './app'; @@ -95,6 +95,8 @@ document.addEventListener('click', event => { }); const init = () => { + app.store.dispatch(doAuthenticate()); + autoUpdater.on('update-downloaded', () => { app.store.dispatch(doAutoUpdate()); }); diff --git a/src/renderer/page/subscriptions/index.js b/src/renderer/page/subscriptions/index.js index 4d1ce6409..1cd401dda 100644 --- a/src/renderer/page/subscriptions/index.js +++ b/src/renderer/page/subscriptions/index.js @@ -4,24 +4,18 @@ import { selectSubscriptionsFromClaims, selectSubscriptions, selectHasFetchedSubscriptions, - selectNotifications, } from 'redux/selectors/subscriptions'; import { doFetchClaimsByChannel } from 'redux/actions/content'; -import { - setHasFetchedSubscriptions, - setSubscriptionNotifications, -} from 'redux/actions/subscriptions'; +import { setHasFetchedSubscriptions } from 'redux/actions/subscriptions'; import SubscriptionsPage from './view'; const select = state => ({ hasFetchedSubscriptions: state.subscriptions.hasFetchedSubscriptions, savedSubscriptions: selectSubscriptions(state), subscriptions: selectSubscriptionsFromClaims(state), - notifications: selectNotifications(state), }); export default connect(select, { doFetchClaimsByChannel, setHasFetchedSubscriptions, - setSubscriptionNotifications, })(SubscriptionsPage); diff --git a/src/renderer/page/subscriptions/view.jsx b/src/renderer/page/subscriptions/view.jsx index 8f0e56840..3e09748a5 100644 --- a/src/renderer/page/subscriptions/view.jsx +++ b/src/renderer/page/subscriptions/view.jsx @@ -4,7 +4,6 @@ import SubHeader from 'component/subHeader'; import { BusyMessage } from 'component/common.js'; import { FeaturedCategory } from 'page/discover/view'; import type { Subscription } from 'redux/reducers/subscriptions'; -import * as NOTIFICATION_TYPES from 'constants/notification_types'; type SavedSubscriptions = Array; @@ -24,23 +23,11 @@ export default class extends React.PureComponent { // that causes this component to be rendered with zero savedSubscriptions // we need to wait until persist/REHYDRATE has fired before rendering the page componentDidMount() { - const { - savedSubscriptions, - setHasFetchedSubscriptions, - notifications, - setSubscriptionNotifications, - } = this.props; + const { savedSubscriptions, setHasFetchedSubscriptions } = this.props; if (savedSubscriptions.length) { this.fetchSubscriptions(savedSubscriptions); setHasFetchedSubscriptions(); } - const newNotifications = {}; - Object.keys(notifications).forEach(cur => { - if (notifications[cur].type === NOTIFICATION_TYPES.DOWNLOADING) { - newNotifications[cur] = { ...notifications[cur] }; - } - }); - setSubscriptionNotifications(newNotifications); } componentWillReceiveProps(props: Props) { @@ -65,7 +52,6 @@ export default class extends React.PureComponent { render() { const { subscriptions, savedSubscriptions } = this.props; - // TODO: if you are subscribed to an empty channel, this will always be true (but it should not be) const someClaimsNotLoaded = Boolean( subscriptions.find(subscription => !subscription.claims.length) ); diff --git a/src/renderer/redux/actions/app.js b/src/renderer/redux/actions/app.js index f9c868baf..fa1483c8f 100644 --- a/src/renderer/redux/actions/app.js +++ b/src/renderer/redux/actions/app.js @@ -9,7 +9,6 @@ import { doFetchRewardedContent } from 'redux/actions/content'; import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info'; import { doAuthNavigate } from 'redux/actions/navigation'; import { doFetchDaemonSettings } from 'redux/actions/settings'; -import { doAuthenticate } from 'redux/actions/user'; import { doBalanceSubscribe } from 'redux/actions/wallet'; import { doPause } from 'redux/actions/media'; import { doCheckSubscriptions } from 'redux/actions/subscriptions'; @@ -289,7 +288,6 @@ export function doDaemonReady() { return (dispatch, getState) => { const state = getState(); - dispatch(doAuthenticate()); dispatch({ type: ACTIONS.DAEMON_READY }); dispatch(doFetchDaemonSettings()); dispatch(doBalanceSubscribe()); diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index 2fdffc677..146b9b6d5 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -1,20 +1,13 @@ import * as ACTIONS from 'constants/action_types'; import * as MODALS from 'constants/modal_types'; import * as SETTINGS from 'constants/settings'; -import * as NOTIFICATION_TYPES from 'constants/notification_types'; import { ipcRenderer } from 'electron'; import Lbry from 'lbry'; import Lbryio from 'lbryio'; import { normalizeURI, buildURI } from 'lbryURI'; import { doAlertError, doOpenModal } from 'redux/actions/app'; import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards'; -import { doNavigate } from 'redux/actions/navigation'; -import { - setSubscriptionLatest, - setSubscriptionNotification, - setSubscriptionNotifications, -} from 'redux/actions/subscriptions'; -import { selectNotifications } from 'redux/selectors/subscriptions'; +import { setSubscriptionLatest } from 'redux/actions/subscriptions'; import { selectBadgeNumber } from 'redux/selectors/app'; import { selectMyClaimsRaw } from 'redux/selectors/claims'; import { selectResolvingUris } from 'redux/selectors/content'; @@ -171,45 +164,13 @@ export function doUpdateLoadStatus(uri, outpoint) { const totalProgress = selectTotalDownloadProgress(getState()); setProgressBar(totalProgress); - const notifications = selectNotifications(getState()); - if (notifications[uri] && notifications[uri].type === NOTIFICATION_TYPES.DOWNLOADING) { - const count = Object.keys(notifications).reduce( - (acc, cur) => - notifications[cur].subscription.channelName === - notifications[uri].subscription.channelName - ? acc + 1 - : acc, - 0 - ); - const notif = new window.Notification(notifications[uri].subscription.channelName, { - body: `Posted ${fileInfo.metadata.title}${ - count > 1 && count < 10 ? ` and ${count - 1} other new items` : '' - }${count > 9 ? ' and 9+ other new items' : ''}`, - silent: false, - }); - notif.onclick = () => { - dispatch( - doNavigate('/show', { - uri, - }) - ); - }; - dispatch( - setSubscriptionNotification( - notifications[uri].subscription, - uri, - NOTIFICATION_TYPES.DOWNLOADED - ) - ); - } else { - const notif = new window.Notification('LBRY Download Complete', { - body: fileInfo.metadata.title, - silent: false, - }); - notif.onclick = () => { - ipcRenderer.send('focusWindow', 'main'); - }; - } + const notif = new window.Notification('LBRY Download Complete', { + body: fileInfo.metadata.title, + silent: false, + }); + notif.onclick = () => { + ipcRenderer.send('focusWindow', 'main'); + }; } else { // ready to play const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo; @@ -383,7 +344,7 @@ export function doPurchaseUri(uri, specificCostInfo) { } export function doFetchClaimsByChannel(uri, page) { - return (dispatch, getState) => { + return dispatch => { dispatch({ type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED, data: { uri, page }, @@ -410,17 +371,6 @@ export function doFetchClaimsByChannel(uri, page) { buildURI({ contentName: latest.name, claimId: latest.claim_id }, false) ) ); - const notifications = selectNotifications(getState()); - const newNotifications = {}; - Object.keys(notifications).forEach(cur => { - if ( - notifications[cur].subscription.channelName !== latest.channel_name || - notifications[cur].type === NOTIFICATION_TYPES.DOWNLOADING - ) { - newNotifications[cur] = { ...notifications[cur] }; - } - }); - dispatch(setSubscriptionNotifications(newNotifications)); } dispatch({ diff --git a/src/renderer/redux/actions/subscriptions.js b/src/renderer/redux/actions/subscriptions.js index 53160ef8c..58269ab40 100644 --- a/src/renderer/redux/actions/subscriptions.js +++ b/src/renderer/redux/actions/subscriptions.js @@ -1,12 +1,6 @@ // @flow import * as ACTIONS from 'constants/action_types'; -import * as NOTIFICATION_TYPES from 'constants/notification_types'; -import type { - Subscription, - Dispatch, - SubscriptionState, - SubscriptionNotifications, -} from 'redux/reducers/subscriptions'; +import type { Subscription, Dispatch, SubscriptionState } from 'redux/reducers/subscriptions'; import { selectSubscriptions } from 'redux/selectors/subscriptions'; import Lbry from 'lbry'; import { doPurchaseUri } from 'redux/actions/content'; @@ -15,7 +9,6 @@ import { buildURI } from 'lbryURI'; import analytics from 'analytics'; const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000; -const SUBSCRIPTION_DOWNLOAD_LIMIT = 1; export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) => { dispatch({ @@ -66,48 +59,64 @@ export const doCheckSubscription = (subscription: Subscription, notify?: boolean const claimResult = result[subscription.uri] || {}; const { claims_in_channel: claimsInChannel } = claimResult; - if (claimsInChannel) { - if (notify) { - claimsInChannel.reduce((prev, cur, index) => { - const uri = buildURI({ contentName: cur.name, claimId: cur.claim_id }, false); - if (prev === -1 && uri !== subscription.latest) { - dispatch( - setSubscriptionNotification( - subscription, - uri, - index < SUBSCRIPTION_DOWNLOAD_LIMIT && !cur.value.stream.metadata.fee - ? NOTIFICATION_TYPES.DOWNLOADING - : NOTIFICATION_TYPES.NOTIFY_ONLY - ) - ); - if (index < SUBSCRIPTION_DOWNLOAD_LIMIT && !cur.value.stream.metadata.fee) { - dispatch(doPurchaseUri(uri, { cost: 0 })); - } - } - return uri === subscription.latest || !subscription.latest ? index : prev; - }, -1); - } + const count = subscription.latest + ? claimsInChannel.reduce( + (prev, cur, index) => + buildURI({ contentName: cur.name, claimId: cur.claim_id }, false) === + subscription.latest + ? index + : prev, + -1 + ) + : 1; - dispatch( - setSubscriptionLatest( - { - channelName: claimsInChannel[0].channel_name, - uri: buildURI( - { - channelName: claimsInChannel[0].channel_name, - claimId: claimsInChannel[0].claim_id, - }, + if (count !== 0 && notify) { + if (!claimsInChannel[0].value.stream.metadata.fee) { + dispatch( + doPurchaseUri( + buildURI( + { contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id }, false ), - }, - buildURI( - { contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id }, - false + { cost: 0 } ) - ) - ); + ); + } + + const notif = new window.Notification(subscription.channelName, { + body: `Posted ${claimsInChannel[0].value.stream.metadata.title}${ + count > 1 ? ` and ${count - 1} other new items` : '' + }${count < 0 ? ' and 9+ other new items' : ''}`, + silent: false, + }); + notif.onclick = () => { + dispatch( + doNavigate('/show', { + uri: buildURI( + { contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id }, + true + ), + }) + ); + }; } + dispatch( + setSubscriptionLatest( + { + channelName: claimsInChannel[0].channel_name, + uri: buildURI( + { channelName: claimsInChannel[0].channel_name, claimId: claimsInChannel[0].claim_id }, + false + ), + }, + buildURI( + { contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id }, + false + ) + ) + ); + dispatch({ type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED, data: subscription, @@ -126,29 +135,5 @@ export const setSubscriptionLatest = (subscription: Subscription, uri: string) = }, }); -export const setSubscriptionNotification = ( - subscription: Subscription, - uri: string, - notificationType: string -) => (dispatch: Dispatch) => - dispatch({ - type: ACTIONS.SET_SUBSCRIPTION_NOTIFICATION, - data: { - subscription, - uri, - type: notificationType, - }, - }); - -export const setSubscriptionNotifications = (notifications: SubscriptionNotifications) => ( - dispatch: Dispatch -) => - dispatch({ - type: ACTIONS.SET_SUBSCRIPTION_NOTIFICATIONS, - data: { - notifications, - }, - }); - export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) => dispatch({ type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS }); diff --git a/src/renderer/redux/reducers/subscriptions.js b/src/renderer/redux/reducers/subscriptions.js index 7a54e2d46..a8f40746f 100644 --- a/src/renderer/redux/reducers/subscriptions.js +++ b/src/renderer/redux/reducers/subscriptions.js @@ -1,6 +1,5 @@ // @flow import * as ACTIONS from 'constants/action_types'; -import * as NOTIFICATION_TYPES from 'constants/notification_types'; import { handleActions } from 'util/redux-utils'; export type Subscription = { @@ -9,23 +8,10 @@ export type Subscription = { latest: ?string, }; -export type NotificationType = - | NOTIFICATION_TYPES.DOWNLOADING - | NOTIFICATION_TYPES.DOWNLOADED - | NOTIFICATION_TYPES.NOTIFY_ONLY; - -export type SubscriptionNotifications = { - [string]: { - subscription: Subscription, - type: NotificationType, - }, -}; - // Subscription redux types export type SubscriptionState = { subscriptions: Array, hasFetchedSubscriptions: boolean, - notifications: SubscriptionNotifications, }; // Subscription action types @@ -51,22 +37,6 @@ type setSubscriptionLatest = { }, }; -type setSubscriptionNotification = { - type: ACTIONS.SET_SUBSCRIPTION_NOTIFICATION, - data: { - subscription: Subscription, - uri: string, - type: NotificationType, - }, -}; - -type setSubscriptionNotifications = { - type: ACTIONS.SET_SUBSCRIPTION_NOTIFICATIONS, - data: { - notifications: SubscriptionNotifications, - }, -}; - type CheckSubscriptionStarted = { type: ACTIONS.CHECK_SUBSCRIPTION_STARTED, }; @@ -80,7 +50,6 @@ export type Action = | doChannelUnsubscribe | HasFetchedSubscriptions | setSubscriptionLatest - | setSubscriptionNotification | CheckSubscriptionStarted | CheckSubscriptionCompleted | Function; @@ -89,7 +58,6 @@ export type Dispatch = (action: Action) => any; const defaultState = { subscriptions: [], hasFetchedSubscriptions: false, - notifications: {}, }; export default handleActions( @@ -138,23 +106,6 @@ export default handleActions( : subscription ), }), - [ACTIONS.SET_SUBSCRIPTION_NOTIFICATION]: ( - state: SubscriptionState, - action: setSubscriptionNotification - ): SubscriptionState => ({ - ...state, - notifications: { - ...state.notifications, - [action.data.uri]: { subscription: action.data.subscription, type: action.data.type }, - }, - }), - [ACTIONS.SET_SUBSCRIPTION_NOTIFICATIONS]: ( - state: SubscriptionState, - action: setSubscriptionNotifications - ): SubscriptionState => ({ - ...state, - notifications: action.data.notifications, - }), }, defaultState ); diff --git a/src/renderer/redux/selectors/subscriptions.js b/src/renderer/redux/selectors/subscriptions.js index 30efb5dc4..50bedf3ef 100644 --- a/src/renderer/redux/selectors/subscriptions.js +++ b/src/renderer/redux/selectors/subscriptions.js @@ -4,8 +4,6 @@ import { selectAllClaimsByChannel, selectClaimsById } from './claims'; // get the entire subscriptions state const selectState = state => state.subscriptions || {}; -export const selectNotifications = createSelector(selectState, state => state.notifications); - // list of saved channel names and uris export const selectSubscriptions = createSelector(selectState, state => state.subscriptions); @@ -25,7 +23,7 @@ export const selectSubscriptionsFromClaims = createSelector( let channelClaims = []; // if subscribed channel has content - if (channelIds[subscription.uri] && channelIds[subscription.uri]['1']) { + if (channelIds[subscription.uri]) { // This will need to be more robust, we will want to be able to load more than the first page const pageOneChannelIds = channelIds[subscription.uri]['1'];