more navigation tweaks (#277)

* upgrade react-navigation module, implement associated code updates
* call resolveUri for a file list item if the claim is not yet resolved
This commit is contained in:
Akinwale Ariwodola 2018-09-02 08:12:21 +01:00 committed by GitHub
parent 77e471d671
commit 8257d7b41d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 249 additions and 132 deletions

120
app/package-lock.json generated
View file

@ -2440,6 +2440,15 @@
"object-assign": "^4.1.1" "object-assign": "^4.1.1"
} }
}, },
"create-react-context": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
"integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
"requires": {
"fbjs": "^0.8.0",
"gud": "^1.0.0"
}
},
"cross-spawn": { "cross-spawn": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@ -3432,6 +3441,11 @@
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE="
}, },
"gud": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
},
"has-ansi": { "has-ansi": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
@ -3969,12 +3983,13 @@
"version": "github:lbryio/lbryinc#678c5098e2099dd1560b2fefa2795f38ca3ce07b", "version": "github:lbryio/lbryinc#678c5098e2099dd1560b2fefa2795f38ca3ce07b",
"from": "github:lbryio/lbryinc", "from": "github:lbryio/lbryinc",
"requires": { "requires": {
"lbry-redux": "github:lbryio/lbry-redux#421321a78397251589e5a890f4caa95e79975e2b",
"reselect": "^3.0.0" "reselect": "^3.0.0"
}, },
"dependencies": { "dependencies": {
"lbry-redux": { "lbry-redux": {
"version": "github:lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc", "version": "github:lbryio/lbry-redux#421321a78397251589e5a890f4caa95e79975e2b",
"from": "github:lbryio/lbry-redux#31f7afa8a37f5741dac01fc1ecdf153f3bed95dc", "from": "github:lbryio/lbry-redux",
"requires": { "requires": {
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0" "reselect": "^3.0.0"
@ -5020,6 +5035,15 @@
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
}, },
"query-string": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz",
"integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==",
"requires": {
"decode-uri-component": "^0.2.0",
"strict-uri-encode": "^2.0.0"
}
},
"randomatic": { "randomatic": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz",
@ -5240,16 +5264,17 @@
} }
}, },
"react-native-safe-area-view": { "react-native-safe-area-view": {
"version": "0.7.0", "version": "0.9.0",
"resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.7.0.tgz", "resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.9.0.tgz",
"integrity": "sha512-SjLdW/Th0WVMhyngH4O6yC21S+O4U4AAG3QxBr7fZ2ftgjXSpKbDHAhEpxBdFwei6HsnsC2h9oYMtPpaW9nfGg==", "integrity": "sha512-y792ScHMzvgwquxL869S9CER4dwiFu/TuCiXdy0xBtygmScMK4eWonnUT65LvOrsSSdr8o6XEK1mbI51h6ozvQ==",
"requires": { "requires": {
"hoist-non-react-statics": "^2.3.1" "hoist-non-react-statics": "^2.3.1"
} }
}, },
"react-native-tab-view": { "react-native-tab-view": {
"version": "github:react-navigation/react-native-tab-view#36ebd834d78b841fc19778c966465d02fd1213bb", "version": "0.0.77",
"from": "react-native-tab-view@github:react-navigation/react-native-tab-view#36ebd834d78b841fc19778c966465d02fd1213bb", "resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-0.0.77.tgz",
"integrity": "sha512-9vjD4Ly1Zlum1Y4g23ODpi/F3gYIUIsKWrsZO/Oh5cuX1eiB1DRVn11nY1z+j/hsQfhfyW6nDlmySyDvYQvYCA==",
"requires": { "requires": {
"prop-types": "^15.6.0" "prop-types": "^15.6.0"
} }
@ -5302,28 +5327,82 @@
} }
}, },
"react-navigation": { "react-navigation": {
"version": "1.5.12", "version": "2.12.1",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-1.5.12.tgz", "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.12.1.tgz",
"integrity": "sha512-+i0ymFHokQxjv0/0knBUtxC1zuyvLgbDVPFU7ScKxT25SGVh2exuRjYwXImF234/qtYMskfY7bfhEjGLcXPySQ==", "integrity": "sha512-C+do+STPvvd/5LbaDhrZyf1P8tCeffttdlHyIRe1NgGg8Nj93FZHWOThi2hnmEZ75kXsS/JGxox4DDPqYVAxeQ==",
"requires": { "requires": {
"clamp": "^1.0.1", "clamp": "^1.0.1",
"create-react-context": "^0.2.1",
"hoist-non-react-statics": "^2.2.0", "hoist-non-react-statics": "^2.2.0",
"path-to-regexp": "^1.7.0", "path-to-regexp": "^1.7.0",
"prop-types": "^15.5.10", "query-string": "^6.1.0",
"react-lifecycles-compat": "^3.0.2", "react-lifecycles-compat": "^3",
"react-native-drawer-layout-polyfill": "^1.3.2", "react-native-safe-area-view": "^0.9.0",
"react-native-safe-area-view": "^0.7.0", "react-navigation-deprecated-tab-navigator": "1.3.0",
"react-native-tab-view": "github:react-navigation/react-native-tab-view#36ebd834d78b841fc19778c966465d02fd1213bb" "react-navigation-drawer": "0.5.0",
"react-navigation-stack": "0.2.3",
"react-navigation-tabs": "0.6.0"
}
},
"react-navigation-deprecated-tab-navigator": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-navigation-deprecated-tab-navigator/-/react-navigation-deprecated-tab-navigator-1.3.0.tgz",
"integrity": "sha512-Cm+qYOPFWbvvcuv0YYX0ioYwLGgw7XAqdhAfpo3sIr3trxRW8871ePmfFOPezjQtz4v6ItjZt6LPgtBAVZoroQ==",
"requires": {
"react-native-tab-view": "^0.0.77"
}
},
"react-navigation-drawer": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/react-navigation-drawer/-/react-navigation-drawer-0.5.0.tgz",
"integrity": "sha512-F1y593uC6pqBMGH+Omz75oNODEbxB/s0EGO8QtYwu1NmOOEUuuLA+c14zm+pgMsI4HlDabiHxPkWqsgGz25xVQ==",
"requires": {
"react-native-drawer-layout-polyfill": "^1.3.2"
} }
}, },
"react-navigation-redux-helpers": { "react-navigation-redux-helpers": {
"version": "1.0.7", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/react-navigation-redux-helpers/-/react-navigation-redux-helpers-1.0.7.tgz", "resolved": "https://registry.npmjs.org/react-navigation-redux-helpers/-/react-navigation-redux-helpers-2.0.5.tgz",
"integrity": "sha512-JUD3ycYS0EZLIzuaZVQ4/c3KMrEztPLqXzVV/qifeWQQLq01BmPnIuR7VWluSfZ98cgGlX9hY5r72wwgvvrfjw==", "integrity": "sha512-oxDpPqmXdzUJJ32ef8NY6Cu9XDJNO4DU91p0+ZgleEfaZwec9t2ua6sKwQyOfdWQPDwbJAxiXfZIAe3ao5MG6Q==",
"requires": { "requires": {
"invariant": "^2.2.2" "invariant": "^2.2.2"
} }
}, },
"react-navigation-stack": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-0.2.3.tgz",
"integrity": "sha512-xjVqiI/ztcQt45jxQ3vfO8Lr+9bVq+0J/lRhMdZCvCDwiyOVuB64wx7qPNJW16pnBBLiI5h6H7uhWE3rAT0r/w=="
},
"react-navigation-tabs": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/react-navigation-tabs/-/react-navigation-tabs-0.6.0.tgz",
"integrity": "sha512-Ax1rujJ51R1Jrz7b5bHUAIgsYC1VrFws+d3hxlPy5dXG84iJdV5dnDFRvdQMDDfDZc+NDx2a223lAYsc3p2+XA==",
"requires": {
"hoist-non-react-statics": "^2.5.0",
"prop-types": "^15.6.1",
"react-lifecycles-compat": "^3.0.4",
"react-native-safe-area-view": "^0.7.0",
"react-native-tab-view": "^1.0.0"
},
"dependencies": {
"react-native-safe-area-view": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.7.0.tgz",
"integrity": "sha512-SjLdW/Th0WVMhyngH4O6yC21S+O4U4AAG3QxBr7fZ2ftgjXSpKbDHAhEpxBdFwei6HsnsC2h9oYMtPpaW9nfGg==",
"requires": {
"hoist-non-react-statics": "^2.3.1"
}
},
"react-native-tab-view": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-1.0.2.tgz",
"integrity": "sha512-x8I43V1X7/AyMnIwnqJGMU54LqQRlV6vJ9irbls9asA/axdHIdxagPIV6Jx1ttFe/bPKhFwXL+lRYdYxGyUlWg==",
"requires": {
"prop-types": "^15.6.1"
}
}
}
},
"react-proxy": { "react-proxy": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz", "resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz",
@ -6339,6 +6418,11 @@
"resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz",
"integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ="
}, },
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
},
"string-width": { "string-width": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",

View file

@ -17,8 +17,8 @@
"react-native-image-zoom-viewer": "^2.2.5", "react-native-image-zoom-viewer": "^2.2.5",
"react-native-vector-icons": "^5.0.0", "react-native-vector-icons": "^5.0.0",
"react-native-video": "lbryio/react-native-video#exoplayer-lbry-android", "react-native-video": "lbryio/react-native-video#exoplayer-lbry-android",
"react-navigation": "^1.5.12", "react-navigation": "^2.12.1",
"react-navigation-redux-helpers": "^1.0.1", "react-navigation-redux-helpers": "^2.0.5",
"react-redux": "^5.0.3", "react-redux": "^5.0.3",
"redux": "^3.6.0", "redux": "^3.6.0",
"redux-logger": "3.0.6", "redux-logger": "3.0.6",

View file

@ -13,13 +13,16 @@ import TransactionHistoryPage from '../page/transactionHistory';
import WalletPage from '../page/wallet'; import WalletPage from '../page/wallet';
import SearchInput from '../component/searchInput'; import SearchInput from '../component/searchInput';
import { import {
addNavigationHelpers, createDrawerNavigator,
DrawerNavigator, createStackNavigator,
StackNavigator,
NavigationActions NavigationActions
} from 'react-navigation'; } from 'react-navigation';
import {
addListener,
reduxifyNavigator,
createReactNavigationReduxMiddleware,
} from 'react-navigation-redux-helpers';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { addListener } from '../utils/redux';
import { import {
AppState, AppState,
AsyncStorage, AsyncStorage,
@ -41,6 +44,7 @@ import {
} from 'lbryinc'; } from 'lbryinc';
import { makeSelectClientSetting } from '../redux/selectors/settings'; import { makeSelectClientSetting } from '../redux/selectors/settings';
import { decode as atob } from 'base-64'; import { decode as atob } from 'base-64';
import { dispatchNavigateToUri } from '../utils/helper';
import Colors from '../styles/colors'; import Colors from '../styles/colors';
import Constants from '../constants'; import Constants from '../constants';
import Icon from 'react-native-vector-icons/FontAwesome5'; import Icon from 'react-native-vector-icons/FontAwesome5';
@ -56,7 +60,7 @@ const menuNavigationButton = (navigation) => <NavigationButton
iconStyle={discoverStyle.drawerHamburger} iconStyle={discoverStyle.drawerHamburger}
onPress={() => navigation.navigate('DrawerOpen')} /> onPress={() => navigation.navigate('DrawerOpen')} />
const discoverStack = StackNavigator({ const discoverStack = createStackNavigator({
Discover: { Discover: {
screen: DiscoverPage, screen: DiscoverPage,
navigationOptions: ({ navigation }) => ({ navigationOptions: ({ navigation }) => ({
@ -78,10 +82,10 @@ const discoverStack = StackNavigator({
}) })
} }
}, { }, {
headerMode: 'screen', headerMode: 'screen'
}); });
const trendingStack = StackNavigator({ const trendingStack = createStackNavigator({
Trending: { Trending: {
screen: TrendingPage, screen: TrendingPage,
navigationOptions: ({ navigation }) => ({ navigationOptions: ({ navigation }) => ({
@ -91,7 +95,7 @@ const trendingStack = StackNavigator({
} }
}); });
const myLbryStack = StackNavigator({ const myLbryStack = createStackNavigator({
Downloads: { Downloads: {
screen: DownloadsPage, screen: DownloadsPage,
navigationOptions: ({ navigation }) => ({ navigationOptions: ({ navigation }) => ({
@ -101,7 +105,7 @@ const myLbryStack = StackNavigator({
} }
}); });
const rewardsStack = StackNavigator({ const rewardsStack = createStackNavigator({
Rewards: { Rewards: {
screen: RewardsPage, screen: RewardsPage,
navigationOptions: ({ navigation }) => ({ navigationOptions: ({ navigation }) => ({
@ -111,7 +115,7 @@ const rewardsStack = StackNavigator({
} }
}); });
const walletStack = StackNavigator({ const walletStack = createStackNavigator({
Wallet: { Wallet: {
screen: WalletPage, screen: WalletPage,
navigationOptions: ({ navigation }) => ({ navigationOptions: ({ navigation }) => ({
@ -130,21 +134,21 @@ const walletStack = StackNavigator({
headerMode: 'screen' headerMode: 'screen'
}); });
const drawer = DrawerNavigator({ const drawer = createDrawerNavigator({
DiscoverStack: { screen: discoverStack, navigationOptions: { DiscoverStack: { screen: discoverStack, navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="compass" size={20} style={{ color: tintColor }} /> title: 'Discover', drawerIcon: ({ tintColor }) => <Icon name="compass" size={20} style={{ color: tintColor }} />
}}, }},
TrendingStack: { screen: trendingStack, navigationOptions: { TrendingStack: { screen: trendingStack, navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="fire" size={20} style={{ color: tintColor }} /> title: 'Trending', drawerIcon: ({ tintColor }) => <Icon name="fire" size={20} style={{ color: tintColor }} />
}}, }},
MyLBRYStack: { screen: myLbryStack, navigationOptions: { MyLBRYStack: { screen: myLbryStack, navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="folder" size={20} style={{ color: tintColor }} /> title: 'My LBRY', drawerIcon: ({ tintColor }) => <Icon name="folder" size={20} style={{ color: tintColor }} />
}}, }},
Rewards: { screen: rewardsStack, navigationOptions: { Rewards: { screen: rewardsStack, navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="trophy" size={20} style={{ color: tintColor }} /> drawerIcon: ({ tintColor }) => <Icon name="trophy" size={20} style={{ color: tintColor }} />
}}, }},
WalletStack: { screen: walletStack, navigationOptions: { WalletStack: { screen: walletStack, navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="wallet" size={20} style={{ color: tintColor }} /> title: 'Wallet', drawerIcon: ({ tintColor }) => <Icon name="wallet" size={20} style={{ color: tintColor }} />
}}, }},
Settings: { screen: SettingsPage, navigationOptions: { Settings: { screen: SettingsPage, navigationOptions: {
drawerLockMode: 'locked-closed', drawerLockMode: 'locked-closed',
@ -162,7 +166,7 @@ const drawer = DrawerNavigator({
} }
}); });
export const AppNavigator = new StackNavigator({ export const AppNavigator = new createStackNavigator({
FirstRun: { FirstRun: {
screen: FirstRunScreen, screen: FirstRunScreen,
navigationOptions: { navigationOptions: {
@ -182,6 +186,16 @@ export const AppNavigator = new StackNavigator({
headerMode: 'none' headerMode: 'none'
}); });
export const reactNavigationMiddleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav,
);
const App = reduxifyNavigator(AppNavigator, "root");
const appMapStateToProps = (state) => ({
state: state.nav,
});
const ReduxAppNavigator = connect(appMapStateToProps)(App);
class AppWithNavigationState extends React.Component { class AppWithNavigationState extends React.Component {
static supportedDisplayTypes = ['toast']; static supportedDisplayTypes = ['toast'];
@ -198,17 +212,11 @@ class AppWithNavigationState extends React.Component {
const { dispatch, nav } = this.props; const { dispatch, nav } = this.props;
// There should be a better way to check this // There should be a better way to check this
if (nav.routes.length > 0) { if (nav.routes.length > 0) {
if (nav.routes[0].routes && nav.routes[0].routes.length > 0) {
const subRoutes = nav.routes[0].routes[0].routes;
const lastRoute = subRoutes[subRoutes.length - 1];
if (nav.routes[0].routes[0].index > 0 &&
['About', 'Settings'].indexOf(lastRoute.key) > -1) {
dispatch(NavigationActions.back());
return true;
}
}
if (nav.routes[0].routeName === 'Main') { if (nav.routes[0].routeName === 'Main') {
if (nav.routes[0].routes[0].routes[0].index > 0) { const mainRoute = nav.routes[0];
if (mainRoute.routes[0].index > 0 /* Discover stack index */ ||
mainRoute.routes[4].index > 0 /* Wallet stack index */ ||
mainRoute.index >= 5 /* Settings and About screens */) {
dispatch(NavigationActions.back()); dispatch(NavigationActions.back());
return true; return true;
} }
@ -313,7 +321,7 @@ class AppWithNavigationState extends React.Component {
} }
_handleUrl = (evt) => { _handleUrl = (evt) => {
const { dispatch } = this.props; const { dispatch, nav } = this.props;
if (evt.url) { if (evt.url) {
if (evt.url.startsWith('lbry://?verify=')) { if (evt.url.startsWith('lbry://?verify=')) {
this.setState({ emailVerifyDone: false }); this.setState({ emailVerifyDone: false });
@ -340,27 +348,13 @@ class AppWithNavigationState extends React.Component {
})); }));
} }
} else { } else {
const navigateAction = NavigationActions.navigate({ dispatchNavigateToUri(dispatch, nav, evt.url);
routeName: 'File',
key: evt.url,
params: { uri: evt.url }
});
dispatch(navigateAction);
} }
} }
} }
render() { render() {
const { dispatch, nav } = this.props; return <ReduxAppNavigator />;
return (
<AppNavigator
navigation={addNavigationHelpers({
dispatch,
state: nav,
addListener,
})}
/>
);
} }
} }
@ -373,7 +367,7 @@ const mapStateToProps = state => ({
emailVerifyPending: selectEmailVerifyIsPending(state), emailVerifyPending: selectEmailVerifyIsPending(state),
emailVerifyErrorMessage: selectEmailVerifyErrorMessage(state), emailVerifyErrorMessage: selectEmailVerifyErrorMessage(state),
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state), showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),
user: selectUser(state), user: selectUser(state)
}); });
export default connect(mapStateToProps)(AppWithNavigationState); export default connect(mapStateToProps)(AppWithNavigationState);

View file

@ -2,6 +2,7 @@ import React from 'react';
import { normalizeURI } from 'lbry-redux'; import { normalizeURI } from 'lbry-redux';
import { NavigationActions } from 'react-navigation'; import { NavigationActions } from 'react-navigation';
import { NativeModules, Text, View, TouchableOpacity } from 'react-native'; import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
import { navigateToUri } from '../../utils/helper';
import FileItemMedia from '../fileItemMedia'; import FileItemMedia from '../fileItemMedia';
import FilePrice from '../filePrice'; import FilePrice from '../filePrice';
import Link from '../link'; import Link from '../link';
@ -54,7 +55,7 @@ class FileItem extends React.PureComponent {
if (NativeModules.Mixpanel) { if (NativeModules.Mixpanel) {
NativeModules.Mixpanel.track('Discover Tap', { Uri: uri }); NativeModules.Mixpanel.track('Discover Tap', { Uri: uri });
} }
navigation.navigate({ routeName: 'File', key: uri, params: { uri } }); navigateToUri(navigation, uri);
} }
}> }>
<FileItemMedia title={title} <FileItemMedia title={title}
@ -68,7 +69,7 @@ class FileItem extends React.PureComponent {
{channelName && {channelName &&
<Link style={discoverStyle.channelName} text={channelName} onPress={() => { <Link style={discoverStyle.channelName} text={channelName} onPress={() => {
const channelUri = normalizeURI(channelName); const channelUri = normalizeURI(channelName);
navigation.navigate({ routeName: 'File', key: channelUri, params: { uri: channelUri }}); navigateToUri(navigation, channelUri);
}} />} }} />}
</TouchableOpacity> </TouchableOpacity>
{obscureNsfw && <NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />} {obscureNsfw && <NsfwOverlay onPress={() => navigation.navigate({ routeName: 'Settings', key: 'settingsPage' })} />}

View file

@ -37,7 +37,6 @@ class FileItemMedia extends React.PureComponent {
case "contain": case "contain":
return FastImage.resizeMode.contain; return FastImage.resizeMode.contain;
case "stretch": case "stretch":
console.log('using stretch resize mode...');
return FastImage.resizeMode.stretch; return FastImage.resizeMode.stretch;
case "center": case "center":
return FastImage.resizeMode.center; return FastImage.resizeMode.center;

View file

@ -8,6 +8,7 @@ import {
TouchableOpacity, TouchableOpacity,
View View
} from 'react-native'; } from 'react-native';
import { navigateToUri } from '../../utils/helper';
import Colors from '../../styles/colors'; import Colors from '../../styles/colors';
import FileItemMedia from '../fileItemMedia'; import FileItemMedia from '../fileItemMedia';
import Link from '../../component/link'; import Link from '../../component/link';
@ -52,6 +53,13 @@ class FileListItem extends React.PureComponent {
return Math.ceil((fileInfo.written_bytes / fileInfo.total_bytes) * 100); return Math.ceil((fileInfo.written_bytes / fileInfo.total_bytes) * 100);
} }
componentDidMount() {
const { claim, resolveUri, uri } = this.props;
if (!claim) {
resolveUri(uri);
}
}
render() { render() {
const { const {
claim, claim,
@ -97,7 +105,7 @@ class FileListItem extends React.PureComponent {
{!isResolving && channel && {!isResolving && channel &&
<Link style={fileListStyle.publisher} text={channel} onPress={() => { <Link style={fileListStyle.publisher} text={channel} onPress={() => {
const channelUri = normalizeURI(channel); const channelUri = normalizeURI(channel);
navigation.navigate({ routeName: 'File', key: channelUri, params: { uri: channelUri }}); navigateToUri(navigation, channelUri);
}} />} }} />}
{fileInfo && {fileInfo &&

View file

@ -17,7 +17,7 @@ class FloatingWalletBalance extends React.PureComponent<Props> {
return ( return (
<TouchableOpacity style={[floatingButtonStyle.container, floatingButtonStyle.bottomRight]} <TouchableOpacity style={[floatingButtonStyle.container, floatingButtonStyle.bottomRight]}
onPress={() => navigation && navigation.navigate({ routeName: 'Wallet' })}> onPress={() => navigation && navigation.navigate({ routeName: 'WalletStack' })}>
{isNaN(balance) && <ActivityIndicator size="small" color={Colors.White} />} {isNaN(balance) && <ActivityIndicator size="small" color={Colors.White} />}
<Text style={floatingButtonStyle.text}> <Text style={floatingButtonStyle.text}>
{(balance || balance === 0) && (formatCredits(balance, 2) + ' LBC')} {(balance || balance === 0) && (formatCredits(balance, 2) + ' LBC')}

View file

@ -6,6 +6,5 @@ import MediaPlayer from './view';
const select = state => ({ const select = state => ({
backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state), backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state),
}); });
const perform = dispatch => ({});
export default connect(select, perform)(MediaPlayer); export default connect(select, null)(MediaPlayer);

View file

@ -225,6 +225,11 @@ class MediaPlayer extends React.PureComponent {
} }
componentDidMount() { componentDidMount() {
const { assignPlayer } = this.props;
if (assignPlayer) {
assignPlayer(this);
}
this.setSeekerPosition(this.calculateSeekerPosition()); this.setSeekerPosition(this.calculateSeekerPosition());
DeviceEventEmitter.addListener('onBackgroundPlayPressed', this.play); DeviceEventEmitter.addListener('onBackgroundPlayPressed', this.play);
DeviceEventEmitter.addListener('onBackgroundPausePressed', this.pause); DeviceEventEmitter.addListener('onBackgroundPausePressed', this.pause);

View file

@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import { Text, View, Linking } from 'react-native'; import { Text, View, Linking } from 'react-native';
import { buildURI, formatCredits } from 'lbry-redux'; import { buildURI, formatCredits } from 'lbry-redux';
import { navigateToUri } from '../../../utils/helper';
import Link from '../../link'; import Link from '../../link';
import moment from 'moment'; import moment from 'moment';
import transactionListStyle from '../../../styles/transactionList'; import transactionListStyle from '../../../styles/transactionList';
@ -10,11 +11,11 @@ class TransactionListItem extends React.PureComponent {
capitalize(string: string) { capitalize(string: string) {
return string.charAt(0).toUpperCase() + string.slice(1); return string.charAt(0).toUpperCase() + string.slice(1);
} }
render() { render() {
const { transaction, navigation } = this.props; const { transaction, navigation } = this.props;
const { amount, claim_id: claimId, claim_name: name, date, fee, txid, type } = transaction; const { amount, claim_id: claimId, claim_name: name, date, fee, txid, type } = transaction;
return ( return (
<View style={transactionListStyle.listItem}> <View style={transactionListStyle.listItem}>
<View style={[transactionListStyle.row, transactionListStyle.topRow]}> <View style={[transactionListStyle.row, transactionListStyle.topRow]}>
@ -23,13 +24,9 @@ class TransactionListItem extends React.PureComponent {
{name && claimId && ( {name && claimId && (
<Link <Link
style={transactionListStyle.link} style={transactionListStyle.link}
onPress={() => navigation && navigation.navigate({ onPress={() => navigateToUri(navigation, buildURI({ claimName: name, claimId }))}
routeName: 'File',
key: evt.Url,
params: { uri: buildURI({ claimName: name, claimId }) }})
}
text={name} /> text={name} />
)} )}
</View> </View>
<View style={transactionListStyle.col}> <View style={transactionListStyle.col}>
<Text style={[transactionListStyle.amount, transactionListStyle.text]}>{formatCredits(amount, 8)}</Text> <Text style={[transactionListStyle.amount, transactionListStyle.text]}>{formatCredits(amount, 8)}</Text>
@ -47,7 +44,7 @@ class TransactionListItem extends React.PureComponent {
{date ? ( {date ? (
<Text style={transactionListStyle.smallText}>{moment(date).format('MMM D')}</Text> <Text style={transactionListStyle.smallText}>{moment(date).format('MMM D')}</Text>
) : ( ) : (
<Text style={transactionListStyle.smallText}>Pending</Text> <Text style={transactionListStyle.smallText}>Pending</Text>
)} )}
</View> </View>
</View> </View>

View file

@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import { SEARCH_TYPES, isNameValid, isURIValid, normalizeURI } from 'lbry-redux'; import { SEARCH_TYPES, isNameValid, isURIValid, normalizeURI } from 'lbry-redux';
import { FlatList, Keyboard, TextInput, View } from 'react-native'; import { FlatList, Keyboard, TextInput, View } from 'react-native';
import { navigateToUri } from '../../utils/helper';
import UriBarItem from './internal/uri-bar-item'; import UriBarItem from './internal/uri-bar-item';
import uriBarStyle from '../../styles/uriBar'; import uriBarStyle from '../../styles/uriBar';
@ -62,7 +63,7 @@ class UriBar extends React.PureComponent {
navigation.navigate({ routeName: 'Search', key: 'searchPage', params: { searchQuery: value }}); navigation.navigate({ routeName: 'Search', key: 'searchPage', params: { searchQuery: value }});
} else { } else {
const uri = normalizeURI(value); const uri = normalizeURI(value);
navigation.navigate({ routeName: 'File', key: uri, params: { uri }}); navigateToUri(navigation, uri);
} }
} }
@ -127,7 +128,7 @@ class UriBar extends React.PureComponent {
if (inputText.startsWith('lbry://') && isURIValid(inputText)) { if (inputText.startsWith('lbry://') && isURIValid(inputText)) {
// if it's a URI (lbry://...), open the file page // if it's a URI (lbry://...), open the file page
const uri = normalizeURI(inputText); const uri = normalizeURI(inputText);
navigation.navigate({ routeName: 'File', key: uri, params: { uri }}); navigateToUri(navigation, uri);
} else { } else {
// Not a URI, default to a search request // Not a URI, default to a search request
if (onSearchSubmitted) { if (onSearchSubmitted) {

View file

@ -20,11 +20,9 @@ import {
import { authReducer, rewardsReducer, userReducer } from 'lbryinc'; import { authReducer, rewardsReducer, userReducer } from 'lbryinc';
import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import { createLogger } from 'redux-logger'; import { createLogger } from 'redux-logger';
import { StackNavigator, addNavigationHelpers } from 'react-navigation';
import { AppNavigator } from './component/AppNavigator'; import { AppNavigator } from './component/AppNavigator';
import { persistStore, autoRehydrate } from 'redux-persist'; import { persistStore, autoRehydrate } from 'redux-persist';
import { reactNavigationMiddleware } from './utils/redux'; import AppWithNavigationState, { reactNavigationMiddleware } from './component/AppNavigator';
import AppWithNavigationState from './component/AppNavigator';
import FilesystemStorage from 'redux-persist-filesystem-storage'; import FilesystemStorage from 'redux-persist-filesystem-storage';
import createCompressor from 'redux-persist-transform-compress'; import createCompressor from 'redux-persist-transform-compress';
import createFilter from 'redux-persist-transform-filter'; import createFilter from 'redux-persist-transform-filter';

View file

@ -31,13 +31,14 @@ class AboutPage extends React.PureComponent {
} }
render() { render() {
const { navigation } = this.props;
const loading = 'Loading...'; const loading = 'Loading...';
const ver = this.state.versionInfo ? this.state.versionInfo : null; const ver = this.state.versionInfo ? this.state.versionInfo : null;
return ( return (
<View style={aboutStyle.container}> <View style={aboutStyle.container}>
<PageHeader title={"About LBRY"} <PageHeader title={"About LBRY"}
onBackPressed={() => { this.props.navigation.goBack(); }} /> onBackPressed={() => navigation.goBack(navigation.state.key)} />
<ScrollView style={aboutStyle.scrollContainer}> <ScrollView style={aboutStyle.scrollContainer}>
<Text style={aboutStyle.title}>Content Freedom</Text> <Text style={aboutStyle.title}>Content Freedom</Text>
<Text style={aboutStyle.paragraph}> <Text style={aboutStyle.paragraph}>

View file

@ -47,12 +47,12 @@ class ChannelPage extends React.PureComponent {
return ( return (
<View style={channelPageStyle.container}> <View style={channelPageStyle.container}>
<PageHeader title={name} onBackPressed={() => { this.props.navigation.goBack(); }} /> <PageHeader title={name} onBackPressed={() => navigation.goBack(navigation.state.key)} />
{contentList} {contentList}
<UriBar value={uri} navigation={navigation} /> <UriBar value={uri} navigation={navigation} />
</View> </View>
) )
} }
} }
export default ChannelPage; export default ChannelPage;

View file

@ -9,6 +9,7 @@ import {
View, View,
ScrollView ScrollView
} from 'react-native'; } from 'react-native';
import { navigateToUri } from '../../utils/helper';
import Colors from '../../styles/colors'; import Colors from '../../styles/colors';
import PageHeader from '../../component/pageHeader'; import PageHeader from '../../component/pageHeader';
import FileListItem from '../../component/fileListItem'; import FileListItem from '../../component/fileListItem';
@ -51,11 +52,7 @@ class DownloadsPage extends React.PureComponent {
style={fileListStyle.item} style={fileListStyle.item}
uri={this.uriFromFileInfo(item)} uri={this.uriFromFileInfo(item)}
navigation={navigation} navigation={navigation}
onPress={() => navigation.navigate({ onPress={() => navigateToUri(navigation, this.uriFromFileInfo(item), { autoplay: true })} />
routeName: 'File',
key: 'filePage',
params: { uri: this.uriFromFileInfo(item), autoplay: true }
})} />
) )
} }
data={fileInfos.sort((a, b) => { data={fileInfos.sort((a, b) => {

View file

@ -37,25 +37,25 @@ class FilePage extends React.PureComponent {
playerBackground = null; playerBackground = null;
player = null;
startTime = null; startTime = null;
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
fileViewLogged: false,
mediaLoaded: false,
autoPlayMedia: false, autoPlayMedia: false,
downloadButtonShown: false, downloadButtonShown: false,
downloadPressed: false, downloadPressed: false,
fileViewLogged: false,
fullscreenMode: false, fullscreenMode: false,
imageUrls: null,
isLandscape: false,
mediaLoaded: false,
pageSuspended: false,
showImageViewer: false, showImageViewer: false,
showWebView: false, showWebView: false,
imageUrls: null,
playerBgHeight: 0, playerBgHeight: 0,
playerHeight: 0, playerHeight: 0,
isLandscape: false, uri: null
}; };
} }
@ -64,6 +64,7 @@ class FilePage extends React.PureComponent {
const { isResolvingUri, resolveUri, navigation } = this.props; const { isResolvingUri, resolveUri, navigation } = this.props;
const { uri } = navigation.state.params; const { uri } = navigation.state.params;
this.setState({ uri });
if (!isResolvingUri) resolveUri(uri); if (!isResolvingUri) resolveUri(uri);
@ -80,15 +81,23 @@ class FilePage extends React.PureComponent {
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
this.fetchFileInfo(this.props); this.fetchFileInfo(this.props);
const { isResolvingUri, resolveUri, claim, navigation } = this.props; const { claim, contentType, fileInfo, isResolvingUri, resolveUri, navigation } = this.props;
const { uri } = navigation.state.params; const { uri } = this.state;
if (!isResolvingUri && claim === undefined && uri) { if (!isResolvingUri && claim === undefined && uri) {
resolveUri(uri); resolveUri(uri);
} }
// Returned to the page. If mediaLoaded, and currentMediaInfo is different, update
if (this.state.mediaLoaded && window.currentMediaInfo && window.currentMediaInfo.uri !== this.state.uri) {
const { metadata } = this.props;
window.currentMediaInfo = {
channel: claim ? claim.channel_name : null,
title: metadata ? metadata.title : claim.name,
uri: this.state.uri
};
}
const prevFileInfo = prevProps.fileInfo; const prevFileInfo = prevProps.fileInfo;
const { fileInfo, contentType } = this.props;
if (!prevFileInfo && fileInfo) { if (!prevFileInfo && fileInfo) {
// started downloading // started downloading
const mediaType = Lbry.getMediaType(contentType); const mediaType = Lbry.getMediaType(contentType);
@ -181,6 +190,7 @@ class FilePage extends React.PureComponent {
if (window.currentMediaInfo) { if (window.currentMediaInfo) {
window.currentMediaInfo = null; window.currentMediaInfo = null;
} }
window.player = null;
} }
localUriForFileInfo = (fileInfo) => { localUriForFileInfo = (fileInfo) => {
@ -397,7 +407,7 @@ class FilePage extends React.PureComponent {
}} />} }} />}
{canLoadMedia && fileInfo && <MediaPlayer {canLoadMedia && fileInfo && <MediaPlayer
fileInfo={fileInfo} fileInfo={fileInfo}
ref={(ref) => { this.player = ref; }} assignPlayer={(ref) => { this.player = ref; }}
uri={uri} uri={uri}
style={playerStyle} style={playerStyle}
autoPlay={autoplay || this.state.autoPlayMedia} autoPlay={autoplay || this.state.autoPlayMedia}
@ -432,7 +442,7 @@ class FilePage extends React.PureComponent {
text={channelName} text={channelName}
onPress={() => { onPress={() => {
const channelUri = normalizeURI(channelName); const channelUri = normalizeURI(channelName);
navigation.navigate({ routeName: 'File', key: channelUri, params: { uri: channelUri }}); navigation.navigate({ routeName: 'File', key: 'filePage', params: { uri: channelUri }});
}} />} }} />}
{description && description.length > 0 && <View style={filePageStyle.divider} />} {description && description.length > 0 && <View style={filePageStyle.divider} />}

View file

@ -9,7 +9,7 @@ import {
TouchableOpacity, TouchableOpacity,
View View
} from 'react-native'; } from 'react-native';
import { NavigationActions } from 'react-navigation'; import { NavigationActions, StackActions } from 'react-navigation';
import Colors from '../../styles/colors'; import Colors from '../../styles/colors';
import Constants from '../../constants'; import Constants from '../../constants';
import WelcomePage from './internal/welcome-page'; import WelcomePage from './internal/welcome-page';
@ -71,7 +71,7 @@ class FirstRunScreen extends React.PureComponent {
launchSplashScreen() { launchSplashScreen() {
const { navigation } = this.props; const { navigation } = this.props;
const resetAction = NavigationActions.reset({ const resetAction = StackActions.reset({
index: 0, index: 0,
actions: [ actions: [
NavigationActions.navigate({ routeName: 'Splash', params: { launchUri: this.state.launchUri } }) NavigationActions.navigate({ routeName: 'Splash', params: { launchUri: this.state.launchUri } })

View file

@ -8,6 +8,7 @@ import {
View, View,
ScrollView ScrollView
} from 'react-native'; } from 'react-native';
import { navigateToUri } from '../../utils/helper';
import Colors from '../../styles/colors'; import Colors from '../../styles/colors';
import PageHeader from '../../component/pageHeader'; import PageHeader from '../../component/pageHeader';
import FileListItem from '../../component/fileListItem'; import FileListItem from '../../component/fileListItem';
@ -42,11 +43,7 @@ class SearchPage extends React.PureComponent {
uri={uri} uri={uri}
style={searchStyle.resultItem} style={searchStyle.resultItem}
navigation={navigation} navigation={navigation}
onPress={() => navigation.navigate({ onPress={() => navigateToUri(navigation, uri)}/>)
routeName: 'File',
key: 'filePage',
params: { uri }})
}/>)
) : null } ) : null }
</ScrollView> </ScrollView>
{isSearching && <ActivityIndicator size="large" color={Colors.LbryGreen} style={searchStyle.loading} /> } {isSearching && <ActivityIndicator size="large" color={Colors.LbryGreen} style={searchStyle.loading} /> }

View file

@ -13,6 +13,7 @@ class SettingsPage extends React.PureComponent {
const { const {
backgroundPlayEnabled, backgroundPlayEnabled,
keepDaemonRunning, keepDaemonRunning,
navigation,
showNsfw, showNsfw,
setClientSetting setClientSetting
} = this.props; } = this.props;
@ -23,7 +24,7 @@ class SettingsPage extends React.PureComponent {
return ( return (
<View> <View>
<PageHeader title={"Settings"} <PageHeader title={"Settings"}
onBackPressed={() => { this.props.navigation.goBack(); }} /> onBackPressed={() => navigation.goBack(navigation.state.key)} />
<ScrollView style={settingsStyle.scrollContainer}> <ScrollView style={settingsStyle.scrollContainer}>
<View style={settingsStyle.row}> <View style={settingsStyle.row}>
<View style={settingsStyle.switchText}> <View style={settingsStyle.switchText}>

View file

@ -10,8 +10,9 @@ import {
Text, Text,
View View
} from 'react-native'; } from 'react-native';
import { NavigationActions } from 'react-navigation'; import { NavigationActions, StackActions } from 'react-navigation';
import { decode as atob } from 'base-64'; import { decode as atob } from 'base-64';
import { navigateToUri } from '../../utils/helper';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Colors from '../../styles/colors'; import Colors from '../../styles/colors';
import Constants from '../../constants'; import Constants from '../../constants';
@ -75,7 +76,7 @@ class SplashScreen extends React.PureComponent {
} }
// user is authenticated, navigate to the main view // user is authenticated, navigate to the main view
const resetAction = NavigationActions.reset({ const resetAction = StackActions.reset({
index: 0, index: 0,
actions: [ actions: [
NavigationActions.navigate({ routeName: 'Main'}) NavigationActions.navigate({ routeName: 'Main'})
@ -108,7 +109,7 @@ class SplashScreen extends React.PureComponent {
}); });
} }
} else { } else {
navigation.navigate({ routeName: 'File', key: launchUrl, params: { uri: launchUrl } }); navigation.navigate({ routeName: 'File', key: 'filePage', params: { uri: launchUrl } });
} }
} }
}); });

View file

@ -6,7 +6,6 @@ const screenWidth = screenDimension.width;
const screenHeight = screenDimension.height; const screenHeight = screenDimension.height;
const screenWidthPixels = PixelRatio.getPixelSizeForLayoutSize(screenWidth); const screenWidthPixels = PixelRatio.getPixelSizeForLayoutSize(screenWidth);
const screenHeightPixels = PixelRatio.getPixelSizeForLayoutSize(screenHeight); const screenHeightPixels = PixelRatio.getPixelSizeForLayoutSize(screenHeight);
console.log('screenHeightPixels=' + screenHeightPixels);
// calculate thumbnail width and height based on device's aspect ratio // calculate thumbnail width and height based on device's aspect ratio
const horizontalMargin = 48; // left and right margins (24 + 24) const horizontalMargin = 48; // left and right margins (24 + 24)
const verticalMargin = (screenWidthPixels > 720 && screenHeightPixels > 1920) ? 0 : ((screenWidthPixels <= 720) ? 20 : 16); const verticalMargin = (screenWidthPixels > 720 && screenHeightPixels > 1920) ? 0 : ((screenWidthPixels <= 720) ? 20 : 16);

40
app/src/utils/helper.js Normal file
View file

@ -0,0 +1,40 @@
import { NavigationActions, StackActions } from 'react-navigation';
export function navigateToUri(navigation, uri, additionalParams) {
if (!navigation) {
return;
}
if (uri === navigation.state.key) {
return;
}
const params = Object.assign({ uri }, additionalParams);
if ('File' === navigation.state.routeName) {
const stackAction = StackActions.replace({ routeName: 'File', newKey: uri, params });
navigation.dispatch(stackAction);
return;
}
navigation.navigate({ routeName: 'File', key: uri, params });
}
export function dispatchNavigateToUri(dispatch, nav, uri) {
const params = { uri };
if (nav && nav.routes && nav.routes.length > 0 && 'Main' === nav.routes[0].routeName) {
const mainRoute = nav.routes[0];
const discoverRoute = mainRoute.routes[0];
if (discoverRoute.index > 0 && 'File' === discoverRoute.routes[discoverRoute.index].routeName) {
const fileRoute = discoverRoute.routes[discoverRoute.index];
// Currently on a file page, so we can ignore (if the URI is the same) or replace (different URIs)
if (uri !== fileRoute.params.uri) {
const stackAction = StackActions.replace({ routeName: 'File', newKey: uri, params });
dispatch(stackAction);
return;
}
}
}
const navigateAction = NavigationActions.navigate({ routeName: 'File', key: uri, params });
dispatch(navigateAction);
}

View file

@ -1,15 +0,0 @@
import {
createReactNavigationReduxMiddleware,
createReduxBoundAddListener,
} from 'react-navigation-redux-helpers';
const reactNavigationMiddleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav,
);
const addListener = createReduxBoundAddListener("root");
export {
reactNavigationMiddleware,
addListener,
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B