From fa09f8a8608619bea6e186796c8aaefe3f9524aa Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 13 Aug 2019 21:24:20 -0400 Subject: [PATCH 01/12] fix: prefil publish links and required lbry-redux publish changes --- package.json | 2 +- src/ui/component/claimPreview/index.js | 10 ++++++++++ src/ui/component/claimPreview/view.jsx | 11 +++++++++-- src/ui/component/fileViewer/view.jsx | 2 +- src/ui/modal/modalAutoGenerateThumbnail/index.js | 3 ++- src/ui/modal/modalConfirmThumbnailUpload/index.js | 3 ++- src/ui/page/file/index.js | 3 ++- yarn.lock | 4 ++-- 8 files changed, 29 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 2e7c64549..55e83e3d3 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "jsmediatags": "^3.8.1", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#05e70648e05c51c51710f6dd698a8e2219b54df2", + "lbry-redux": "lbryio/lbry-redux#58bbdb9a2e537b3994d545ede120d070a7b41ee5", "lbryinc": "lbryio/lbryinc#a93596c51c8fb0a226cb84df04c26a6bb60a45fb", "lint-staged": "^7.0.2", "localforage": "^1.7.1", diff --git a/src/ui/component/claimPreview/index.js b/src/ui/component/claimPreview/index.js index 7b49dc36d..203d81718 100644 --- a/src/ui/component/claimPreview/index.js +++ b/src/ui/component/claimPreview/index.js @@ -1,3 +1,4 @@ +import * as PAGES from 'constants/pages'; import { connect } from 'react-redux'; import { doResolveUri, @@ -10,11 +11,15 @@ import { makeSelectClaimIsNsfw, selectBlockedChannels, selectChannelIsBlocked, + doClearPublish, + doPrepareEdit, } from 'lbry-redux'; import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc'; import { selectShowMatureContent } from 'redux/selectors/settings'; import { makeSelectHasVisitedUri } from 'redux/selectors/content'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; +import { push } from 'connected-react-router'; + import ClaimPreview from './view'; const select = (state, props) => ({ @@ -36,6 +41,11 @@ const select = (state, props) => ({ const perform = dispatch => ({ resolveUri: uri => dispatch(doResolveUri(uri)), + beginPublish: name => { + dispatch(doClearPublish()); + dispatch(doPrepareEdit({ name })); + dispatch(push(`/$/${PAGES.PUBLISH}`)); + }, }); export default connect( diff --git a/src/ui/component/claimPreview/view.jsx b/src/ui/component/claimPreview/view.jsx index d15ed42ad..93f142916 100644 --- a/src/ui/component/claimPreview/view.jsx +++ b/src/ui/component/claimPreview/view.jsx @@ -44,6 +44,7 @@ type Props = { blockedChannelUris: Array, channelIsBlocked: boolean, isSubscribed: boolean, + beginPublish: string => void, }; const ClaimPreview = forwardRef((props: Props, ref: any) => { @@ -68,6 +69,7 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => { showUserBlocked, channelIsBlocked, isSubscribed, + beginPublish, } = props; const haventFetched = claim === undefined; const abandoned = !isResolvingUri && !claim; @@ -77,8 +79,9 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => { const hideActions = type === 'small' || type === 'tooltip'; let isValid; + let name; try { - parseURI(uri); + ({ claimName: name } = parseURI(uri)); isValid = true; } catch (e) { isValid = false; @@ -191,7 +194,11 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => {
{__('Publish something and claim this spot!')}
-
)} diff --git a/src/ui/component/fileViewer/view.jsx b/src/ui/component/fileViewer/view.jsx index 1f96390e8..c67f6ff3c 100644 --- a/src/ui/component/fileViewer/view.jsx +++ b/src/ui/component/fileViewer/view.jsx @@ -87,7 +87,7 @@ export default function FileViewer(props: Props) { const hidePlayer = !isPlaying || !uri || (!inline && (!floatingPlayerEnabled || !isStreamable)); if (hidePlayer) { - clearPlayingUri(); + // clearPlayingUri(); return null; } diff --git a/src/ui/modal/modalAutoGenerateThumbnail/index.js b/src/ui/modal/modalAutoGenerateThumbnail/index.js index d17116afe..da06408b6 100644 --- a/src/ui/modal/modalAutoGenerateThumbnail/index.js +++ b/src/ui/modal/modalAutoGenerateThumbnail/index.js @@ -1,11 +1,12 @@ import { connect } from 'react-redux'; import { doHideModal } from 'redux/actions/app'; import { doToast, doUploadThumbnail } from 'lbry-redux'; +import fs from 'fs'; import ModalAutoGenerateThumbnail from './view'; const perform = dispatch => ({ closeModal: () => dispatch(doHideModal()), - upload: buffer => dispatch(doUploadThumbnail(null, buffer)), + upload: buffer => dispatch(doUploadThumbnail(null, buffer, null, fs)), showToast: options => dispatch(doToast(options)), }); diff --git a/src/ui/modal/modalConfirmThumbnailUpload/index.js b/src/ui/modal/modalConfirmThumbnailUpload/index.js index f30c9a74f..6c5c6858e 100644 --- a/src/ui/modal/modalConfirmThumbnailUpload/index.js +++ b/src/ui/modal/modalConfirmThumbnailUpload/index.js @@ -1,11 +1,12 @@ import { connect } from 'react-redux'; import { doHideModal } from 'redux/actions/app'; import { doUploadThumbnail, doUpdatePublishForm } from 'lbry-redux'; +import fs from 'fs'; import ModalConfirmThumbnailUpload from './view'; const perform = dispatch => ({ closeModal: () => dispatch(doHideModal()), - upload: path => dispatch(doUploadThumbnail(path)), + upload: path => dispatch(doUploadThumbnail(path, null, null, fs)), updatePublishForm: value => dispatch(doUpdatePublishForm(value)), }); diff --git a/src/ui/page/file/index.js b/src/ui/page/file/index.js index d56504d5f..b0f1c6c8e 100644 --- a/src/ui/page/file/index.js +++ b/src/ui/page/file/index.js @@ -22,6 +22,7 @@ import { doFetchViewCount, makeSelectViewCountForUri, makeSelectCostInfoForUri, import { selectShowMatureContent, makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; import { doOpenModal } from 'redux/actions/app'; +import fs from 'fs'; import FilePage from './view'; const select = (state, props) => ({ @@ -47,7 +48,7 @@ const perform = dispatch => ({ fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)), fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)), openModal: (modal, props) => dispatch(doOpenModal(modal, props)), - prepareEdit: (publishData, uri, fileInfo) => dispatch(doPrepareEdit(publishData, uri, fileInfo)), + prepareEdit: (publishData, uri, fileInfo) => dispatch(doPrepareEdit(publishData, uri, fileInfo, fs)), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setViewed: uri => dispatch(doSetContentHistoryItem(uri)), markSubscriptionRead: (channel, uri) => dispatch(doRemoveUnreadSubscription(channel, uri)), diff --git a/yarn.lock b/yarn.lock index 444ae1a62..d1ad5cbbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6762,9 +6762,9 @@ lazy-val@^1.0.3, lazy-val@^1.0.4: yargs "^13.2.2" zstd-codec "^0.1.1" -lbry-redux@lbryio/lbry-redux#05e70648e05c51c51710f6dd698a8e2219b54df2: +lbry-redux@lbryio/lbry-redux#58bbdb9a2e537b3994d545ede120d070a7b41ee5: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/05e70648e05c51c51710f6dd698a8e2219b54df2" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/58bbdb9a2e537b3994d545ede120d070a7b41ee5" dependencies: mime "^2.4.4" proxy-polyfill "0.1.6" -- 2.45.2 From f51cabc5613cacb078cf0ea976c8a12d9cb83925 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 13 Aug 2019 23:04:08 -0400 Subject: [PATCH 02/12] add back file view analytics --- src/ui/analytics.js | 13 +++----- src/ui/component/fileViewer/index.js | 2 ++ src/ui/component/fileViewer/view.jsx | 44 +++++++++++++++++++++------- src/ui/page/settings/index.js | 2 ++ src/ui/page/settings/view.jsx | 2 ++ src/ui/redux/actions/app.js | 25 +++++++++++++++- src/ui/util/use-previous.js | 11 +++++++ 7 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 src/ui/util/use-previous.js diff --git a/src/ui/analytics.js b/src/ui/analytics.js index 2c887eeaa..47e6eeb2f 100644 --- a/src/ui/analytics.js +++ b/src/ui/analytics.js @@ -39,7 +39,7 @@ const analytics: Analytics = { analyticsEnabled = enabled; // @endif }, - apiLogView: (uri, outpoint, claimId, timeToStart, onSuccessCb) => { + apiLogView: (uri, outpoint, claimId, timeToStart) => { if (analyticsEnabled) { const params: { uri: string, @@ -52,17 +52,12 @@ const analytics: Analytics = { claim_id: claimId, }; - if (timeToStart) { + // lbry.tv streams from AWS so we don't care about the time to start + if (timeToStart && !IS_WEB) { params.time_to_start = timeToStart; } - Lbryio.call('file', 'view', params) - .then(() => { - if (onSuccessCb) { - onSuccessCb(); - } - }) - .catch(() => {}); + Lbryio.call('file', 'view', params); } }, apiLogSearch: () => { diff --git a/src/ui/component/fileViewer/index.js b/src/ui/component/fileViewer/index.js index 82249b4bb..5551fec66 100644 --- a/src/ui/component/fileViewer/index.js +++ b/src/ui/component/fileViewer/index.js @@ -12,6 +12,7 @@ import { makeSelectIsPlaying, makeSelectShouldObscurePreview, selectPlayingUri } import { makeSelectClientSetting } from 'redux/selectors/settings'; import { doSetPlayingUri } from 'redux/actions/content'; import { withRouter } from 'react-router'; +import { doAnalyticsView } from 'redux/actions/app'; import FileViewer from './view'; const select = (state, props) => { @@ -32,6 +33,7 @@ const select = (state, props) => { const perform = dispatch => ({ clearPlayingUri: () => dispatch(doSetPlayingUri(null)), + triggerAnalyticsView: (uri, timeToStart) => dispatch(doAnalyticsView(uri, timeToStart)), }); export default withRouter( diff --git a/src/ui/component/fileViewer/view.jsx b/src/ui/component/fileViewer/view.jsx index c67f6ff3c..8797e2baf 100644 --- a/src/ui/component/fileViewer/view.jsx +++ b/src/ui/component/fileViewer/view.jsx @@ -1,12 +1,13 @@ // @flow import * as ICONS from 'constants/icons'; -import React, { useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import Button from 'component/button'; import classnames from 'classnames'; import LoadingScreen from 'component/common/loading-screen'; import FileRender from 'component/fileRender'; import UriIndicator from 'component/uriIndicator'; import usePersistedState from 'util/use-persisted-state'; +import usePrevious from 'util/use-previous'; import { FILE_WRAPPER_CLASS } from 'page/file/view'; import Draggable from 'react-draggable'; import Tooltip from 'component/common/tooltip'; @@ -27,6 +28,7 @@ type Props = { title: ?string, floatingPlayerEnabled: boolean, clearPlayingUri: () => void, + triggerAnalyticsView: (string, number) => void, }; export default function FileViewer(props: Props) { @@ -40,7 +42,9 @@ export default function FileViewer(props: Props) { title, clearPlayingUri, floatingPlayerEnabled, + triggerAnalyticsView, } = props; + const [playTime, setPlayTime] = useState(); const [fileViewerRect, setFileViewerRect] = usePersistedState('inline-file-viewer:rect'); const [position, setPosition] = usePersistedState('floating-file-viewer:position', { x: -25, @@ -54,15 +58,24 @@ export default function FileViewer(props: Props) { ? __("It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds.") : __('Loading'); - function handleDrag(e, ui) { - const { x, y } = position; - const newX = x + ui.deltaX; - const newY = y + ui.deltaY; - setPosition({ - x: newX, - y: newY, - }); - } + const previousUri = usePrevious(uri); + const previousIsReadyToPlay = usePrevious(isReadyToPlay); + const isNewView = uri && previousUri !== uri && isPlaying; + const wasntReadyButNowItIs = isReadyToPlay && !previousIsReadyToPlay; + + useEffect(() => { + if (isNewView) { + setPlayTime(Date.now()); + } + }, [isNewView, uri]); + + useEffect(() => { + if (playTime && isReadyToPlay && wasntReadyButNowItIs) { + const timeToStart = Date.now() - playTime; + triggerAnalyticsView(uri, timeToStart); + setPlayTime(null); + } + }, [setPlayTime, triggerAnalyticsView, isReadyToPlay, wasntReadyButNowItIs, playTime, uri]); useEffect(() => { function handleResize() { @@ -85,9 +98,18 @@ export default function FileViewer(props: Props) { } }, [setFileViewerRect, inline]); + function handleDrag(e, ui) { + const { x, y } = position; + const newX = x + ui.deltaX; + const newY = y + ui.deltaY; + setPosition({ + x: newX, + y: newY, + }); + } + const hidePlayer = !isPlaying || !uri || (!inline && (!floatingPlayerEnabled || !isStreamable)); if (hidePlayer) { - // clearPlayingUri(); return null; } diff --git a/src/ui/page/settings/index.js b/src/ui/page/settings/index.js index 2fcc268c7..56a7c7a43 100644 --- a/src/ui/page/settings/index.js +++ b/src/ui/page/settings/index.js @@ -2,6 +2,7 @@ import { connect } from 'react-redux'; import * as settings from 'constants/settings'; import { doClearCache, doNotifyEncryptWallet, doNotifyDecryptWallet } from 'redux/actions/app'; import { doSetDaemonSetting, doSetClientSetting, doGetThemes, doChangeLanguage } from 'redux/actions/settings'; +import { doSetPlayingUri } from 'redux/actions/content'; import { makeSelectClientSetting, selectDaemonSettings, @@ -40,6 +41,7 @@ const perform = dispatch => ({ encryptWallet: () => dispatch(doNotifyEncryptWallet()), decryptWallet: () => dispatch(doNotifyDecryptWallet()), updateWalletStatus: () => dispatch(doWalletStatus()), + clearPlayingUri: () => dispatch(doSetPlayingUri(null)), }); export default connect( diff --git a/src/ui/page/settings/view.jsx b/src/ui/page/settings/view.jsx index c31decd29..06feac772 100644 --- a/src/ui/page/settings/view.jsx +++ b/src/ui/page/settings/view.jsx @@ -168,6 +168,7 @@ class SettingsPage extends React.PureComponent { hideBalance, userBlockedChannelsCount, floatingPlayer, + clearPlayingUri, } = this.props; const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0; @@ -319,6 +320,7 @@ class SettingsPage extends React.PureComponent { name="floating_player" onChange={() => { setClientSetting(SETTINGS.FLOATING_PLAYER, !floatingPlayer); + clearPlayingUri(); }} checked={floatingPlayer} label={__('Floating video player')} diff --git a/src/ui/redux/actions/app.js b/src/ui/redux/actions/app.js index cd05bba2b..ee5114926 100644 --- a/src/ui/redux/actions/app.js +++ b/src/ui/redux/actions/app.js @@ -6,7 +6,14 @@ import { ipcRenderer, remote } from 'electron'; import path from 'path'; import * as ACTIONS from 'constants/action_types'; import * as MODALS from 'constants/modal_types'; -import { Lbry, doBalanceSubscribe, doFetchFileInfosAndPublishedClaims, doError } from 'lbry-redux'; +import { + Lbry, + doBalanceSubscribe, + doFetchFileInfosAndPublishedClaims, + doError, + makeSelectClaimForUri, + makeSelectClaimIsMine, +} from 'lbry-redux'; import Native from 'native'; import { doFetchDaemonSettings } from 'redux/actions/settings'; import { doCheckSubscriptionsInit } from 'redux/actions/subscriptions'; @@ -24,6 +31,7 @@ import { import { doAuthenticate } from 'lbryinc'; import { lbrySettings as config, version as appVersion } from 'package.json'; import { push } from 'connected-react-router'; +import analytics from 'analytics'; // @if TARGET='app' const { autoUpdater } = remote.require('electron-updater'); @@ -410,3 +418,18 @@ export function doToggleSearchExpanded() { type: ACTIONS.TOGGLE_SEARCH_EXPANDED, }; } + +export function doAnalyticsView(uri, timeToStart) { + return (dispatch, getState) => { + const state = getState(); + const { txid, nout, claim_id: claimId } = makeSelectClaimForUri(uri)(state); + const claimIsMine = makeSelectClaimIsMine(uri)(state); + const outpoint = `${txid}:${nout}`; + + if (claimIsMine) { + return; + } + + analytics.apiLogView(uri, outpoint, claimId, timeToStart); + }; +} diff --git a/src/ui/util/use-previous.js b/src/ui/util/use-previous.js new file mode 100644 index 000000000..ed46581cb --- /dev/null +++ b/src/ui/util/use-previous.js @@ -0,0 +1,11 @@ +import { useEffect, useRef } from 'react'; + +export default function usePrevious(value) { + const ref = useRef(); + + useEffect(() => { + ref.current = value; + }, [value]); + + return ref.current; +} -- 2.45.2 From 00e03ff6bef40bb128bd4006996b6ca027720a87 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 13 Aug 2019 23:09:25 -0400 Subject: [PATCH 03/12] fix: only autoplay streamable files --- src/ui/component/fileViewerInitiator/view.jsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ui/component/fileViewerInitiator/view.jsx b/src/ui/component/fileViewerInitiator/view.jsx index 7572b6f77..a8e5142a9 100644 --- a/src/ui/component/fileViewerInitiator/view.jsx +++ b/src/ui/component/fileViewerInitiator/view.jsx @@ -25,7 +25,18 @@ type Props = { }; export default function FileViewer(props: Props) { - const { play, mediaType, isPlaying, fileInfo, uri, obscurePreview, insufficientCredits, thumbnail, autoplay } = props; + const { + play, + mediaType, + isPlaying, + fileInfo, + uri, + obscurePreview, + insufficientCredits, + thumbnail, + autoplay, + isStreamable, + } = props; const isPlayable = ['audio', 'video'].indexOf(mediaType) !== -1; const fileStatus = fileInfo && fileInfo.status; @@ -64,10 +75,10 @@ export default function FileViewer(props: Props) { useEffect(() => { const videoOnPage = document.querySelector('video'); - if (autoplay && !videoOnPage) { + if (autoplay && !videoOnPage && isStreamable) { viewFile(); } - }, [autoplay, viewFile]); + }, [autoplay, viewFile, isStreamable]); return (
Date: Tue, 13 Aug 2019 23:56:11 -0400 Subject: [PATCH 04/12] general player fixes --- package.json | 2 +- src/ui/analytics.js | 2 +- src/ui/component/fileDownloadLink/view.jsx | 4 +--- src/ui/modal/modalRemoveFile/view.jsx | 2 +- src/ui/redux/actions/file.js | 3 +++ src/ui/scss/component/_content.scss | 9 ++++----- yarn.lock | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 55e83e3d3..609de08c9 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "jsmediatags": "^3.8.1", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#58bbdb9a2e537b3994d545ede120d070a7b41ee5", + "lbry-redux": "lbryio/lbry-redux#4e093983eaf3d9e7513119657d731b808ead74a6", "lbryinc": "lbryio/lbryinc#a93596c51c8fb0a226cb84df04c26a6bb60a45fb", "lint-staged": "^7.0.2", "localforage": "^1.7.1", diff --git a/src/ui/analytics.js b/src/ui/analytics.js index 47e6eeb2f..7aff3a2f5 100644 --- a/src/ui/analytics.js +++ b/src/ui/analytics.js @@ -40,7 +40,7 @@ const analytics: Analytics = { // @endif }, apiLogView: (uri, outpoint, claimId, timeToStart) => { - if (analyticsEnabled) { + if (analyticsEnabled && isProduction) { const params: { uri: string, outpoint: string, diff --git a/src/ui/component/fileDownloadLink/view.jsx b/src/ui/component/fileDownloadLink/view.jsx index f41035954..488be2b3b 100644 --- a/src/ui/component/fileDownloadLink/view.jsx +++ b/src/ui/component/fileDownloadLink/view.jsx @@ -23,9 +23,7 @@ function FileDownloadLink(props: Props) { if (loading || downloading) { const progress = fileInfo && fileInfo.written_bytes > 0 ? (fileInfo.written_bytes / fileInfo.total_bytes) * 100 : 0; const label = - fileInfo && fileInfo.written_bytes > 0 - ? __('Downloading: ') + progress.toFixed(0) + __('% complete') - : __('Connecting...'); + fileInfo && fileInfo.written_bytes > 0 ? progress.toFixed(0) + __('% downloaded') : __('Connecting...'); return {label}; } diff --git a/src/ui/modal/modalRemoveFile/view.jsx b/src/ui/modal/modalRemoveFile/view.jsx index 9fca2e35a..ccf05e277 100644 --- a/src/ui/modal/modalRemoveFile/view.jsx +++ b/src/ui/modal/modalRemoveFile/view.jsx @@ -54,7 +54,7 @@ function ModalRemoveFile(props: Props) { button="primary" label={__('OK')} disabled={!deleteChecked && !abandonChecked} - onClick={() => deleteFile(outpoint || '', deleteChecked, abandonChecked)} + onClick={() => deleteFile(outpoint || '', deleteChecked, claimIsMine ? abandonChecked : false)} />
diff --git a/src/ui/redux/actions/file.js b/src/ui/redux/actions/file.js index 99b95cd7c..5bd4abc75 100644 --- a/src/ui/redux/actions/file.js +++ b/src/ui/redux/actions/file.js @@ -5,6 +5,7 @@ import { shell } from 'electron'; import { Lbry, batchActions, doAbandonClaim, selectMyClaimsOutpoints } from 'lbry-redux'; import { doHideModal } from 'redux/actions/app'; import { goBack } from 'connected-react-router'; +import { doSetPlayingUri } from 'redux/actions/content'; export function doOpenFileInFolder(path) { return () => { @@ -52,7 +53,9 @@ export function doDeleteFileAndMaybeGoBack(fileInfo, deleteFromComputer, abandon const actions = []; actions.push(doHideModal()); actions.push(doDeleteFile(fileInfo, deleteFromComputer, abandonClaim)); + actions.push(doSetPlayingUri(null)); dispatch(batchActions(...actions)); + if (abandonClaim) { dispatch(goBack()); } diff --git a/src/ui/scss/component/_content.scss b/src/ui/scss/component/_content.scss index cc59f2bb6..99ad73011 100644 --- a/src/ui/scss/component/_content.scss +++ b/src/ui/scss/component/_content.scss @@ -23,6 +23,9 @@ position: relative; width: 100%; height: 100%; + // display: flex; + // flex-direction: column; + // justify-content: space-between; } .content__wrapper--floating { @@ -85,11 +88,7 @@ } .content__loading { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; + height: 100%; display: flex; align-items: center; flex-direction: column; diff --git a/yarn.lock b/yarn.lock index d1ad5cbbf..9d9bc61f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6762,9 +6762,9 @@ lazy-val@^1.0.3, lazy-val@^1.0.4: yargs "^13.2.2" zstd-codec "^0.1.1" -lbry-redux@lbryio/lbry-redux#58bbdb9a2e537b3994d545ede120d070a7b41ee5: +lbry-redux@lbryio/lbry-redux#4e093983eaf3d9e7513119657d731b808ead74a6: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/58bbdb9a2e537b3994d545ede120d070a7b41ee5" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/4e093983eaf3d9e7513119657d731b808ead74a6" dependencies: mime "^2.4.4" proxy-polyfill "0.1.6" -- 2.45.2 From 70fc45464782c80135b80e57890ad2a24ec938a2 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 14 Aug 2019 00:10:27 -0400 Subject: [PATCH 05/12] v0.35.0-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 609de08c9..d9865cae5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.34.2", + "version": "0.35.0-rc.1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "keywords": [ "lbry" -- 2.45.2 From e589a872986c42aa7cb1f586207017e74d09573d Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 14 Aug 2019 12:28:13 -0400 Subject: [PATCH 06/12] add analytics for version/email/reward eligibility --- package.json | 2 +- src/ui/analytics.js | 43 +++++++++++++++++++++++--- src/ui/component/app/view.jsx | 24 +++++++++++--- src/ui/component/userEmailNew/view.jsx | 2 ++ yarn.lock | 4 +-- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index d9865cae5..0627fa89e 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", "lbry-redux": "lbryio/lbry-redux#4e093983eaf3d9e7513119657d731b808ead74a6", - "lbryinc": "lbryio/lbryinc#a93596c51c8fb0a226cb84df04c26a6bb60a45fb", + "lbryinc": "lbryio/lbryinc#1ce266b3c52654190b955e9c869b8e302aa5c585", "lint-staged": "^7.0.2", "localforage": "^1.7.1", "lodash-es": "^4.17.14", diff --git a/src/ui/analytics.js b/src/ui/analytics.js index 7aff3a2f5..373a20ca2 100644 --- a/src/ui/analytics.js +++ b/src/ui/analytics.js @@ -3,6 +3,7 @@ import { Lbryio } from 'lbryinc'; import ReactGA from 'react-ga'; import { history } from './store'; // @if TARGET='app' +import Native from 'native'; import ElectronCookies from '@exponent/electron-cookies'; // @endif @@ -15,6 +16,9 @@ type Analytics = { apiLogView: (string, string, string, ?number, ?() => void) => void, apiLogPublish: () => void, tagFollowEvent: (string, boolean, string) => void, + emailProvidedEvent: () => void, + emailVerifiedEvent: () => void, + rewardEligibleEvent: () => void, }; let analyticsEnabled: boolean = true; @@ -26,11 +30,18 @@ const analytics: Analytics = { }, setUser: userId => { if (analyticsEnabled && userId) { - ReactGA.event({ - category: 'User', - action: 'userId', - value: userId, + ReactGA.set({ + userId, }); + + // @if TARGET='app' + Native.getAppVersionInfo().then(({ localVersion }) => { + ReactGA.event({ + category: 'Desktop-Version', + action: localVersion, + }); + }); + // @endif } }, toggle: (enabled: boolean): void => { @@ -92,6 +103,30 @@ const analytics: Analytics = { }); } }, + emailProvidedEvent: () => { + if (analyticsEnabled && isProduction) { + ReactGA.event({ + category: 'Engagement', + action: 'Email-Provided', + }); + } + }, + emailVerifiedEvent: () => { + if (analyticsEnabled && isProduction) { + ReactGA.event({ + category: 'Engagement', + action: 'Email-Verified', + }); + } + }, + rewardEligibleEvent: () => { + if (analyticsEnabled && isProduction) { + ReactGA.event({ + category: 'Engagement', + action: 'Reward-Eligible', + }); + } + }, }; // Initialize google analytics diff --git a/src/ui/component/app/view.jsx b/src/ui/component/app/view.jsx index 80501bce8..b337e9c93 100644 --- a/src/ui/component/app/view.jsx +++ b/src/ui/component/app/view.jsx @@ -12,6 +12,7 @@ import useKonamiListener from 'util/enhanced-layout'; import Yrbl from 'component/yrbl'; import FileViewer from 'component/fileViewer'; import { withRouter } from 'react-router'; +import usePrevious from 'util/use-previous'; export const MAIN_WRAPPER_CLASS = 'main-wrapper'; @@ -21,7 +22,7 @@ type Props = { language: string, theme: string, accessToken: ?string, - user: ?{ id: string, has_verified_email: boolean }, + user: ?{ id: string, has_verified_email: boolean, is_reward_approved: boolean }, location: { pathname: string }, fetchRewards: () => void, fetchRewardedContent: () => void, @@ -35,7 +36,10 @@ function App(props: Props) { const isEnhancedLayout = useKonamiListener(); const userId = user && user.id; const hasVerifiedEmail = user && user.has_verified_email; - + const isRewardApproved = user && user.is_reward_approved; + const previousUserId = usePrevious(userId); + const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail); + const previousRewardApproved = usePrevious(isRewardApproved); const { pathname } = props.location; const urlParts = pathname.split('/'); const claimName = urlParts[1]; @@ -65,10 +69,22 @@ function App(props: Props) { }, [theme]); useEffect(() => { - if (userId) { + if (previousUserId === undefined && userId) { analytics.setUser(userId); } - }, [userId]); + }, [previousUserId, userId]); + + useEffect(() => { + if (previousHasVerifiedEmail !== undefined && hasVerifiedEmail) { + analytics.emailVerifiedEvent(); + } + }, [previousHasVerifiedEmail, hasVerifiedEmail]); + + useEffect(() => { + if (previousRewardApproved !== undefined && isRewardApproved) { + analytics.rewardEligibleEvent(); + } + }, [previousRewardApproved, isRewardApproved]); // @if TARGET='web' useEffect(() => { diff --git a/src/ui/component/userEmailNew/view.jsx b/src/ui/component/userEmailNew/view.jsx index 4e8129c71..0fe2f8b62 100644 --- a/src/ui/component/userEmailNew/view.jsx +++ b/src/ui/component/userEmailNew/view.jsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { FormField, Form } from 'component/common/form'; import Button from 'component/button'; import { Lbryio } from 'lbryinc'; +import analytics from 'analytics'; type Props = { cancelButton: React.Node, @@ -37,6 +38,7 @@ class UserEmailNew extends React.PureComponent { const { email } = this.state; const { addUserEmail } = this.props; addUserEmail(email); + analytics.emailProvidedEvent(); // @if TARGET='web' Lbryio.call('user_tag', 'edit', { add: 'lbrytv' }); diff --git a/yarn.lock b/yarn.lock index 9d9bc61f7..0b78fb183 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6771,9 +6771,9 @@ lbry-redux@lbryio/lbry-redux#4e093983eaf3d9e7513119657d731b808ead74a6: reselect "^3.0.0" uuid "^3.3.2" -lbryinc@lbryio/lbryinc#a93596c51c8fb0a226cb84df04c26a6bb60a45fb: +lbryinc@lbryio/lbryinc#1ce266b3c52654190b955e9c869b8e302aa5c585: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/a93596c51c8fb0a226cb84df04c26a6bb60a45fb" + resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/1ce266b3c52654190b955e9c869b8e302aa5c585" dependencies: reselect "^3.0.0" -- 2.45.2 From 3c39dbf01e682cadc4f7d4ef1235f42f3b42dbf2 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 14 Aug 2019 12:31:34 -0400 Subject: [PATCH 07/12] disable user drag on links and images --- src/ui/scss/init/_gui.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/scss/init/_gui.scss b/src/ui/scss/init/_gui.scss index afb5685ca..018172e55 100644 --- a/src/ui/scss/init/_gui.scss +++ b/src/ui/scss/init/_gui.scss @@ -98,6 +98,11 @@ hr { } } +img, +a { + -webkit-user-drag: none; +} + .columns { display: flex; justify-content: space-between; -- 2.45.2 From c20f491457a1358182fd68cead6fce041fffd389 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 14 Aug 2019 14:09:45 -0400 Subject: [PATCH 08/12] cleanup --- package.json | 2 +- src/ui/component/common/icon.jsx | 2 +- src/ui/component/fileDetails/view.jsx | 1 + src/ui/component/fileProperties/index.js | 4 ++-- src/ui/redux/selectors/subscriptions.js | 6 +++++- src/ui/scss/component/_button.scss | 10 ++++++++++ src/ui/scss/component/_content.scss | 3 --- src/ui/scss/component/_file-render.scss | 7 +++++++ yarn.lock | 4 ++-- 9 files changed, 29 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 0627fa89e..6e250b5ad 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "jsmediatags": "^3.8.1", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#4e093983eaf3d9e7513119657d731b808ead74a6", + "lbry-redux": "lbryio/lbry-redux#1bd625f0c6e9e36d14eb0c520a3eb99f9600705d", "lbryinc": "lbryio/lbryinc#1ce266b3c52654190b955e9c869b8e302aa5c585", "lint-staged": "^7.0.2", "localforage": "^1.7.1", diff --git a/src/ui/component/common/icon.jsx b/src/ui/component/common/icon.jsx index 480bc47f8..75e66b091 100644 --- a/src/ui/component/common/icon.jsx +++ b/src/ui/component/common/icon.jsx @@ -25,7 +25,7 @@ class IconComponent extends React.PureComponent { case ICONS.FEATURED: return __('Featured content. Earn rewards for watching.'); case ICONS.DOWNLOAD: - return __('This file is downloaded.'); + return __('This file is in your library.'); case ICONS.SUBSCRIBE: return __('You are subscribed to this channel.'); case ICONS.SETTINGS: diff --git a/src/ui/component/fileDetails/view.jsx b/src/ui/component/fileDetails/view.jsx index 72cc8a869..8682359d5 100644 --- a/src/ui/component/fileDetails/view.jsx +++ b/src/ui/component/fileDetails/view.jsx @@ -77,6 +77,7 @@ class FileDetails extends PureComponent { {': '}