Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Expensify/Expensify.cash into paras…
Browse files Browse the repository at this point in the history
…harrajat/unreadchat
  • Loading branch information
parasharrajat committed Apr 27, 2021
2 parents 73dc5d8 + 99b44b3 commit 388543d
Showing 57 changed files with 415 additions and 83 deletions.
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -4,3 +4,4 @@ EXPENSIFY_PARTNER_NAME=chat-expensify-com
EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66
PUSHER_APP_KEY=268df511a204fbb60884
USE_WEB_PROXY=false
ENVIRONMENT=PROD
1 change: 1 addition & 0 deletions .env.staging
Original file line number Diff line number Diff line change
@@ -4,3 +4,4 @@ EXPENSIFY_PARTNER_NAME=chat-expensify-com
EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66
PUSHER_APP_KEY=268df511a204fbb60884
USE_WEB_PROXY=false
ENVIRONMENT=STG
11 changes: 11 additions & 0 deletions STYLE.md
Original file line number Diff line number Diff line change
@@ -141,6 +141,17 @@ Using arrow functions is the preferred way to write an anonymous function such a
_.map(someArray, (item) => {...});
```

Empty functions (noop) should be declare as arrow functions with no whitespace inside. Avoid _.noop()

```javascript
// Bad
const callback = _.noop;
const callback = () => { };
// Good
const callback = () => {};
```

## `var`, `const` and `let`

- Never use `var`
216 changes: 216 additions & 0 deletions STYLING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# React Native Styling Guidelines

## Where to Define Styles

All styles must be defined in the `/styles` directory and `styles.js` contains the final export after gathering all appropriate styles. Unlike some React Native applications we are not using `StyleSheet.create()` and instead store styles as plain JS objects. There are also many helper styles available for direct use in components.

These helper styles are loosely based on the [Bootstrap system of CSS utility helper classes](https://getbootstrap.com/docs/5.0/utilities/spacing/) and are typically incremented by units of `4`.

**Note:** Not all helpers from Bootstrap exist, so it may be necessary to create the helper style we need.

## When to Create a New Style

If we need some minimal set of styling rules applied to a single-use component then it's almost always better to use an array of helper styles rather than create an entirely new style if it will only be used once. Resist the urge to create a new style for every new element added to a screen. There is a very good chance the style we are adding is a "single-use" style.

```jsx
// Bad - Since we only use this style once in this component
const TextWithPadding = props => (
<Text style={styles.textWithPadding}>
{props.children}
</Text>
);

// Good
const TextWithPadding = props => (
<Text
style={[
styles.p5,
styles.noWrap,
]}
>
{props.children}
</Text>
);
```

On the other hand, if we are copying and pasting some chunks of JSX from one place to another then that might be a sign that we need a new reusable style.

## Use the "Rule of Three"

In order to resist the urge to preoptimize and have many single-use components we've adopted a main principle:

Any array of styles associated with a single type of React element that has at least 3 identical usages should be refactored into:

- A new resusable style that can be used in many places e.g. `styles.button`
- If that style has modifiers or style variations then those styles should follow a naming convention of `styles.elementModifer` e.g. `styles.buttonSuccess`
- If a reusable style has 3 or more modifiers it should be refactored into a component with props to modify the styles e.g.

```jsx
<Button title="Submit" success large />
```

## Inline Styles

**Inline styles are forbidden.** If we run into a case where we feel it's necessary to conditionally render some styles we should create a helper function then pass any modifying parameters to that function. Small helper functions can be written directly in `styles.js`, but larger, more complex methods should be put in their own modules and imported into `styles.js`.

```jsx
// Bad - Do not use inline styles
const TextWithPadding = props => (
<Text style={{
padding: 10,
whiteSpace: props.shouldWrap ? 'wrap' : 'nowrap',
}}>
{props.children}
</Text>
);

// Good
const TextWithPadding = props => (
<Text
style={[
styles.p5,
getTextWrapStyle(props.shouldWrap)
]}
>
{props.children}
</Text>
);
```

## How to Reuse Styles

There are many styles in the `styles.js` file. It is generally a bad practice to grab a style meant for a _specific_ use case and utilize it for some other more _general_ use case without changing it's name to make it more general. If we think we see a style that might be appropriate for reuse, but does not have a generic name then we should **rename it** instead of using it directly.

```jsx
// Bad - Reuses style without generalizing style name
const SettingsScreen = props => (
<View>
<Text style={[styles.settingsScreenText]}>
Expensify
</Text>
</View>
);

const SomeOtherScreen = props => (
<View>
<Text style={[styles.settingsScreenText]}>
Expensify.cash
</Text>
</View>
);

// Good
const SettingsScreen = props => (
<View>
<Text style={[styles.defaultScreenText]}>
Expensify
</Text>
</View>
);

const SomeOtherScreen = props => (
<View>
<Text style={[styles.defaultScreenText]}>
Expensify.cash
</Text>
</View>
);
```

## When and How to Pass Styles via Props

In some cases, we may want a more complex component to allow a parent to modify a style of one of it's child elements. In other cases, we may have a very simple component that has one child which has a `style` prop. Let's look at how to handle these two examples.

### Complex Component

Always pass style props with a name that describes which child element styles will be modified. All style props should accept an `Array` of style `Object` and have a pluralized name e.g. `headerStyles`

```jsx
// Bad - props.style should not be used in complex components
const SettingsScreen = props => (
<View>
<Header
style={[
styles.defaultHeader,
props.style,
]}
/>
<Body style={props.bodyStyles} />
...
</View>
);

// Bad - style with a flexible type requires extra handling
const SettingsScreen = props => {
const extraHeaderStyles = _.isArray(props.headerStyle)
? props.headerStyle
: [props.headerStyle];
return (
<View>
<Header
style={[
styles.defaultHeader,
...extraHeaderStyles,
]}
/>
<Body style={[props.bodyStyle]} />
...
</View>
);
}

// Bad - Uses a singular and passes a single style object
const SettingsScreen = props => (
<View>
<Header
style={[
styles.defaultHeader,
props.headerStyle,
]}
/>
...
</View>
);

// Good - Uses a plural and passes an array of style objects with spread syntax
const SettingsScreen = props => (
<View>
<Header
style={[
styles.defaultHeader,
...props.headerStyles,
]}
/>
...
</View>
);
```

### Simple Component

The only time we should allow a component to have a `style` prop with `PropTypes.any` is when we are wrapping a single child that has a flexible `style` type that accepts both `Array` or `Object` types.

```jsx
// Good
const CustomText = props => (
<Text style={props.style}>{props.children}</Text>
);

// Good
const CustomText = props => {
const propsStyle = _.isArray(props.style)
? props.style
: [props.style];
}(
<Text
style={[
styles.defaultCustomText,
...propsStyle,
]}
>
{props.children}
</Text>
);
```

In that last example, there is just one simple element and no ambiguity about what `props.style` refers to. The component is used in many places and has some default styles therefore we must add custom style handling behavior.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -148,8 +148,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001003100
versionName "1.0.31-0"
versionCode 1001003104
versionName "1.0.31-4"
}
splits {
abi {
Binary file modified android/app/src/main/res/drawable-hdpi/ic_notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/drawable-mdpi/ic_notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/drawable-xhdpi/ic_notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/drawable-xxhdpi/ic_notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/drawable-xxxhdpi/ic_notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-hdpi/bootsplash_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-mdpi/bootsplash_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xhdpi/bootsplash_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xxhdpi/bootsplash_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xxxhdpi/bootsplash_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:textColor">#000000</item>
<item name="android:windowTranslucentStatus">true</item>
</style>

<style name="BootTheme" parent="AppTheme">
8 changes: 8 additions & 0 deletions assets/images/expensify-cash-dev.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions assets/images/expensify-cash-stg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 14 additions & 19 deletions assets/images/expensify-cash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/expensify-logo-round.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/welcome-screenshot-wide.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/welcome-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion config/electron.config.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ module.exports = {
},
mac: {
category: 'public.app-category.finance',
icon: './desktop/icon.png',
icon: process.env.SHOULD_DEPLOY_PRODUCTION === 'true' ? './desktop/icon.png' : './desktop/icon-stg.png',
hardenedRuntime: true,
entitlements: 'desktop/entitlements.mac.plist',
entitlementsInherit: 'desktop/entitlements.mac.plist',
Binary file added desktop/icon-dev.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added desktop/icon-stg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified desktop/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions desktop/main.js
Original file line number Diff line number Diff line change
@@ -117,6 +117,12 @@ const mainWindow = (() => {
? win => win.loadURL(`http://localhost:${port}`)
: serve({directory: `${__dirname}/../dist`});

// Prod and staging set the icon in the electron-builder config, so only update it here for dev
if (isDev) {
app.dock.setIcon(`${__dirname}/icon-dev.png`);
app.setName('Expensify.cash');
}

return app.whenReady()
.then(() => {
const browserWindow = new BrowserWindow({
@@ -130,6 +136,11 @@ const mainWindow = (() => {
titleBarStyle: 'hidden',
});

// Prod and staging overwrite the app name in the electron-builder config, so only update it here for dev
if (isDev) {
browserWindow.setTitle('Expensify.cash');
}

// List the Expensify Chat instance under the Window menu, even when it's hidden
const systemMenu = Menu.getApplicationMenu();
systemMenu.insert(4, new MenuItem({
Binary file modified ios/ExpensifyCash/Images.xcassets/AppIcon.appiconset/Store.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ios/ExpensifyCash/Images.xcassets/AppIcon.appiconset/iPad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ios/ExpensifyCash/Images.xcassets/AppIcon.appiconset/iPadPro.png
2 changes: 1 addition & 1 deletion ios/ExpensifyCash/Info.plist
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.0.31.0</string>
<string>1.0.31.4</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
2 changes: 1 addition & 1 deletion ios/ExpensifyCashTests/Info.plist
Original file line number Diff line number Diff line change
@@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.31.0</string>
<string>1.0.31.4</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "expensify.cash",
"version": "1.0.31-0",
"version": "1.0.31-4",
"author": "Expensify, Inc.",
"homepage": "https://expensify.cash",
"description": "Expensify.cash is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Loading

0 comments on commit 388543d

Please sign in to comment.