From c88961002fe2ed04afd2d5be2e662c63c9f6694d Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Fri, 6 Sep 2019 19:43:47 +0100 Subject: [PATCH] canonical url and transform updates (#38) * canonical url and transform updates * account unlock after sync apply * fix featured search item * unlock after sync apply * pin lbryinc commit * fix featured search result item stuck loading --- package-lock.json | 8 ++--- package.json | 4 +-- src/component/AppNavigator.js | 4 +-- src/component/claimList/view.js | 7 +---- src/component/fileListItem/view.js | 11 +++++++ src/component/uriBar/view.js | 19 ++++++++---- src/page/firstRun/index.js | 2 +- src/page/firstRun/view.js | 29 ++++++++++++++----- src/page/splash/view.js | 10 +++---- src/page/verification/index.js | 6 ++-- .../verification/internal/sync-verify-page.js | 28 ++++++++++++++---- src/page/wallet/view.js | 2 +- src/utils/helper.js | 8 ++++- 13 files changed, 94 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index 824a37d..7139a04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5574,8 +5574,8 @@ } }, "lbry-redux": { - "version": "github:lbryio/lbry-redux#c74deed2a63e1acd0d1827ed9b954242d74e2a1e", - "from": "github:lbryio/lbry-redux#c74deed2a63e1acd0d1827ed9b954242d74e2a1e", + "version": "github:lbryio/lbry-redux#362d764c4c0de23032b6871b4d54207dc548028c", + "from": "github:lbryio/lbry-redux#362d764c4c0de23032b6871b4d54207dc548028c", "requires": { "proxy-polyfill": "0.1.6", "reselect": "^3.0.0", @@ -5583,8 +5583,8 @@ } }, "lbryinc": { - "version": "github:lbryio/lbryinc#4c761084990557d379c85e1c998fcae7e5db143a", - "from": "github:lbryio/lbryinc#4c761084990557d379c85e1c998fcae7e5db143a", + "version": "github:lbryio/lbryinc#b9f354ae50bd57691765a7d042c5054167878bf4", + "from": "github:lbryio/lbryinc#b9f354ae50bd57691765a7d042c5054167878bf4", "requires": { "reselect": "^3.0.0" } diff --git a/package.json b/package.json index d94945e..c8413f3 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "base-64": "^0.1.0", "@expo/vector-icons": "^8.1.0", "gfycat-style-urls": "^1.0.3", - "lbry-redux": "lbryio/lbry-redux#c74deed2a63e1acd0d1827ed9b954242d74e2a1e", - "lbryinc": "lbryio/lbryinc#4c761084990557d379c85e1c998fcae7e5db143a", + "lbry-redux": "lbryio/lbry-redux#362d764c4c0de23032b6871b4d54207dc548028c", + "lbryinc": "lbryio/lbryinc#b9f354ae50bd57691765a7d042c5054167878bf4", "lodash": ">=4.17.11", "merge": ">=1.2.1", "moment": "^2.22.1", diff --git a/src/component/AppNavigator.js b/src/component/AppNavigator.js index 9b5c1b7..c737581 100644 --- a/src/component/AppNavigator.js +++ b/src/component/AppNavigator.js @@ -40,7 +40,7 @@ import { } from 'lbryinc'; import { makeSelectClientSetting } from 'redux/selectors/settings'; import { decode as atob } from 'base-64'; -import { dispatchNavigateBack, dispatchNavigateToUri } from 'utils/helper'; +import { dispatchNavigateBack, dispatchNavigateToUri, transformUrl } from 'utils/helper'; import AsyncStorage from '@react-native-community/async-storage'; import Colors from 'styles/colors'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api @@ -413,7 +413,7 @@ class AppWithNavigationState extends React.Component { ); } } else { - dispatchNavigateToUri(dispatch, nav, evt.url); + dispatchNavigateToUri(dispatch, nav, transformUrl(evt.url)); } } }; diff --git a/src/component/claimList/view.js b/src/component/claimList/view.js index 208e8c6..3f447d1 100644 --- a/src/component/claimList/view.js +++ b/src/component/claimList/view.js @@ -204,12 +204,7 @@ class ClaimList extends React.PureComponent { const options = this.buildClaimSearchOptions(); const claimSearchKey = createNormalizedClaimSearchKey(options); - let uris = claimSearchByQuery[claimSearchKey]; - - if (uris) { - // temporary workaround for missing short_urls - uris = uris.filter(uri => uri && uri.length > 0); - } + const uris = claimSearchByQuery[claimSearchKey]; if (Constants.ORIENTATION_VERTICAL === orientation) { return ( diff --git a/src/component/fileListItem/view.js b/src/component/fileListItem/view.js index 96b5119..c2faa83 100644 --- a/src/component/fileListItem/view.js +++ b/src/component/fileListItem/view.js @@ -13,6 +13,10 @@ import ProgressBar from 'component/progressBar'; import fileListStyle from 'styles/fileList'; class FileListItem extends React.PureComponent { + state = { + url: null, + }; + getStorageForFileInfo = fileInfo => { if (!fileInfo.completed) { const written = formatBytes(fileInfo.written_bytes); @@ -42,6 +46,13 @@ class FileListItem extends React.PureComponent { } } + componentDidUpdate() { + const { claim, resolveUri, uri } = this.props; + if (!claim && uri !== this.state.url) { + this.setState({ url: uri }, () => resolveUri(uri)); + } + } + defaultOnPress = () => { const { autoplay, claim, featuredResult, navigation, uri, shortUrl } = this.props; diff --git a/src/component/uriBar/view.js b/src/component/uriBar/view.js index 1097ec7..8a2b605 100644 --- a/src/component/uriBar/view.js +++ b/src/component/uriBar/view.js @@ -2,7 +2,7 @@ import React from 'react'; import { SEARCH_TYPES, isNameValid, isURIValid, normalizeURI } from 'lbry-redux'; import { FlatList, Keyboard, Text, TextInput, TouchableOpacity, View } from 'react-native'; -import { navigateToUri } from 'utils/helper'; +import { navigateToUri, transformUrl } from 'utils/helper'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import UriBarItem from './internal/uri-bar-item'; import Icon from 'react-native-vector-icons/FontAwesome5'; @@ -109,12 +109,19 @@ class UriBar extends React.PureComponent { handleSubmitEditing = () => { const { navigation, onSearchSubmitted, updateSearchQuery } = this.props; if (this.state.inputText) { - let inputText = this.state.inputText; - if (inputText.startsWith('lbry://') && isURIValid(inputText)) { + let inputText = this.state.inputText, + inputTextIsUrl = false; + if (inputText.startsWith('lbry://')) { + const transformedUrl = transformUrl(inputText); // if it's a URI (lbry://...), open the file page - const uri = normalizeURI(inputText); - navigateToUri(navigation, uri); - } else { + if (transformedUrl && isURIValid(transformedUrl)) { + inputTextIsUrl = true; + navigateToUri(navigation, transformedUrl); + } + } + + // couldn't parse the inputText as a URL for some reason, so do a search instead + if (!inputTextIsUrl) { updateSearchQuery(inputText); // Not a URI, default to a search request if (onSearchSubmitted) { diff --git a/src/page/firstRun/index.js b/src/page/firstRun/index.js index 35ce654..1596cb3 100644 --- a/src/page/firstRun/index.js +++ b/src/page/firstRun/index.js @@ -46,7 +46,7 @@ const perform = dispatch => ({ syncApply: (hash, data, password) => dispatch(doSyncApply(hash, data, password)), getSync: password => dispatch(doGetSync(password)), checkSync: () => dispatch(doCheckSync()), - setDefaultAccount: () => dispatch(doSetDefaultAccount()), + setDefaultAccount: (success, failure) => dispatch(doSetDefaultAccount(success, failure)), notify: data => dispatch(doToast(data)), resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)), }); diff --git a/src/page/firstRun/view.js b/src/page/firstRun/view.js index 32756ca..b2995f4 100644 --- a/src/page/firstRun/view.js +++ b/src/page/firstRun/view.js @@ -33,7 +33,7 @@ class FirstRunScreen extends React.PureComponent { isEmailVerified: false, skipAccountConfirmed: false, showBottomContainer: false, - walletPassword: null, + walletPassword: '', syncApplyStarted: false, }; @@ -86,12 +86,25 @@ class FirstRunScreen extends React.PureComponent { this.setState({ showBottomContainer: true }); } else { // password successfully verified - if (NativeModules.UtilityModule) { - NativeModules.UtilityModule.setSecureValue(Constants.KEY_FIRST_RUN_PASSWORD, this.state.walletPassword); - } - setDefaultAccount(); - setClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED, true); - this.closeFinalPage(); + NativeModules.UtilityModule.setSecureValue(Constants.KEY_FIRST_RUN_PASSWORD, this.state.walletPassword); + setDefaultAccount( + () => { + setClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED, true); + + // unlock the wallet + Lbry.account_unlock({ password: this.state.walletPassword ? this.state.walletPassword : '' }) + .then(() => this.closeFinalPage()) + .catch(err => + notify({ message: 'The wallet could not be unlocked at this time. Please restart the app.' }) + ); + }, + err => { + notify({ + message: + 'The account restore operation could not be completed successfully. Please restart the app and try again.', + }); + } + ); } } @@ -253,7 +266,7 @@ class FirstRunScreen extends React.PureComponent { }; onWalletPasswordChanged = password => { - this.setState({ walletPassword: password }); + this.setState({ walletPassword: password !== null ? password : '' }); }; onWalletViewLayout = () => { diff --git a/src/page/splash/view.js b/src/page/splash/view.js index 90f1ed3..567cfec 100644 --- a/src/page/splash/view.js +++ b/src/page/splash/view.js @@ -3,7 +3,7 @@ import { Lbry } from 'lbry-redux'; import { ActivityIndicator, Linking, NativeModules, Platform, Text, View } from 'react-native'; import { NavigationActions, StackActions } from 'react-navigation'; import { decode as atob } from 'base-64'; -import { navigateToUri } from 'utils/helper'; +import { navigateToUri, transformUrl } from 'utils/helper'; import moment from 'moment'; import AsyncStorage from '@react-native-community/async-storage'; import Button from 'component/button'; @@ -81,7 +81,7 @@ class SplashScreen extends React.PureComponent { }); } } else { - navigateToUri(navigation, launchUrl); + navigateToUri(navigation, transformUrl(launchUrl)); } } }; @@ -130,7 +130,7 @@ class SplashScreen extends React.PureComponent { if (user && user.id && user.has_verified_email) { // user already authenticated NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => { - if (walletPassword && walletPassword.trim().length > 0) { + if (walletPassword) { getSync(walletPassword); } this.navigateToMain(); @@ -166,14 +166,14 @@ class SplashScreen extends React.PureComponent { // For now, automatically unlock the wallet if a password is set so that downloads work NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(password => { - if (password && password.trim().length > 0) { + if (password) { this.setState({ message: 'Unlocking account', details: 'Decrypting wallet', }); // unlock the wallet and then finish the splash screen - Lbry.account_unlock({ password }) + Lbry.account_unlock({ password: password || '' }) .then(() => { this.setState({ message: testingNetwork, diff --git a/src/page/verification/index.js b/src/page/verification/index.js index c1d71bd..30dca55 100644 --- a/src/page/verification/index.js +++ b/src/page/verification/index.js @@ -29,7 +29,7 @@ import { } from 'lbryinc'; import { doSetClientSetting } from 'redux/actions/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings'; -import Constants from 'constants'; +import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Verification from './view'; const select = state => ({ @@ -54,13 +54,13 @@ const select = state => ({ const perform = dispatch => ({ addUserEmail: email => dispatch(doUserEmailNew(email)), - addUserPhone: (phone, country_code) => dispatch(doUserPhoneNew(phone, country_code)), + addUserPhone: (phone, countryCode) => dispatch(doUserPhoneNew(phone, countryCode)), getSync: password => dispatch(doGetSync(password)), checkSync: () => dispatch(doCheckSync()), verifyPhone: verificationCode => dispatch(doUserPhoneVerify(verificationCode)), notify: data => dispatch(doToast(data)), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), - setDefaultAccount: () => dispatch(doSetDefaultAccount()), + setDefaultAccount: (success, failure) => dispatch(doSetDefaultAccount(success, failure)), setEmailToVerify: email => dispatch(doUserEmailToVerify(email)), syncApply: (hash, data, password) => dispatch(doSyncApply(hash, data, password)), resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)), diff --git a/src/page/verification/internal/sync-verify-page.js b/src/page/verification/internal/sync-verify-page.js index c53653b..6862733 100644 --- a/src/page/verification/internal/sync-verify-page.js +++ b/src/page/verification/internal/sync-verify-page.js @@ -5,7 +5,7 @@ import { BarPasswordStrengthDisplay } from 'react-native-password-strength-meter import Button from 'component/button'; import Link from 'component/link'; import Colors from 'styles/colors'; -import Constants from 'constants'; +import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import firstRunStyle from 'styles/firstRun'; import Icon from 'react-native-vector-icons/FontAwesome5'; import rewardStyle from 'styles/reward'; @@ -62,11 +62,29 @@ class SyncVerifyPage extends React.PureComponent { } else { // password successfully verified if (NativeModules.UtilityModule) { - NativeModules.UtilityModule.setSecureValue(Constants.KEY_FIRST_RUN_PASSWORD, this.state.password); + NativeModules.UtilityModule.setSecureValue( + Constants.KEY_FIRST_RUN_PASSWORD, + this.state.password ? this.state.password : '' + ); } - setDefaultAccount(); - setClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED, true); - navigation.goBack(); + setDefaultAccount( + () => { + setClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED, true); + + // unlock the wallet + Lbry.account_unlock({ password: this.state.password ? this.state.password : '' }) + .then(() => navigation.goBack()) + .catch(err => + notify({ message: 'The wallet could not be unlocked at this time. Please restart the app.' }) + ); + }, + err => { + notify({ + message: + 'The account restore operation could not be completed successfully. Please restart the app and try again.', + }); + } + ); } } } diff --git a/src/page/wallet/view.js b/src/page/wallet/view.js index 20d40c1..df6c5f5 100644 --- a/src/page/wallet/view.js +++ b/src/page/wallet/view.js @@ -47,7 +47,7 @@ class WalletPage extends React.PureComponent { const { deviceWalletSynced, getSync, user } = this.props; if (deviceWalletSynced && user && user.has_verified_email) { NativeModules.UtilityModule.getSecureValue(Constants.KEY_FIRST_RUN_PASSWORD).then(walletPassword => { - if (walletPassword && walletPassword.trim().length > 0) { + if (walletPassword) { getSync(walletPassword); } }); diff --git a/src/utils/helper.js b/src/utils/helper.js index 6bc6d50..7152c40 100644 --- a/src/utils/helper.js +++ b/src/utils/helper.js @@ -1,5 +1,5 @@ import { NavigationActions, StackActions } from 'react-navigation'; -import { buildURI, isURIValid } from 'lbry-redux'; +import { buildURI, isURIValid, normalizeURI } from 'lbry-redux'; import { doPopDrawerStack, doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import Constants, { DrawerRoutes } from 'constants'; // eslint-disable-line node/no-deprecated-api @@ -246,6 +246,12 @@ export function getOrderBy(item) { return orderBy; } +// replace occurrences of ':' with '#' in a url (entered in the URI bar) +export function transformUrl(url) { + const start = 'lbry://'.length; + return normalizeURI(url.substring(start).replace(/:/g, '#')); +} + // i18n placeholder until we find a good react-native i18n module export function __(str) { return str;