Notify after download, badges and fix error
This commit is contained in:
parent
87cb8731c8
commit
2251fe5832
10 changed files with 217 additions and 66 deletions
src/renderer
component/subHeader
constants
page/subscriptions
redux
|
@ -2,11 +2,13 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectCurrentPage, selectHeaderLinks } from 'redux/selectors/navigation';
|
import { selectCurrentPage, selectHeaderLinks } from 'redux/selectors/navigation';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
|
import { selectNotifications } from 'redux/selectors/subscriptions';
|
||||||
import SubHeader from './view';
|
import SubHeader from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
currentPage: selectCurrentPage(state),
|
currentPage: selectCurrentPage(state),
|
||||||
subLinks: selectHeaderLinks(state),
|
subLinks: selectHeaderLinks(state),
|
||||||
|
notifications: selectNotifications(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||||
|
|
||||||
const SubHeader = props => {
|
const SubHeader = props => {
|
||||||
const { subLinks, currentPage, navigate, fullWidth, smallMargin } = 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 links = [];
|
const links = [];
|
||||||
|
|
||||||
|
@ -14,7 +20,9 @@ const SubHeader = props => {
|
||||||
key={link}
|
key={link}
|
||||||
className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected'}
|
className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected'}
|
||||||
>
|
>
|
||||||
{subLinks[link]}
|
{subLinks[link] === 'Subscriptions' && badges
|
||||||
|
? `Subscriptions (${badges})`
|
||||||
|
: subLinks[link]}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,6 +165,8 @@ export const CHANNEL_SUBSCRIBE = 'CHANNEL_SUBSCRIBE';
|
||||||
export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE';
|
export const CHANNEL_UNSUBSCRIBE = 'CHANNEL_UNSUBSCRIBE';
|
||||||
export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS';
|
export const HAS_FETCHED_SUBSCRIPTIONS = 'HAS_FETCHED_SUBSCRIPTIONS';
|
||||||
export const SET_SUBSCRIPTION_LATEST = 'SET_SUBSCRIPTION_LATEST';
|
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_STARTED = 'CHECK_SUBSCRIPTION_STARTED';
|
||||||
export const CHECK_SUBSCRIPTION_COMPLETED = 'CHECK_SUBSCRIPTION_COMPLETED';
|
export const CHECK_SUBSCRIPTION_COMPLETED = 'CHECK_SUBSCRIPTION_COMPLETED';
|
||||||
export const CHECK_SUBSCRIPTIONS_SUBSCRIBE = 'CHECK_SUBSCRIPTIONS_SUBSCRIBE';
|
export const CHECK_SUBSCRIPTIONS_SUBSCRIBE = 'CHECK_SUBSCRIPTIONS_SUBSCRIBE';
|
||||||
|
|
3
src/renderer/constants/notification_types.js
Normal file
3
src/renderer/constants/notification_types.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const DOWNLOADING = 'DOWNLOADING';
|
||||||
|
export const DOWNLOADED = 'DOWNLOADED';
|
||||||
|
export const NOTIFY_ONLY = 'NOTIFY_ONLY;';
|
|
@ -4,18 +4,24 @@ import {
|
||||||
selectSubscriptionsFromClaims,
|
selectSubscriptionsFromClaims,
|
||||||
selectSubscriptions,
|
selectSubscriptions,
|
||||||
selectHasFetchedSubscriptions,
|
selectHasFetchedSubscriptions,
|
||||||
|
selectNotifications,
|
||||||
} from 'redux/selectors/subscriptions';
|
} from 'redux/selectors/subscriptions';
|
||||||
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
||||||
import { setHasFetchedSubscriptions } from 'redux/actions/subscriptions';
|
import {
|
||||||
|
setHasFetchedSubscriptions,
|
||||||
|
setSubscriptionNotifications,
|
||||||
|
} from 'redux/actions/subscriptions';
|
||||||
import SubscriptionsPage from './view';
|
import SubscriptionsPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
hasFetchedSubscriptions: state.subscriptions.hasFetchedSubscriptions,
|
hasFetchedSubscriptions: state.subscriptions.hasFetchedSubscriptions,
|
||||||
savedSubscriptions: selectSubscriptions(state),
|
savedSubscriptions: selectSubscriptions(state),
|
||||||
subscriptions: selectSubscriptionsFromClaims(state),
|
subscriptions: selectSubscriptionsFromClaims(state),
|
||||||
|
notifications: selectNotifications(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, {
|
export default connect(select, {
|
||||||
doFetchClaimsByChannel,
|
doFetchClaimsByChannel,
|
||||||
setHasFetchedSubscriptions,
|
setHasFetchedSubscriptions,
|
||||||
|
setSubscriptionNotifications,
|
||||||
})(SubscriptionsPage);
|
})(SubscriptionsPage);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import SubHeader from 'component/subHeader';
|
||||||
import { BusyMessage } from 'component/common.js';
|
import { BusyMessage } from 'component/common.js';
|
||||||
import { FeaturedCategory } from 'page/discover/view';
|
import { FeaturedCategory } from 'page/discover/view';
|
||||||
import type { Subscription } from 'redux/reducers/subscriptions';
|
import type { Subscription } from 'redux/reducers/subscriptions';
|
||||||
|
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||||
|
|
||||||
type SavedSubscriptions = Array<Subscription>;
|
type SavedSubscriptions = Array<Subscription>;
|
||||||
|
|
||||||
|
@ -23,11 +24,23 @@ export default class extends React.PureComponent<Props> {
|
||||||
// that causes this component to be rendered with zero savedSubscriptions
|
// that causes this component to be rendered with zero savedSubscriptions
|
||||||
// we need to wait until persist/REHYDRATE has fired before rendering the page
|
// we need to wait until persist/REHYDRATE has fired before rendering the page
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { savedSubscriptions, setHasFetchedSubscriptions } = this.props;
|
const {
|
||||||
|
savedSubscriptions,
|
||||||
|
setHasFetchedSubscriptions,
|
||||||
|
notifications,
|
||||||
|
setSubscriptionNotifications,
|
||||||
|
} = this.props;
|
||||||
if (savedSubscriptions.length) {
|
if (savedSubscriptions.length) {
|
||||||
this.fetchSubscriptions(savedSubscriptions);
|
this.fetchSubscriptions(savedSubscriptions);
|
||||||
setHasFetchedSubscriptions();
|
setHasFetchedSubscriptions();
|
||||||
}
|
}
|
||||||
|
const newNotifications = {};
|
||||||
|
Object.keys(notifications).forEach(cur => {
|
||||||
|
if (notifications[cur].type === NOTIFICATION_TYPES.DOWNLOADING) {
|
||||||
|
newNotifications[cur] = { ...notifications[cur] };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setSubscriptionNotifications(newNotifications);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(props: Props) {
|
componentWillReceiveProps(props: Props) {
|
||||||
|
@ -52,6 +65,7 @@ export default class extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { subscriptions, savedSubscriptions } = this.props;
|
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(
|
const someClaimsNotLoaded = Boolean(
|
||||||
subscriptions.find(subscription => !subscription.claims.length)
|
subscriptions.find(subscription => !subscription.claims.length)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
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 * as SETTINGS from 'constants/settings';
|
import * as SETTINGS from 'constants/settings';
|
||||||
|
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import Lbryio from 'lbryio';
|
import Lbryio from 'lbryio';
|
||||||
import { normalizeURI, buildURI } from 'lbryURI';
|
import { normalizeURI, buildURI } from 'lbryURI';
|
||||||
import { doAlertError, doOpenModal } from 'redux/actions/app';
|
import { doAlertError, doOpenModal } from 'redux/actions/app';
|
||||||
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
||||||
import { setSubscriptionLatest } from 'redux/actions/subscriptions';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
|
import {
|
||||||
|
setSubscriptionLatest,
|
||||||
|
setSubscriptionNotification,
|
||||||
|
setSubscriptionNotifications,
|
||||||
|
} from 'redux/actions/subscriptions';
|
||||||
|
import { selectNotifications } from 'redux/selectors/subscriptions';
|
||||||
import { selectBadgeNumber } from 'redux/selectors/app';
|
import { selectBadgeNumber } from 'redux/selectors/app';
|
||||||
import { selectMyClaimsRaw } from 'redux/selectors/claims';
|
import { selectMyClaimsRaw } from 'redux/selectors/claims';
|
||||||
import { selectResolvingUris } from 'redux/selectors/content';
|
import { selectResolvingUris } from 'redux/selectors/content';
|
||||||
|
@ -164,13 +171,45 @@ export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
const totalProgress = selectTotalDownloadProgress(getState());
|
const totalProgress = selectTotalDownloadProgress(getState());
|
||||||
setProgressBar(totalProgress);
|
setProgressBar(totalProgress);
|
||||||
|
|
||||||
const notif = new window.Notification('LBRY Download Complete', {
|
const notifications = selectNotifications(getState());
|
||||||
body: fileInfo.metadata.title,
|
if (notifications[uri] && notifications[uri].type === NOTIFICATION_TYPES.DOWNLOADING) {
|
||||||
silent: false,
|
const count = Object.keys(notifications).reduce(
|
||||||
});
|
(acc, cur) =>
|
||||||
notif.onclick = () => {
|
notifications[cur].subscription.channelName ===
|
||||||
ipcRenderer.send('focusWindow', 'main');
|
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');
|
||||||
|
};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// ready to play
|
// ready to play
|
||||||
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
||||||
|
@ -344,7 +383,7 @@ export function doPurchaseUri(uri, specificCostInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchClaimsByChannel(uri, page) {
|
export function doFetchClaimsByChannel(uri, page) {
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED,
|
type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED,
|
||||||
data: { uri, page },
|
data: { uri, page },
|
||||||
|
@ -371,6 +410,17 @@ export function doFetchClaimsByChannel(uri, page) {
|
||||||
buildURI({ contentName: latest.name, claimId: latest.claim_id }, false)
|
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({
|
dispatch({
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import type { Subscription, Dispatch, SubscriptionState } from 'redux/reducers/subscriptions';
|
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||||
|
import type {
|
||||||
|
Subscription,
|
||||||
|
Dispatch,
|
||||||
|
SubscriptionState,
|
||||||
|
SubscriptionNotifications,
|
||||||
|
} from 'redux/reducers/subscriptions';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import Lbry from 'lbry';
|
import Lbry from 'lbry';
|
||||||
import { doPurchaseUri } from 'redux/actions/content';
|
import { doPurchaseUri } from 'redux/actions/content';
|
||||||
|
@ -9,6 +15,7 @@ import { buildURI } from 'lbryURI';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
|
||||||
const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000;
|
const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000;
|
||||||
|
const SUBSCRIPTION_DOWNLOAD_LIMIT = 1;
|
||||||
|
|
||||||
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) => {
|
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -59,63 +66,47 @@ export const doCheckSubscription = (subscription: Subscription, notify?: boolean
|
||||||
const claimResult = result[subscription.uri] || {};
|
const claimResult = result[subscription.uri] || {};
|
||||||
const { claims_in_channel: claimsInChannel } = claimResult;
|
const { claims_in_channel: claimsInChannel } = claimResult;
|
||||||
|
|
||||||
const count = subscription.latest
|
if (claimsInChannel) {
|
||||||
? claimsInChannel.reduce(
|
if (notify) {
|
||||||
(prev, cur, index) =>
|
claimsInChannel.reduce((prev, cur, index) => {
|
||||||
buildURI({ contentName: cur.name, claimId: cur.claim_id }, false) ===
|
const uri = buildURI({ contentName: cur.name, claimId: cur.claim_id }, false);
|
||||||
subscription.latest
|
if (prev === -1 && uri !== subscription.latest) {
|
||||||
? index
|
dispatch(
|
||||||
: prev,
|
setSubscriptionNotification(
|
||||||
-1
|
subscription,
|
||||||
)
|
uri,
|
||||||
: 1;
|
index < SUBSCRIPTION_DOWNLOAD_LIMIT && !cur.value.stream.metadata.fee
|
||||||
|
? NOTIFICATION_TYPES.DOWNLOADING
|
||||||
if (count !== 0 && notify) {
|
: NOTIFICATION_TYPES.NOTIFY_ONLY
|
||||||
if (!claimsInChannel[0].value.stream.metadata.fee) {
|
)
|
||||||
dispatch(
|
);
|
||||||
doPurchaseUri(
|
if (index < SUBSCRIPTION_DOWNLOAD_LIMIT && !cur.value.stream.metadata.fee) {
|
||||||
buildURI(
|
dispatch(doPurchaseUri(uri, { cost: 0 }));
|
||||||
{ contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id },
|
}
|
||||||
false
|
}
|
||||||
),
|
return uri === subscription.latest || !subscription.latest ? index : prev;
|
||||||
{ cost: 0 }
|
}, -1);
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const notif = new window.Notification(subscription.channelName, {
|
dispatch(
|
||||||
body: `Posted ${claimsInChannel[0].value.stream.metadata.title}${
|
setSubscriptionLatest(
|
||||||
count > 1 ? ` and ${count - 1} other new items` : ''
|
{
|
||||||
}${count < 0 ? ' and 9+ other new items' : ''}`,
|
channelName: claimsInChannel[0].channel_name,
|
||||||
silent: false,
|
|
||||||
});
|
|
||||||
notif.onclick = () => {
|
|
||||||
dispatch(
|
|
||||||
doNavigate('/show', {
|
|
||||||
uri: buildURI(
|
uri: buildURI(
|
||||||
{ contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id },
|
{
|
||||||
true
|
channelName: claimsInChannel[0].channel_name,
|
||||||
|
claimId: claimsInChannel[0].claim_id,
|
||||||
|
},
|
||||||
|
false
|
||||||
),
|
),
|
||||||
})
|
},
|
||||||
);
|
buildURI(
|
||||||
};
|
{ contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id },
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
setSubscriptionLatest(
|
|
||||||
{
|
|
||||||
channelName: claimsInChannel[0].channel_name,
|
|
||||||
uri: buildURI(
|
|
||||||
{ channelName: claimsInChannel[0].channel_name, claimId: claimsInChannel[0].claim_id },
|
|
||||||
false
|
false
|
||||||
),
|
)
|
||||||
},
|
|
||||||
buildURI(
|
|
||||||
{ contentName: claimsInChannel[0].name, claimId: claimsInChannel[0].claim_id },
|
|
||||||
false
|
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED,
|
type: ACTIONS.CHECK_SUBSCRIPTION_COMPLETED,
|
||||||
|
@ -135,5 +126,29 @@ 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) =>
|
export const setHasFetchedSubscriptions = () => (dispatch: Dispatch) =>
|
||||||
dispatch({ type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS });
|
dispatch({ type: ACTIONS.HAS_FETCHED_SUBSCRIPTIONS });
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||||
import { handleActions } from 'util/redux-utils';
|
import { handleActions } from 'util/redux-utils';
|
||||||
|
|
||||||
export type Subscription = {
|
export type Subscription = {
|
||||||
|
@ -8,10 +9,23 @@ export type Subscription = {
|
||||||
latest: ?string,
|
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
|
// Subscription redux types
|
||||||
export type SubscriptionState = {
|
export type SubscriptionState = {
|
||||||
subscriptions: Array<Subscription>,
|
subscriptions: Array<Subscription>,
|
||||||
hasFetchedSubscriptions: boolean,
|
hasFetchedSubscriptions: boolean,
|
||||||
|
notifications: SubscriptionNotifications,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Subscription action types
|
// Subscription action types
|
||||||
|
@ -37,6 +51,22 @@ 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 CheckSubscriptionStarted = {
|
||||||
type: ACTIONS.CHECK_SUBSCRIPTION_STARTED,
|
type: ACTIONS.CHECK_SUBSCRIPTION_STARTED,
|
||||||
};
|
};
|
||||||
|
@ -50,6 +80,7 @@ export type Action =
|
||||||
| doChannelUnsubscribe
|
| doChannelUnsubscribe
|
||||||
| HasFetchedSubscriptions
|
| HasFetchedSubscriptions
|
||||||
| setSubscriptionLatest
|
| setSubscriptionLatest
|
||||||
|
| setSubscriptionNotification
|
||||||
| CheckSubscriptionStarted
|
| CheckSubscriptionStarted
|
||||||
| CheckSubscriptionCompleted
|
| CheckSubscriptionCompleted
|
||||||
| Function;
|
| Function;
|
||||||
|
@ -58,6 +89,7 @@ export type Dispatch = (action: Action) => any;
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
subscriptions: [],
|
subscriptions: [],
|
||||||
hasFetchedSubscriptions: false,
|
hasFetchedSubscriptions: false,
|
||||||
|
notifications: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handleActions(
|
export default handleActions(
|
||||||
|
@ -106,6 +138,23 @@ export default handleActions(
|
||||||
: subscription
|
: 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
|
defaultState
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { selectAllClaimsByChannel, selectClaimsById } from './claims';
|
||||||
// get the entire subscriptions state
|
// get the entire subscriptions state
|
||||||
const selectState = state => state.subscriptions || {};
|
const selectState = state => state.subscriptions || {};
|
||||||
|
|
||||||
|
export const selectNotifications = createSelector(selectState, state => state.notifications);
|
||||||
|
|
||||||
// list of saved channel names and uris
|
// list of saved channel names and uris
|
||||||
export const selectSubscriptions = createSelector(selectState, state => state.subscriptions);
|
export const selectSubscriptions = createSelector(selectState, state => state.subscriptions);
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ export const selectSubscriptionsFromClaims = createSelector(
|
||||||
let channelClaims = [];
|
let channelClaims = [];
|
||||||
|
|
||||||
// if subscribed channel has content
|
// if subscribed channel has content
|
||||||
if (channelIds[subscription.uri]) {
|
if (channelIds[subscription.uri] && channelIds[subscription.uri]['1']) {
|
||||||
// This will need to be more robust, we will want to be able to load more than the first page
|
// 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'];
|
const pageOneChannelIds = channelIds[subscription.uri]['1'];
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue