From b8ac8a0340a03bdc4bc4695009821a8d03938dba Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Mon, 1 Apr 2019 10:30:19 -0400 Subject: [PATCH 1/4] add google analytics --- package.json | 2 +- src/ui/analytics.js | 58 ++++++++++----------- src/ui/component/button/view.jsx | 10 +++- src/ui/component/navigationHistory/view.jsx | 1 - src/ui/index.jsx | 20 ------- src/ui/redux/actions/settings.js | 2 +- yarn.lock | 10 ++-- 7 files changed, 44 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index dccc9bd29..717496e30 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,6 @@ "make-runnable": "^1.3.6", "mammoth": "^1.4.6", "mime": "^2.3.1", - "mixpanel-browser": "^2.17.1", "moment": "^2.22.0", "node-abi": "^2.5.1", "node-fetch": "^2.3.0", @@ -130,6 +129,7 @@ "react": "^16.8.2", "react-dom": "^16.8.2", "react-feather": "^1.0.8", + "react-ga": "^2.5.7", "react-hot-loader": "^4.7.2", "react-modal": "^3.1.7", "react-paginate": "^5.2.1", diff --git a/src/ui/analytics.js b/src/ui/analytics.js index 48b684591..58e7581cc 100644 --- a/src/ui/analytics.js +++ b/src/ui/analytics.js @@ -1,48 +1,31 @@ // @flow -import mixpanel from 'mixpanel-browser'; import { Lbryio } from 'lbryinc'; -import isDev from 'electron-is-dev'; - -if (isDev) { - mixpanel.init('691723e855cabb9d27a7a79002216967'); -} else { - mixpanel.init('af5c6b8110068fa4f5c4600c81f05e60'); -} +import ReactGA from 'react-ga'; +import { globalHistory } from '@reach/router'; type Analytics = { - track: (string, ?Object) => void, + pageView: string => void, setUser: Object => void, toggle: (boolean, ?boolean) => void, apiLogView: (string, string, string, ?number, ?() => void) => void, apiLogPublish: () => void, }; -let analyticsEnabled: boolean = false; - +let analyticsEnabled: boolean = true; const analytics: Analytics = { - track: (name, payload) => { + pageView: path => { if (analyticsEnabled) { - if (payload) { - mixpanel.track(name, payload); - } else { - mixpanel.track(name); - } + ReactGA.pageview(path); } }, setUser: user => { - if (user.id) { - mixpanel.identify(user.id); - } - if (user.primary_email) { - mixpanel.people.set({ - $email: 1, - }); - } + // Commented out because currently there is some delay before we know the user + // We should retrieve this server side so we have it immediately + // if (analyticsEnabled && user.id) { + // ReactGA.set('userId', user.id); + // } }, - toggle: (enabled: boolean, logDisabled: ?boolean): void => { - if (!enabled && logDisabled) { - mixpanel.track('DISABLED'); - } + toggle: (enabled: boolean): void => { analyticsEnabled = enabled; }, apiLogView: (uri, outpoint, claimId, timeToStart, onSuccessCb) => { @@ -87,4 +70,21 @@ const analytics: Analytics = { }, }; +// Initialize google analytics +// Set `debug: true` for debug info +ReactGA.initialize('UA-60403362-12', { + gaOptions: { name: IS_WEB ? 'web' : 'desktop' }, + testMode: process.env.NODE_ENV !== 'production', +}); + +// Manually call the first page view +// Reach Router doesn't include this on `history.listen` +analytics.pageView(window.location.pathname + window.location.search); + +// Listen for url changes and report +// This will include search queries/filter options +globalHistory.listen(({ location }) => + analytics.pageView(window.location.pathname + window.location.search) +); + export default analytics; diff --git a/src/ui/component/button/view.jsx b/src/ui/component/button/view.jsx index a92322175..8bee0261b 100644 --- a/src/ui/component/button/view.jsx +++ b/src/ui/component/button/view.jsx @@ -4,6 +4,7 @@ import Icon from 'component/common/icon'; import classnames from 'classnames'; import { Link } from '@reach/router'; import { formatLbryUriForWeb } from 'util/uri'; +import { OutboundLink } from 'react-ga'; type Props = { onClick: ?(any) => any, @@ -85,9 +86,14 @@ class Button extends React.PureComponent { if (href) { return ( - + {content} - + ); } diff --git a/src/ui/component/navigationHistory/view.jsx b/src/ui/component/navigationHistory/view.jsx index bc05f8dfd..57031a3d6 100644 --- a/src/ui/component/navigationHistory/view.jsx +++ b/src/ui/component/navigationHistory/view.jsx @@ -93,7 +93,6 @@ class UserHistoryPage extends React.PureComponent { render() { const { history = [], page, pageCount } = this.props; - const { itemsSelected } = this.state; const allSelected = Object.keys(itemsSelected).length === history.length; const selectHandler = allSelected ? this.unselectAll : this.selectAll; diff --git a/src/ui/index.jsx b/src/ui/index.jsx index 72e0d8931..6d21bcb86 100644 --- a/src/ui/index.jsx +++ b/src/ui/index.jsx @@ -173,26 +173,6 @@ document.addEventListener('click', event => { let { target } = event; while (target && target !== document) { - if (target.matches('a') || target.matches('button')) { - // TODO: Look into using accessiblity labels (this would also make the app more accessible) - const hrefParts = window.location.href.split('#'); - - // Buttons that we want to track should use `data-id` - // This prevents multiple buttons being grouped together if they have the same text - const element = - target.dataset.id || target.title || (target.textContent && target.textContent.trim()); - if (element) { - analytics.track('CLICK', { - target: element, - location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/', - }); - } else { - analytics.track('UNMARKED_CLICK', { - location: hrefParts.length > 1 ? hrefParts[hrefParts.length - 1] : '/', - source: target.outerHTML, - }); - } - } if (target.matches('a[href^="http"]') || target.matches('a[href^="mailto"]')) { // @if TARGET='app' event.preventDefault(); diff --git a/src/ui/redux/actions/settings.js b/src/ui/redux/actions/settings.js index b09c56283..54ab1f2fb 100644 --- a/src/ui/redux/actions/settings.js +++ b/src/ui/redux/actions/settings.js @@ -30,7 +30,7 @@ export function doSetDaemonSetting(key, value) { }; Lbry.settings_set(newSettings).then(newSettings); Lbry.settings_get().then(settings => { - analytics.toggle(settings.share_usage_data, true); + analytics.toggle(settings.share_usage_data); dispatch({ type: ACTIONS.DAEMON_SETTINGS_RECEIVED, data: { diff --git a/yarn.lock b/yarn.lock index 7572faae7..0681b2e27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6938,11 +6938,6 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mixpanel-browser@^2.17.1: - version "2.26.0" - resolved "https://registry.yarnpkg.com/mixpanel-browser/-/mixpanel-browser-2.26.0.tgz#0f2108d36c8170dab32dd16cabac6eb13138652e" - integrity sha512-aIRtoMvv6B+syslAvYyk+seuYObm0TeOxQz2JZqquZTEa+Kw9cNTVRA+H1s7QY1QFOKrk94gkmLdKJbwcOcG5w== - mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -8626,6 +8621,11 @@ react-feather@^1.0.8: resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-1.1.6.tgz#2a547e3d5cd5e383d3da0128d593cbdb3c1b32f7" integrity sha512-iCofWhTjX+vQwvDmg7o6vg0XrUg1c41yBDZG+l83nz1FiCsleJoUgd3O+kHpOeWMXuPrRIFfCixvcqyOLGOgIg== +react-ga@^2.5.7: + version "2.5.7" + resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.5.7.tgz#1c80a289004bf84f84c26d46f3a6a6513081bf2e" + integrity sha512-UmATFaZpEQDO96KFjB5FRLcT6hFcwaxOmAJZnjrSiFN/msTqylq9G+z5Z8TYzN/dbamDTiWf92m6MnXXJkAivQ== + react-hot-loader@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.7.2.tgz#54cd99441c2d594bdc58c90673690c245dcfcaff" -- 2.45.2 From 5251ce509063e2173adf89ca2082a17b2e7d6d60 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Mon, 1 Apr 2019 23:25:26 -0400 Subject: [PATCH 2/4] add hover effect for file cards --- src/ui/scss/component/_media.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ui/scss/component/_media.scss b/src/ui/scss/component/_media.scss index e4c209c86..81624e156 100644 --- a/src/ui/scss/component/_media.scss +++ b/src/ui/scss/component/_media.scss @@ -10,6 +10,16 @@ .media__properties { height: 1em; } + + &:hover { + box-shadow: 0 0 50px rgba($lbry-black, 0.08); + background-color: rgba($lbry-black, 0.04); + + html[data-mode='dark'] & { + box-shadow: 0 0 50px rgba($lbry-white, 0.07); + background-color: rgba($lbry-white, 0.03); + } + } } // M E D I A -- 2.45.2 From 497e499c622f0830989359ef26c35f5dc4c13e5b Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 2 Apr 2019 00:30:19 -0400 Subject: [PATCH 3/4] temp fix to scroll to top on navigate --- src/ui/component/app/view.jsx | 4 +-- src/ui/component/router/view.jsx | 61 ++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/ui/component/app/view.jsx b/src/ui/component/app/view.jsx index 8f2ea7f64..74be7a2d6 100644 --- a/src/ui/component/app/view.jsx +++ b/src/ui/component/app/view.jsx @@ -70,14 +70,14 @@ class App extends React.PureComponent { return (
openContextMenu(e)}>
-
+
{enhancedLayout && }
-
+
); } diff --git a/src/ui/component/router/view.jsx b/src/ui/component/router/view.jsx index 6f8de4ae9..03cd902fc 100644 --- a/src/ui/component/router/view.jsx +++ b/src/ui/component/router/view.jsx @@ -1,5 +1,5 @@ import * as PAGES from 'constants/pages'; -import React from 'react'; +import React, { useEffect } from 'react'; import { Router } from '@reach/router'; import SettingsPage from 'page/settings'; import HelpPage from 'page/help'; @@ -21,31 +21,46 @@ import UserHistoryPage from 'page/userHistory'; import SendCreditsPage from 'page/sendCredits'; import NavigationHistory from 'page/navigationHistory'; -export default function AppRouter(props) { +const ScrollHandler = props => { + const { key } = props.location; + + useEffect(() => { + // This shouldn't scroll to top when you click "back" + // Might take some more work but fixes scroll position being stuck on navigation for now + const main = document.querySelector('main'); + main.scrollIntoView(); + }, [key]); + + return props.children; +}; + +export default function AppRouter() { return ( - - - + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + ); } -- 2.45.2 From dcafe9ab9e8850a09c24b51efa370e402c6f5487 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 3 Apr 2019 00:17:00 -0400 Subject: [PATCH 4/4] replace insufficient credits modal with inline ui elements --- flow-typed/web.js | 3 + src/ui/component/common/lbc-symbol.jsx | 2 +- .../component/fileViewer/internal/player.jsx | 4 +- src/ui/component/fileViewer/view.jsx | 13 +- src/ui/component/header/view.jsx | 4 +- src/ui/component/publishForm/view.jsx | 3 +- src/ui/component/router/view.jsx | 1 + src/ui/component/yrbl/index.jsx | 8 +- src/ui/constants/modal_types.js | 1 - src/ui/modal/modalCreditIntro/index.js | 31 --- src/ui/modal/modalCreditIntro/view.jsx | 56 ----- src/ui/modal/modalRouter/index.js | 15 +- src/ui/modal/modalRouter/view.jsx | 209 +++++------------- src/ui/page/file/index.js | 2 + src/ui/page/file/view.jsx | 28 ++- src/ui/page/publish/index.js | 2 + src/ui/page/publish/view.jsx | 52 ++++- src/ui/redux/actions/content.js | 1 - src/ui/scss/component/_card.scss | 15 +- src/ui/scss/component/_content.scss | 5 + src/ui/scss/component/_header.scss | 8 + src/ui/scss/component/_media.scss | 4 + src/ui/scss/component/_yrbl.scss | 8 +- src/ui/scss/init/_gui.scss | 2 +- src/ui/scss/init/_vars.scss | 1 + 25 files changed, 202 insertions(+), 276 deletions(-) create mode 100644 flow-typed/web.js delete mode 100644 src/ui/modal/modalCreditIntro/index.js delete mode 100644 src/ui/modal/modalCreditIntro/view.jsx diff --git a/flow-typed/web.js b/flow-typed/web.js new file mode 100644 index 000000000..69b1914e0 --- /dev/null +++ b/flow-typed/web.js @@ -0,0 +1,3 @@ +// @flow + +declare var IS_WEB: boolean; diff --git a/src/ui/component/common/lbc-symbol.jsx b/src/ui/component/common/lbc-symbol.jsx index 612247836..0fb91fe46 100644 --- a/src/ui/component/common/lbc-symbol.jsx +++ b/src/ui/component/common/lbc-symbol.jsx @@ -1,6 +1,6 @@ // @flow import React from 'react'; -const LbcSymbol = () => LBC; // ℄ +const LbcSymbol = () => LBC; // ℄ export default LbcSymbol; diff --git a/src/ui/component/fileViewer/internal/player.jsx b/src/ui/component/fileViewer/internal/player.jsx index 0cb98774a..cc602c63e 100644 --- a/src/ui/component/fileViewer/internal/player.jsx +++ b/src/ui/component/fileViewer/internal/player.jsx @@ -202,8 +202,8 @@ class MediaPlayer extends React.PureComponent { } // @if TARGET='app' - sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); } refreshMetadata() { diff --git a/src/ui/component/fileViewer/view.jsx b/src/ui/component/fileViewer/view.jsx index 914d8ceef..34336951c 100644 --- a/src/ui/component/fileViewer/view.jsx +++ b/src/ui/component/fileViewer/view.jsx @@ -47,6 +47,7 @@ type Props = { nextFileToPlay: ?string, navigate: (string, {}) => void, costInfo: ?{ cost: number }, + insufficientCredits: boolean, }; class FileViewer extends React.PureComponent { @@ -150,7 +151,11 @@ class FileViewer extends React.PureComponent { } playContent() { - const { play, uri, fileInfo, isDownloading, isLoading } = this.props; + const { play, uri, fileInfo, isDownloading, isLoading, insufficientCredits } = this.props; + + if (insufficientCredits) { + return; + } // @if TARGET='app' if (fileInfo || isDownloading || isLoading) { @@ -220,6 +225,7 @@ class FileViewer extends React.PureComponent { className, obscureNsfw, mediaType, + insufficientCredits, } = this.props; const isPlaying = playingUri === uri; @@ -246,7 +252,10 @@ class FileViewer extends React.PureComponent { } const poster = metadata && metadata.thumbnail; - const layoverClass = classnames('content__cover', { 'card__media--nsfw': shouldObscureNsfw }); + const layoverClass = classnames('content__cover', { + 'card__media--nsfw': shouldObscureNsfw, + 'card__media--disabled': insufficientCredits, + }); const layoverStyle = !shouldObscureNsfw && poster ? { backgroundImage: `url("${poster}")` } : {}; diff --git a/src/ui/component/header/view.jsx b/src/ui/component/header/view.jsx index 75d923e62..769571697 100644 --- a/src/ui/component/header/view.jsx +++ b/src/ui/component/header/view.jsx @@ -85,8 +85,7 @@ const Header = (props: Props) => { title={`Your balance is ${balance} LBRY Credits`} label={ - {roundedBalance} - + {roundedBalance} } navigate="/$/wallet" @@ -94,6 +93,7 @@ const Header = (props: Props) => {