Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make download links cross-platform #476

Merged
merged 15 commits into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,18 @@ module.exports = {
env: {
jest: true
},
settings: {
'import/resolver': {
node: {
extensions: [
'.js',
'.website.js',
'.desktop.js',
'.native.js',
'.ios.js',
'.android.js',
]
}
}
}
};
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ You can use any IDE or code editing tool for developing on any platform. Use you
1. The application uses [React-Router](https://reactrouter.com/native/guides/quick-start) for navigating between parts of the app.
1. [Higher Order Components](https://reactjs.org/docs/higher-order-components.html) are used to connect React components to persistent storage via Ion.

## Platform-Specific File Extensions
In most cases, the code written for this repo should be platform-independent. In such cases, each module should have a single file, `index.js`, which defines the module's exports. There are, however, some cases in which a feature is intrinsically tied to the underlying platform. In such cases, the following file extensions can be used to export platform-specific code from a module:
- Mobile => `index.native.js`
- iOS/Android => `index.ios.js`/`index.android.js`
- Web => `index.website.js`
- Desktop => `index.desktop.js`

Note that `index.js` should be the default. i.e: If you have mobile-specific implementation in `index.native.js`, then the desktop/web implementation can be contained in a shared `index.js`. Furthermore, `index.native.js` should not be included in the same module as `index.ios.js` or `index.android.js`, nor should `index.js` be included in the same module as `index.website.js` or `index.desktop.js`.

## Structure of the app
These are the main pieces of the application.

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
"android": "react-native run-android",
"ios": "react-native run-ios",
"ipad": "react-native run-ios --simulator=\"iPad Pro (12.9-inch) (4th generation)\"",
"desktop": "webpack --config webpack.dev.js && electron main.js",
"desktop": "webpack --config webpack.dev.js --platform desktop && electron main.js",
"start": "react-native start",
"web": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js",
"desktop-build": "webpack --config webpack.prod.js && electron-builder --config desktop/electron.config.js --publish always",
"desktop-build": "webpack --config webpack.prod.js --platform desktop && electron-builder --config desktop/electron.config.js --publish always",
"ios-build": "fastlane ios build",
"android-build": "fastlane android build",
"test": "jest",
Expand Down
30 changes: 30 additions & 0 deletions src/page/home/sidebar/AppLinks/index.desktop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';

import styles from '../../../../style/StyleSheet';
import openURLInNewTab from '../../../../lib/openURLInNewTab';
import Text from '../../../../components/Text';

const AppLinks = () => (
<>
<Text
style={[styles.sidebarFooterLink, styles.mr2]}
onPress={() => openURLInNewTab('https://chat.expensify.com')}
>
Web
</Text>
<Text
style={[styles.sidebarFooterLink, styles.mr2]}
onPress={() => openURLInNewTab('https://testflight.apple.com/join/ucuXr4g5')}
>
iOS
</Text>
<Text
style={[styles.sidebarFooterLink, styles.mr2]}
onPress={() => openURLInNewTab('https://play.google.com/apps/internaltest/4700657970395613233')}
>
Android
</Text>
</>
);

export default AppLinks;
17 changes: 17 additions & 0 deletions src/page/home/sidebar/AppLinks/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import styles from '../../../../style/StyleSheet';
import openURLInNewTab from '../../../../lib/openURLInNewTab';
import Text from '../../../../components/Text';

const AppLinks = () => (
<>
<Text
style={[styles.sidebarFooterLink, styles.mr2]}
onPress={() => openURLInNewTab('https://chat.expensify.com/')}
>
View on web
</Text>
</>
);

export default AppLinks;
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import styles from '../../../style/StyleSheet';
import openURLInNewTab from '../../../lib/openURLInNewTab';
import Text from '../../../components/Text';

import styles from '../../../../style/StyleSheet';
import openURLInNewTab from '../../../../lib/openURLInNewTab';
import Text from '../../../../components/Text';

const AppLinks = () => (
<>
Expand Down
22 changes: 18 additions & 4 deletions webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');

// Check for a --platform command line argument (default to 'web')
// If it is 'web', we want to ignore .desktop.js files, and if it is 'desktop', we want to ignore .website.js files.
const platformIndex = process.argv.findIndex(arg => arg === '--platform');
const platform = (platformIndex > 0) ? process.argv[platformIndex + 1] : 'web';
const platformExclude = platform === 'web' ? new RegExp(/\.desktop\.js$/) : new RegExp(/\.website\.js$/);

module.exports = {
entry: {
app: './web/index.js',
Expand Down Expand Up @@ -41,12 +47,18 @@ module.exports = {
* You can remove something from this list if it doesn't use "react-native" as an import and it doesn't
* use JSX/JS that needs to be transformed by babel.
*/
exclude: /node_modules\/(?!(react-native-render-html|react-native-webview)\/).*|\.native.js$/,
exclude: [
/node_modules\/(?!(react-native-render-html|react-native-webview)\/).*|\.native\.js$/,
platformExclude
],
},
{
test: /\.js$/,
loader: 'eslint-loader',
exclude: /node_modules|\.native.js$/,
exclude: [
/node_modules|\.native\.js$/,
platformExclude
],
options: {
cache: false,
emitWarning: true,
Expand All @@ -71,7 +83,9 @@ module.exports = {
},

// React Native libraries may have web-specific module implementations that appear with the extension `.web.js`
// without this, web will try to use native implementations and break in not very obvious ways
extensions: ['.web.js', '.js'],
// without this, web will try to use native implementations and break in not very obvious ways.
// This is also why we have to use .website.js for our own web-specific files...
// Because desktop also relies on "web-specific" module implementations
extensions: ['.web.js', '.js', (platform === 'web') ? '.website.js' : '.desktop.js'],
},
};