diff --git a/.eslintrc.js b/.eslintrc.js
index 6d493dec553ce..630a8f04f884c 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -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',
+ ]
+ }
+ }
+ }
};
diff --git a/README.md b/README.md
index d5de57d694e9d..5e6b7fb94f333 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/package.json b/package.json
index e06014a9b0ea8..be815949101d1 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/page/home/sidebar/AppLinks/index.desktop.js b/src/page/home/sidebar/AppLinks/index.desktop.js
new file mode 100644
index 0000000000000..2d966d9e149b5
--- /dev/null
+++ b/src/page/home/sidebar/AppLinks/index.desktop.js
@@ -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 = () => (
+ <>
+ openURLInNewTab('https://chat.expensify.com')}
+ >
+ Web
+
+ openURLInNewTab('https://testflight.apple.com/join/ucuXr4g5')}
+ >
+ iOS
+
+ openURLInNewTab('https://play.google.com/apps/internaltest/4700657970395613233')}
+ >
+ Android
+
+ >
+);
+
+export default AppLinks;
diff --git a/src/page/home/sidebar/AppLinks/index.native.js b/src/page/home/sidebar/AppLinks/index.native.js
new file mode 100644
index 0000000000000..7488b7905b4aa
--- /dev/null
+++ b/src/page/home/sidebar/AppLinks/index.native.js
@@ -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 = () => (
+ <>
+ openURLInNewTab('https://chat.expensify.com/')}
+ >
+ View on web
+
+ >
+);
+
+export default AppLinks;
diff --git a/src/page/home/sidebar/AppLinks.js b/src/page/home/sidebar/AppLinks/index.website.js
similarity index 81%
rename from src/page/home/sidebar/AppLinks.js
rename to src/page/home/sidebar/AppLinks/index.website.js
index 214e6ae63592c..59204dc80c849 100644
--- a/src/page/home/sidebar/AppLinks.js
+++ b/src/page/home/sidebar/AppLinks/index.website.js
@@ -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 = () => (
<>
diff --git a/webpack.common.js b/webpack.common.js
index 578f7a8e1411a..691a0160fc3aa 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -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',
@@ -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,
@@ -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'],
},
};