Skip to content

Commit

Permalink
Breathly v2 (#99)
Browse files Browse the repository at this point in the history
I redesigned Breathly's UI and architecture from the ground up to make it easy to implement many of the requests I got in the past. I'm talking about things like pure OLED theme, being able to use decimals in the exercise step lengths, adding white noise, and so on.

From a technical standpoint, I moved Breathly to Expo. This change should make it easier to update to major versions of React Native.
  • Loading branch information
mmazzarolo authored Feb 5, 2023
1 parent 71e0225 commit 2f17d01
Show file tree
Hide file tree
Showing 378 changed files with 28,646 additions and 24,017 deletions.
Binary file removed .assets/app/check.png
Binary file not shown.
Binary file removed .assets/app/close.png
Binary file not shown.
Binary file removed .assets/app/left-arrow.png
Binary file not shown.
Binary file removed .assets/app/meditation.png
Binary file not shown.
Binary file removed .assets/app/play.png
Binary file not shown.
Binary file removed .assets/app/settings.png
Binary file not shown.
Binary file removed .assets/app/stars.png
Binary file not shown.
570 changes: 0 additions & 570 deletions .assets/app/stars.svg

This file was deleted.

Binary file removed .assets/audio/julianebreathein.mp3
Binary file not shown.
Binary file removed .assets/audio/julianebreatheout.mp3
Binary file not shown.
Binary file removed .assets/audio/julianehold.mp3
Binary file not shown.
Binary file removed .assets/icon/icon-rounded.png
Binary file not shown.
Binary file removed .assets/icon/icon.png
Binary file not shown.
Binary file removed .assets/icon/icon.psd
Binary file not shown.
Binary file removed .assets/logo/logo-colored.png
Binary file not shown.
Binary file removed .assets/logo/logo.png
Binary file not shown.
Binary file removed .assets/logo/logo.psd
Binary file not shown.
Binary file removed .assets/splash-screen/splash-bg.png
Binary file not shown.
Binary file removed .assets/splash-screen/splash-fg.png
Binary file not shown.
Binary file removed .assets/splash-screen/splash-fg.psd
Binary file not shown.
6 changes: 0 additions & 6 deletions .buckconfig

This file was deleted.

32 changes: 32 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"overrides": [
{
"files": ["*.ts", "*.tsx"],
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react", "react-hooks", "@typescript-eslint"],
"rules": {
"@typescript-eslint/ban-ts-comment": "warn"
},
"settings": {
"react": {
"version": "detect"
}
}
}
]
}
4 changes: 4 additions & 0 deletions .expo-shared/assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
3 changes: 0 additions & 3 deletions .gitattributes

This file was deleted.

Binary file removed .github/breathly-hatchful-logo.png
Binary file not shown.
Binary file modified .github/icon-rounded.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 .github/iphone-1.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 .github/iphone-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 21 additions & 59 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,62 +1,24 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate

# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml

# Visual Studio Code
#
.vscode/

# node.js
#
# Node & Expo defaults
node_modules/
npm-debug.log
yarn-error.log

# BUCK
buck-out/
\.buckd/
*.keystore

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/

*/fastlane/report.xml
*/fastlane/Preview.html
*/fastlane/screenshots
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/

# macOS
.DS_Store

# Bundle artifact
*.jsbundle
# Secrets
android/keystores
credentials.json

# CocoaPods
/ios/Pods/
# Build output
*.ipa
*.apk
*.aab
32 changes: 32 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.rulers": [100],
"editor.quickSuggestions": {
"strings": true
},
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#425394",
"activityBar.background": "#425394",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#421e25",
"activityBarBadge.foreground": "#e7e7e7",
"commandCenter.border": "#e7e7e799",
"sash.hoverBorder": "#425394",
"statusBar.background": "#323f71",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#425394",
"statusBarItem.remoteBackground": "#323f71",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#323f71",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#323f7199",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "#323f71",
"typescript.tsdk": "node_modules/typescript/lib"
}
1 change: 0 additions & 1 deletion .watchmanconfig

This file was deleted.

1 change: 1 addition & 0 deletions @types/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="nativewind/types" />
3 changes: 0 additions & 3 deletions @types/images.d.ts

This file was deleted.

1 change: 0 additions & 1 deletion @types/json.d.ts

This file was deleted.

3 changes: 3 additions & 0 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { EntryPoint } from "./src/core/entry-point";

export default EntryPoint;
27 changes: 26 additions & 1 deletion DEVLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
# DEVLOG

## 2023-02-04

I'm back! With a huge update.

I'll try to keep it short this time: I redesigned Breathly's UI and architecture from the ground up to make it easy to implement many of the requests I got in the past. I'm talking about things like pure OLED theme, being able to use decimals in the exercise step lengths, adding white noise, and so on.

From a technical standpoint, I moved Breathly to Expo. This change should make it easier to update to major versions of React Native.

Check out updated README.md for more info!

### New stack

- Expo, expo, expo. And several expo-related-libraries like `expo-haptics`, `expo-keep-awake`, etc. I'm so happy I can finally use these kind of things without wasting hours tuning them on the native side (check the previous DEVLOG entries for examples of what I mean).
- I ditched my custom routing solution for React Navigation (which is pretty good nowadays!).
- I'm using [NativeWind](https://www.nativewind.dev/) to style the app. I love Tailwind and NativeWind worked really well for me so far.
- I replaced the messy React Context with [Zustand](https://github.com/pmndrs/zustand). I'm mainly using it to store and persist the user customizations.

### Quirks and issues

1. [This ancient React Native bug is still alive](https://github.com/facebook/react-native/issues/28517): in release mode on iOS the starry background was mistakenly defaulting to `resizeMode=”cover”` even if I explicitly set it to `resizeMode=“repeat”`. Had to edit the image to solve it.
2. Talking about ancient issues, [I still couldn’t get `Animated.sequence` + `Animated.loop` to work correctly together with animation using the native driver](https://github.com/facebook/react-native/issues/28670). I’m still using my own little util as a workaround (`src/utils/loop-animations.ts`).
3. On Android, animating the opacity of images with the native driver sometimes causes a flash of the image even when completely transparent. This is also an old issue that I’ve been solving for ages [with this ugly workaround](https://github.com/mmazzarolo/ordinary-puzzles-app/blob/b31ca3cc0e4cc66b7b9e39ecc3449b828c5f09e5/src/op-board/Board.tsx#L102-L111).
4. Transparent Android navbars are cool but are wonky on Expo/RN. To make them work [you must set their background to a dumb value like `"rgba(0, 0, 0, 0.002)"` (`"transparent"` or hex vals don’t work)](https://github.com/expo/expo/issues/16036). Also, the transparency breaks when the app transitions from the background to the foreground. I'm manually forcing the transparency back by checking the `appState` and avoiding race conditions with ugly timers/next-ticks but it's inconsistent and you can still see it flash a bit. And it also makes the splash screen jump a bit because the navigation bar is hidden **while** the splash screen is being shown 🙄.
5. I enjoyed using NativeWind on this project. I only had a couple of issues with `useColorScheme` returning stale data but I patched it manually (see `patches/nativewind+2.0.11.patch`). I noticed it’s being solved in the next version (v3) anyway.

## 2020-05-17

It has been a long time since my last update to the codebase.
Expand All @@ -25,7 +50,7 @@ Updating Breathly to `[email protected]` was... well, definitely **not** painl
5. Next, it was the turn of the _"Undefined symbol: \_swift_getFunctionReplacement"_, fixed following https://github.com/react-native-community/upgrade-support/issues/25.
6. At this point I was finally able to build the project and create a debug build.
7. I immediately tried building production one, and it "worked"... with a minor, problem: the IPA size is now double the size it was before (https://github.com/facebook/react-native/issues/28890). Everything seems to be working fine though 🤷‍♂️
Update: also notice building on a real device is not working for me. Had to completely disable Flipper to make it work https://github.com/invertase/react-native-firebase/issues/3384
Update: also notice building on a real device is not working for me. Had to completely disable Flipper to make it work https://github.com/invertase/react-native-firebase/issues/3384

#### Building Android

Expand Down
33 changes: 8 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,10 @@ You can use Breathly for daily relaxation and breath training: just choose a bre

<p align="center" margin-bottom="0">
<a href="https://breathly.app">
<img alt="Breathly" width="820" height="auto" src="https://github.com/mmazzarolo/breathly-website/raw/master/.github/screenshot.png">
</a>
</p>

<p align="center" margin-bottom="0">
<a href="https://breathly.app">
<img alt="Breathly" width="380" height="auto" src="./.github/iphone-1.png">
<img alt="Breathly" width="300" height="auto" src="./.github/iphone-1.png">
</a>
<a href="https://breathly.app">
<img alt="Breathly" width="380" height="auto" src="./.github/iphone-2.png">
<img alt="Breathly" width="300" height="auto" src="./.github/iphone-2.png">
</a>
</p>

Expand All @@ -49,29 +43,18 @@ You can use Breathly for daily relaxation and breath training: just choose a bre

In this repository you'll find the source code of the Breathly mobile app.

Breathly is a small React-Native app that I developed on my free time in 2018 for playing around with the React-Native `Animated` API.
With the incoming React-Native's hooks support I decided to get back on it, rewrite it with hooks, and also release it in the Play Store and in App Store.
Breathly is a tiny React-Native app that I developed in my free time to refine my React-Native knowledge and test new shiny things.

I hope the source code will be useful to someone.

👉 **Check the [DEVLOG](./DEVLOG.md) for more informations and details about the app architecture and a few development highlights.**

### Features / Stack

- React-Native and TypeScript
- React hooks
- All the `Animated` animations are using the native driver
- Type-safe `Context` + `useReducer` usage (pretty similar to Redux)

### Resources and acknowledgements

Most of the stuff you see in the app is just a derivation of other people's work.
I tried to keep track of them during the development process:
## Resources and acknowledgements

- The "play" button animation is based on a Switft custom modal transition called [BubbleTransition](https://github.com/andreamazz/BubbleTransition)
- For the Breathly logo I used [Hatchful](https://hatchful.shopify.com) to get a few proposed logos and I used [this one](./.github/breathly-hatchful-logo.png) as the foundation for the current one (build with PhotoShop)
- The technique picker View Pager animations are inspired by the InVision Android app onboarding screen
- I used [this mockup](https://gumroad.com/l/edFPQ) from [Lstore design goodies](https://gumroad.com/lstore) to create the iPhone X preview that you can see at the top of the README.
- I created the app icon using [SVGWave](https://svgwave.in/) and edited using [Affinity Photo](https://svgwave.in/).
- I created and edited the App Store screenshots using [Screenshots.pro](https://screenshots.pro/).
- I created the Play Store screenshots by grabbing a few device mockups from [Mockuuups Studio](https://mockuuups.studio/) and editing them using [Affinity Photo](https://svgwave.in/).
- The breathing animation is a copy/paste of different breathing animation styles I've found online. Nothing fancy.
- The breathing techniques are the same ones used in a bunch of other iOS apps and their description were obtained with a Google search. A few of the apps used as inspirations are:
- [Breathe+ Simple Breath Trainer](https://itunes.apple.com/us/app/breathe-simple-breath-trainer/id1106998959?mt=8)
- [iBreathe – Relax and Breathe](https://itunes.apple.com/us/app/ibreathe-relax-and-breathe/id1296605806)
Expand Down
55 changes: 0 additions & 55 deletions android/app/BUCK

This file was deleted.

Loading

0 comments on commit 2f17d01

Please sign in to comment.