Skip to content
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
15 changes: 2 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,15 +443,7 @@ Files should be named after the component/function/constants they export, respec
- All React components should be PascalCase (a.k.a. UpperCamelCase 🐫).

## 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 Native App/Android Native App => `index.ios.js`/`index.android.js`
- Web => `index.website.js`
- Desktop => `index.desktop.js`

**Note:** `index.js` should be the default and only platform-specific implementations should be done in their respective files. 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`.

`index.ios.js` and `index.android.js` are used when the app is running natively on respective platforms. These files are not used when users access the app through mobile browsers, but `index.website.js` is used instead. `index.native.js` are for both iOS and Android native apps. `index.native.js` should not be included in the same module as `index.ios.js` or `index.android.js`.
This section has moved [here](contributingGuides/philosophies/CROSS-PLATFORM.md).

## API building
When adding new API commands (and preferably when starting using a new one that was not yet used in this codebase) always
Expand Down Expand Up @@ -659,10 +651,7 @@ This application is built with the following principles.
5. UI updates with data from the server

1. **Cross Platform 99.9999%**
1. A feature isn't done until it works on all platforms. Accordingly, don't even bother writing a platform-specific code block because you're just going to need to undo it.
1. If the reason you can't write cross-platform code is because there is a bug in ReactNative that is preventing it from working, the correct action is to fix RN and submit a PR upstream -- not to hack around RN bugs with platform-specific code paths.
1. If there is a feature that simply doesn't exist on all platforms and thus doesn't exist in RN, rather than doing if (platform=iOS) { }, instead write a "shim" library that is implemented with NOOPs on the other platforms. For example, rather than injecting platform-specific multi-tab code (which can only work on browsers, because it's the only platform with multiple tabs), write a TabManager class that just is NOOP for non-browser platforms. This encapsulates the platform-specific code into a platform library, rather than sprinkling through the business logic.
1. Put all platform specific code in dedicated files and folders, like /platform, and reject any PR that attempts to put platform-specific code anywhere else. This maintains a strict separation between business logic and platform code.
See details [here](contributingGuides/philosophies/CROSS-PLATFORM.md).

----

Expand Down
45 changes: 45 additions & 0 deletions contributingGuides/philosophies/CROSS-PLATFORM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Cross Platform Philosophy
Learn how the app supports features across all our different platforms.

Currently supported platforms:
- Web
- Mobile Web
- Desktop
- iOS
- Android

The goal is: **Cross Platform 99.9999%**

## Rules
### - Features MUST be implemented on all supported platforms
A feature isn't done until it works on all platforms. Any platform-specific code blocks will be asked to be undone.

### - React Native bugs MUST be fixed upstream
If the reason cross-platform code cannot be written is because there is a bug in ReactNative that is preventing it from working, the correct action is to fix RN and submit a PR upstream -- not to hack around RN bugs with platform-specific code paths.

While upstream PRs are waiting to be merged, a patch can be used which is managed by the NPM package `patch-package`. Read more about it [here](https://github.com/Expensify/App?tab=readme-ov-file#adding-hybridapp-related-patches).

### - Features that don't exist on all platforms MUST use NOOP shims
If there is a feature that simply doesn't exist on all platforms and thus doesn't exist in RN, rather than doing `if (platform=iOS) { }`, instead write a "shim" library that is implemented with NOOPs on the other platforms. For example, rather than injecting platform-specific multi-tab code (which can only work on browsers, because it's the only platform with multiple tabs), write a TabManager class that just is NOOP for non-browser platforms. This encapsulates the platform-specific code into a platform library, rather than sprinkling through the business logic.

### - Platform specific code MUST be placed in dedicated files and folders
Put all platform specific code in dedicated files and folders (see below) and reject any PR that attempts to put platform-specific code anywhere else. This maintains a strict separation between business logic and platform code.

## 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 Native App/Android Native App => `index.ios.js`/`index.android.js`
- Web => `index.website.js`
- Desktop => `index.desktop.js`

**Note:** `index.js` should be the default and only platform-specific implementations should be done in their respective files. 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`.

`index.ios.js` and `index.android.js` are used when the app is running natively on respective platforms. These files are not used when users access the app through mobile browsers, but `index.website.js` is used instead. `index.native.js` are for both iOS and Android native apps. `index.native.js` should not be included in the same module as `index.ios.js` or `index.android.js`.

### Supporting Mobile Web
The above platform-specific files only work because they are compiled when the app is built for the different platforms. This means that a different mechanism needs to be used for Mobile Web (since "mobile web" and "web" are the same at build time).

It is also well known that different mobile browsers have different quirks and need to use different workarounds at times.

#### - Mobile browser detection SHOULD never be used

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### - Mobile browser detection SHOULD never be used
#### - Mobile browser detection should NEVER be used

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to reject this suggestion since it wouldn't be consistent with all the rest of the docs where the "SHOULD" (ie. "MUST") word is in all caps.

If there is absolutely no other way to fix a bug, then the proper way of detecting the browser is using `@libs/Browser`. Use this as an absolute last resort and have the exception approved by several (ie. more than one) internal engineers.
1 change: 1 addition & 0 deletions contributingGuides/philosophies/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
"OPTIONAL" are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).

## Contents
* [Cross-Platform Philosophy](/contributingGuides/philosophies/CROSS-PLATFORM.md)
* [Offline Philosophy](/contributingGuides/philosophies/OFFLINE.md)
* [Routing Philosophy](/contributingGuides/philosophies/ROUTING.md)