mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-30 17:01:25 +00:00
Merge pull request #1113 from lbryio/subscription-quirks
Added api sub logging, sub modal, and immediate download initiation
This commit is contained in:
commit
209817c2a2
9 changed files with 108 additions and 11 deletions
|
@ -2,6 +2,7 @@
|
||||||
import mixpanel from 'mixpanel-browser';
|
import mixpanel from 'mixpanel-browser';
|
||||||
import Lbryio from 'lbryio';
|
import Lbryio from 'lbryio';
|
||||||
import isDev from 'electron-is-dev';
|
import isDev from 'electron-is-dev';
|
||||||
|
import type { Subscription } from 'redux/reducers/subscriptions';
|
||||||
|
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
mixpanel.init('691723e855cabb9d27a7a79002216967');
|
mixpanel.init('691723e855cabb9d27a7a79002216967');
|
||||||
|
@ -13,7 +14,9 @@ type Analytics = {
|
||||||
track: (string, ?Object) => void,
|
track: (string, ?Object) => void,
|
||||||
setUser: Object => void,
|
setUser: Object => void,
|
||||||
toggle: (boolean, ?boolean) => void,
|
toggle: (boolean, ?boolean) => void,
|
||||||
apiLog: (string, string, string) => void,
|
apiLogView: (string, string, string) => void,
|
||||||
|
apiLogSubscribe: Subscription => void,
|
||||||
|
apiLogUnsubscribe: Subscription => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
let analyticsEnabled: boolean = false;
|
let analyticsEnabled: boolean = false;
|
||||||
|
@ -44,7 +47,7 @@ const analytics: Analytics = {
|
||||||
}
|
}
|
||||||
analyticsEnabled = enabled;
|
analyticsEnabled = enabled;
|
||||||
},
|
},
|
||||||
apiLog: (uri: string, outpoint: string, claimId: string): void => {
|
apiLogView: (uri: string, outpoint: string, claimId: string): void => {
|
||||||
if (analyticsEnabled) {
|
if (analyticsEnabled) {
|
||||||
Lbryio.call('file', 'view', {
|
Lbryio.call('file', 'view', {
|
||||||
uri,
|
uri,
|
||||||
|
@ -53,6 +56,20 @@ const analytics: Analytics = {
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
apiLogSubscribe: (subscription: Subscription): void => {
|
||||||
|
if (analyticsEnabled) {
|
||||||
|
Lbryio.call('subscription', 'new', {
|
||||||
|
subscription,
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
apiLogUnsubscribe: (subscription: Subscription): void => {
|
||||||
|
if (analyticsEnabled) {
|
||||||
|
Lbryio.call('subscription', 'delete', {
|
||||||
|
subscription,
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default analytics;
|
export default analytics;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions';
|
import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions';
|
||||||
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
|
|
||||||
import SubscribeButton from './view';
|
import SubscribeButton from './view';
|
||||||
|
@ -11,4 +12,5 @@ const select = (state, props) => ({
|
||||||
export default connect(select, {
|
export default connect(select, {
|
||||||
doChannelSubscribe,
|
doChannelSubscribe,
|
||||||
doChannelUnsubscribe,
|
doChannelUnsubscribe,
|
||||||
|
doOpenModal,
|
||||||
})(SubscribeButton);
|
})(SubscribeButton);
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
|
import * as modals from 'constants/modal_types';
|
||||||
|
|
||||||
export default ({ channelName, uri, subscriptions, doChannelSubscribe, doChannelUnsubscribe }) => {
|
export default ({
|
||||||
|
channelName,
|
||||||
|
uri,
|
||||||
|
subscriptions,
|
||||||
|
doChannelSubscribe,
|
||||||
|
doChannelUnsubscribe,
|
||||||
|
doOpenModal,
|
||||||
|
}) => {
|
||||||
const isSubscribed =
|
const isSubscribed =
|
||||||
subscriptions.map(subscription => subscription.channelName).indexOf(channelName) !== -1;
|
subscriptions.map(subscription => subscription.channelName).indexOf(channelName) !== -1;
|
||||||
|
|
||||||
|
@ -15,12 +23,15 @@ export default ({ channelName, uri, subscriptions, doChannelSubscribe, doChannel
|
||||||
iconRight={isSubscribed ? '' : 'at'}
|
iconRight={isSubscribed ? '' : 'at'}
|
||||||
button={isSubscribed ? 'alt' : 'primary'}
|
button={isSubscribed ? 'alt' : 'primary'}
|
||||||
label={subscriptionLabel}
|
label={subscriptionLabel}
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
|
if (!subscriptions.length) {
|
||||||
|
doOpenModal(modals.FIRST_SUBSCRIPTION);
|
||||||
|
}
|
||||||
subscriptionHandler({
|
subscriptionHandler({
|
||||||
channelName,
|
channelName,
|
||||||
uri,
|
uri,
|
||||||
})
|
});
|
||||||
}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
|
@ -16,3 +16,4 @@ export const TRANSACTION_FAILED = 'transaction_failed';
|
||||||
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
|
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
|
||||||
export const AFFIRM_PURCHASE = 'affirm_purchase';
|
export const AFFIRM_PURCHASE = 'affirm_purchase';
|
||||||
export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke';
|
export const CONFIRM_CLAIM_REVOKE = 'confirmClaimRevoke';
|
||||||
|
export const FIRST_SUBSCRIPTION = 'firstSubscription';
|
||||||
|
|
11
src/renderer/modal/modalFirstSubscription/index.js
Normal file
11
src/renderer/modal/modalFirstSubscription/index.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { doCloseModal } from 'redux/actions/app';
|
||||||
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
|
import ModalFirstSubscription from './view';
|
||||||
|
|
||||||
|
const perform = dispatch => () => ({
|
||||||
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
|
navigate: path => dispatch(doNavigate(path)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, perform)(ModalFirstSubscription);
|
43
src/renderer/modal/modalFirstSubscription/view.jsx
Normal file
43
src/renderer/modal/modalFirstSubscription/view.jsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Modal } from 'modal/modal';
|
||||||
|
import Link from 'component/link';
|
||||||
|
|
||||||
|
const ModalFirstSubscription = props => {
|
||||||
|
const { closeModal, navigate } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal type="custom" isOpen contentLabel="Subscriptions 101">
|
||||||
|
<section>
|
||||||
|
<h3 className="modal__header">{__('Subscriptions 101')}</h3>
|
||||||
|
<p>{__('You just subscribed to your first channel. Awesome!')}</p>
|
||||||
|
<p>{__('A few quick things to know:')}</p>
|
||||||
|
<p>
|
||||||
|
{__('1) You can use the')}{' '}
|
||||||
|
<Link
|
||||||
|
label={__('Subscriptions Page')}
|
||||||
|
onClick={() => {
|
||||||
|
navigate('/subscriptions');
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
/>{' '}
|
||||||
|
{__('to view content across all of your subscribed channels.')}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
'2) This app will automatically download new free content from channels you are subscribed to.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
'3) If we have your email address, we may send you notifications and rewards related to new content.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<div className="modal__buttons">
|
||||||
|
<Link button="primary" onClick={closeModal} label={__('Got it')} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModalFirstSubscription;
|
|
@ -14,8 +14,9 @@ import ModalTransactionFailed from 'modal/modalTransactionFailed';
|
||||||
import ModalFileTimeout from 'modal/modalFileTimeout';
|
import ModalFileTimeout from 'modal/modalFileTimeout';
|
||||||
import ModalAffirmPurchase from 'modal/modalAffirmPurchase';
|
import ModalAffirmPurchase from 'modal/modalAffirmPurchase';
|
||||||
import ModalRevokeClaim from 'modal/modalRevokeClaim';
|
import ModalRevokeClaim from 'modal/modalRevokeClaim';
|
||||||
import ModalEmailCollection from '../modalEmailCollection';
|
import ModalEmailCollection from 'modal/modalEmailCollection';
|
||||||
import ModalPhoneCollection from '../modalPhoneCollection';
|
import ModalPhoneCollection from 'modal/modalPhoneCollection';
|
||||||
|
import ModalFirstSubscription from 'modal/modalFirstSubscription';
|
||||||
import * as modals from 'constants/modal_types';
|
import * as modals from 'constants/modal_types';
|
||||||
|
|
||||||
class ModalRouter extends React.PureComponent {
|
class ModalRouter extends React.PureComponent {
|
||||||
|
@ -135,6 +136,8 @@ class ModalRouter extends React.PureComponent {
|
||||||
return <ModalPhoneCollection {...modalProps} />;
|
return <ModalPhoneCollection {...modalProps} />;
|
||||||
case modals.EMAIL_COLLECTION:
|
case modals.EMAIL_COLLECTION:
|
||||||
return <ModalEmailCollection {...modalProps} />;
|
return <ModalEmailCollection {...modalProps} />;
|
||||||
|
case modals.FIRST_SUBSCRIPTION:
|
||||||
|
return <ModalFirstSubscription {...modalProps} />;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ export function doDownloadFile(uri, streamInfo) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(doStartDownload(uri, streamInfo.outpoint));
|
dispatch(doStartDownload(uri, streamInfo.outpoint));
|
||||||
|
|
||||||
analytics.apiLog(uri, streamInfo.output, streamInfo.claim_id);
|
analytics.apiLogView(uri, streamInfo.output, streamInfo.claim_id);
|
||||||
|
|
||||||
dispatch(doClaimEligiblePurchaseRewards());
|
dispatch(doClaimEligiblePurchaseRewards());
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,21 +6,30 @@ import Lbry from 'lbry';
|
||||||
import { doPurchaseUri } from 'redux/actions/content';
|
import { doPurchaseUri } from 'redux/actions/content';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { buildURI } from 'lbryURI';
|
import { buildURI } from 'lbryURI';
|
||||||
|
import analytics from 'analytics';
|
||||||
|
|
||||||
const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000;
|
const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000;
|
||||||
|
|
||||||
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) =>
|
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||||
data: subscription,
|
data: subscription,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const doChannelUnsubscribe = (subscription: Subscription) => (dispatch: Dispatch) =>
|
analytics.apiLogSubscribe(subscription);
|
||||||
|
|
||||||
|
dispatch(doCheckSubscription(subscription, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const doChannelUnsubscribe = (subscription: Subscription) => (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||||
data: subscription,
|
data: subscription,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
analytics.apiLogUnsubscribe(subscription);
|
||||||
|
};
|
||||||
|
|
||||||
export const doCheckSubscriptions = () => (
|
export const doCheckSubscriptions = () => (
|
||||||
dispatch: Dispatch,
|
dispatch: Dispatch,
|
||||||
getState: () => SubscriptionState
|
getState: () => SubscriptionState
|
||||||
|
|
Loading…
Add table
Reference in a new issue