Skip to content

Commit

Permalink
Improvement/browser refactor (#1829)
Browse files Browse the repository at this point in the history
* First implementation working

* finish use effect

* Update webview

* Fix watch asset

* Improve url modal

* Fix replace and remove unused variable

* Comments

* Fix approved hosts & webview inject

* Fix effects and callbacks

* Update test and remove unecessary comments

* Fix redirections

* Fix more redirects

* Fix redirections and add icon

* Fix address bar icon

* Move some variables from state to component and native webview fix

* remove logs

* Update tabs and fix patch package error

* Improve tabs initial performance

* Fix www replace

* move render phishing up

* update test

* fixing phishing with timeout

* Update test

* Tidy up getFavicon

* ishidden

* snap

Co-authored-by: rickycodes <ricky.miller@gmail.com>
Co-authored-by: Esteban Mino <efmino@uc.cl>
  • Loading branch information
3 people authored Sep 29, 2020
1 parent 82f8f77 commit ca7f653
Show file tree
Hide file tree
Showing 17 changed files with 1,353 additions and 4,786 deletions.
1 change: 0 additions & 1 deletion android/app/src/main/java/io/metamask/MainApplication.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.metamask;

import com.facebook.react.ReactApplication;
import com.reactnativecommunity.webviewforked.RNCWebViewForkedPackage;
import com.cmcewen.blurview.BlurViewPackage;
import android.content.Context;
import com.facebook.react.PackageList;
Expand Down
2 changes: 0 additions & 2 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
rootProject.name = 'MetaMask'
include ':react-native-webview-forked'
project(':react-native-webview-forked').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview-forked/android')
include ':@react-native-community_blur'
project(':@react-native-community_blur').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/blur/android')
include ':lottie-react-native'
Expand Down
14 changes: 11 additions & 3 deletions app/components/UI/Navbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -469,15 +469,16 @@ export function getBrowserViewNavbarOptions(navigation) {

const isHomepage = url => getHost(url) === getHost(HOMEPAGE_URL);
const error = navigation.getParam('error', '');
const icon = navigation.getParam('icon', null);

if (url && !isHomepage(url)) {
isHttps = url && url.toLowerCase().substr(0, 6) === 'https:';
const urlObj = new URL(url);
hostname = urlObj.hostname.toLowerCase().replace(/^www./, '');
hostname = urlObj.hostname.toLowerCase().replace(/^www\./, '');
if (isGatewayUrl(urlObj) && url.search(`${AppConstants.IPFS_OVERRIDE_PARAM}=false`) === -1) {
const ensUrl = navigation.getParam('currentEnsName', '');
if (ensUrl) {
hostname = ensUrl.toLowerCase().replace(/^www./, '');
hostname = ensUrl.toLowerCase().replace(/^www\./, '');
}
}
} else {
Expand All @@ -501,7 +502,14 @@ export function getBrowserViewNavbarOptions(navigation) {
</TouchableOpacity>
),
headerTitle: (
<NavbarBrowserTitle error={!!error} navigation={navigation} url={url} hostname={hostname} https={isHttps} />
<NavbarBrowserTitle
error={!!error}
icon={url && !isHomepage(url) ? icon : null}
navigation={navigation}
url={url}
hostname={hostname}
https={isHttps}
/>
),
headerRight: (
<View style={styles.browserRightButton}>
Expand Down
28 changes: 17 additions & 11 deletions app/components/UI/NavbarBrowserTitle/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { TouchableOpacity, View, StyleSheet, Text } from 'react-native';
import { TouchableOpacity, View, StyleSheet, Text, Image } from 'react-native';
import { colors, fontStyles } from '../../../styles/common';
import Networks from '../../../util/networks';
import Icon from 'react-native-vector-icons/FontAwesome';
Expand Down Expand Up @@ -37,7 +37,7 @@ const styles = StyleSheet.create({
},
lockIcon: {
marginTop: 2,
marginRight: 10
marginLeft: 10
},
currentUrl: {
...fontStyles.normal,
Expand All @@ -46,6 +46,11 @@ const styles = StyleSheet.create({
},
currentUrlAndroid: {
maxWidth: '60%'
},
siteIcon: {
width: 16,
height: 16,
marginRight: 4
}
});

Expand Down Expand Up @@ -78,15 +83,16 @@ class NavbarBrowserTitle extends PureComponent {
/**
* Boolean that specifies if there is an error
*/
error: PropTypes.bool
error: PropTypes.bool,
/**
* Website icon
*/
icon: PropTypes.string
};

onTitlePress = () => {
this.props.navigation.setParams({
...this.props.navigation.state.params,
url: this.props.url,
showUrlModal: true
});
const showUrlModal = this.props.navigation.getParam('showUrlModal', () => null);
showUrlModal({ urlInput: this.props.url });
};

getNetworkName(network) {
Expand All @@ -107,21 +113,21 @@ class NavbarBrowserTitle extends PureComponent {
}

render = () => {
const { https, network, hostname, error } = this.props;
const { https, network, hostname, error, icon } = this.props;
const color = (Networks[network.provider.type] && Networks[network.provider.type].color) || null;
const name = this.getNetworkName(network);

return (
<TouchableOpacity onPress={this.onTitlePress} style={styles.wrapper}>
<View style={styles.currentUrlWrapper}>
{https && !error ? <Icon name="lock" size={14} style={styles.lockIcon} /> : null}
{icon && <Image style={styles.siteIcon} source={{ uri: icon }} />}
<Text
numberOfLines={1}
ellipsizeMode={'head'}
style={[styles.currentUrl, Device.isAndroid() ? styles.currentUrlAndroid : {}]}
>
{hostname}
</Text>
{https && !error ? <Icon name="lock" size={14} style={styles.lockIcon} /> : null}
</View>
<View style={styles.network}>
<View style={[styles.networkIcon, { backgroundColor: color || colors.red }]} />
Expand Down
3 changes: 2 additions & 1 deletion app/components/UI/TransactionHeader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class TransactionHeader extends PureComponent {

render() {
const {
currentPageInformation: { url, currentEnsName },
currentPageInformation: { url, currentEnsName, icon },
networkType
} = this.props;
const title = getHost(currentEnsName || url);
Expand All @@ -118,6 +118,7 @@ class TransactionHeader extends PureComponent {
viewStyle={styles.assetLogo}
title={title}
url={currentEnsName || url}
icon={icon}
/>
<View style={styles.domanUrlContainer}>
{this.renderSecureIcon()}
Expand Down
9 changes: 8 additions & 1 deletion app/components/UI/UrlAutocomplete/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,14 @@ class UrlAutocomplete extends PureComponent {
};

render() {
if (!this.props.input || this.props.input.length < 2) return <View style={styles.wrapper} />;
if (!this.props.input || this.props.input.length < 2)
return (
<View style={styles.wrapper}>
<TouchableWithoutFeedback style={styles.bg} onPress={this.props.onDismiss}>
<View style={styles.bg} />
</TouchableWithoutFeedback>
</View>
);
if (this.state.results.length === 0) {
return (
<View style={styles.wrapper}>
Expand Down
10 changes: 7 additions & 3 deletions app/components/UI/WebsiteIcon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ export default class WebsiteIcon extends PureComponent {
* Flag that determines if the background
* should be transaparent or not
*/
transparent: PropTypes.bool
transparent: PropTypes.bool,
/**
* Icon image to use, this substitutes getting the icon from the url
*/
icon: PropTypes.string
};

state = {
Expand All @@ -76,8 +80,8 @@ export default class WebsiteIcon extends PureComponent {

render = () => {
const { renderIconUrlError } = this.state;
const { viewStyle, style, textStyle, transparent, url } = this.props;
const apiLogoUrl = { uri: this.getIconUrl(url) };
const { viewStyle, style, textStyle, transparent, url, icon } = this.props;
const apiLogoUrl = { uri: icon || this.getIconUrl(url) };
const title = typeof this.props.title === 'string' ? this.props.title.substr(0, 1) : getHost(url).substr(0, 1);

if (renderIconUrlError && title) {
Expand Down
68 changes: 15 additions & 53 deletions app/components/Views/Browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Device from '../../../util/Device';
import BrowserTab from '../BrowserTab';
import AppConstants from '../../../core/AppConstants';
import { baseStyles } from '../../../styles/common';
import { getVersion } from 'react-native-device-info';

const margin = 16;
const THUMB_WIDTH = Dimensions.get('window').width / 2 - margin * 2;
Expand Down Expand Up @@ -57,18 +56,14 @@ class Browser extends PureComponent {
activeTab: PropTypes.number
};
static navigationOptions = ({ navigation }) => getBrowserViewNavbarOptions(navigation);
tabs = {};

constructor(props) {
super(props);

if (!props.tabs.length) {
this.newTab();
}

this.createBrowserTabs(props.tabs);
}

componentDidMount() {
const activeTab = this.props.tabs.find(tab => tab.id === this.props.activeTab);
if (activeTab) {
Expand All @@ -78,38 +73,7 @@ class Browser extends PureComponent {
}
}

async createBrowserTabs(tabs) {
const APP_VERSION = await getVersion();

// Delete closed tabs
Object.keys(this.tabs).forEach(tabID => {
const existingTab = tabs.find(tab => tab.id === tabID);
if (!existingTab) {
delete this.tabs[tabID];
}
});

// Add new tabs
tabs.forEach(tab => {
if (!this.tabs[tab.id]) {
this.tabs[tab.id] = React.createElement(BrowserTab, {
id: tab.id,
key: `tab_${tab.id}`,
initialUrl: tab.url || AppConstants.HOMEPAGE_URL,
updateTabInfo: (url, tabID) => this.updateTabInfo(url, tabID),
showTabs: () => this.showTabs(),
newTab: url => this.newTab(url),
app_version: APP_VERSION
});
}
});
}

componentDidUpdate(prevProps) {
if (this.props.tabs.length !== Object.keys(this.tabs).length) {
this.createBrowserTabs(this.props.tabs);
}

const prevNavigation = prevProps.navigation;
const { navigation } = this.props;

Expand Down Expand Up @@ -238,19 +202,10 @@ class Browser extends PureComponent {
return null;
}

updateTabInfo = (url, tabID) => {
if (this.snapshotTimer) {
clearTimeout(this.snapshotTimer);
}
this.snapshotTimer = setTimeout(() => {
const showTabs = this.props.navigation.getParam('showTabs', false);
if (showTabs) {
this.updateTabInfo(url, tabID);
return false;
}
this.takeScreenshot(url, tabID);
}, 500);
};
updateTabInfo = (url, tabID) =>
this.props.updateTab(tabID, {
url
});

takeScreenshot = (url, tabID) =>
new Promise((resolve, reject) => {
Expand All @@ -276,10 +231,17 @@ class Browser extends PureComponent {
);
});

renderBrowserTabs() {
const tabs = Object.keys(this.tabs).map(tabID => this.tabs[tabID]);
return tabs;
}
renderBrowserTabs = () =>
this.props.tabs.map(tab => (
<BrowserTab
id={tab.id}
key={`tab_${tab.id}`}
initialUrl={tab.url || AppConstants.HOMEPAGE_URL}
updateTabInfo={this.updateTabInfo}
showTabs={this.showTabs}
newTab={this.newTab}
/>
));

render() {
return (
Expand Down
Loading

0 comments on commit ca7f653

Please sign in to comment.