Skip to content

Commit

Permalink
Adding Example App for faster development (#1411)
Browse files Browse the repository at this point in the history
[skip ci]

The goal of this PR is to have an example app inside the project to
improve developer experience and exercise reactotron's capabilities.
Currently, you need to have an application configured for Reactotron
outside of the project to test. If you want to test the client
libraries, you'd have to setup copying those dependencies into your
application as an additional step.

By adding an example application into the monorepo, we get the following
benefits:

- Faster feedback loop on client library development
- All inclusive reactotron development experience (No external
application required; though still supported.)
- An application for people to reproduce bugs in shortening time to
resolution.
- Show examples of usage and conifguration

In this PR, I've additionally done the following in support of this
effort:

- Upgraded Ramda to 0.28.0. I could not go to latest as we are still
using Typescript 4.9.5.
(ramda/ramda#3415 (comment))
- Upgraded mobx and mobx-state-tree so that our dev dependencies are
using the latest versions.
- Updated the documentation

---------

Co-authored-by: Mark Rickert <mjar81@gmail.com>
  • Loading branch information
morganick and markrickert committed Jan 24, 2024
1 parent d1b3270 commit c95e172
Show file tree
Hide file tree
Showing 175 changed files with 11,102 additions and 4,697 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[Join our Community Slack](http://community.infinite.red/)

# Introduction
## Introduction

Reactotron is a powerful debugger for React and React Native applications. It provides an easy-to-use interface for developers to monitor their application's **state, network requests, and performance metrics** and can be used for any size of project, from small personal apps to large-scale enterprise applications. The OG debugger at [Infinite Red](https://infinite.red) that we use on a day-to-day basis to build client apps. Additionally, Reactotron is completely open source and free to use, making it an invaluable tool for developers at all levels of experience.

Expand Down Expand Up @@ -66,7 +66,11 @@ On the [Releases](https://github.com/infinitered/reactotron/releases?q=reactotro

[Some tips that will elevate your Reactotron experience.](https://docs.infinite.red/reactotron/tips/)

## Want to contribute? Here are some helpful reading materials:
## Bug Reports

When reporting problems with Reactotron, use the provided example app located in `app/example-app` to replicate the issue. This approach enables us to isolate and expedite the resolution of the problem.

## Want to contribute? Here are some helpful reading materials

- [**Contributing**](https://docs.infinite.red/reactotron/contributing/)
- [**Architecture**](https://docs.infinite.red/reactotron/contributing/architecture/)
Expand All @@ -78,10 +82,10 @@ On the [Releases](https://github.com/infinitered/reactotron/releases?q=reactotro
- [**React Native iOS**](https://docs.infinite.red/reactotron/troubleshooting/#react-native-ios)
- [**React Native Android**](https://docs.infinite.red/reactotron/troubleshooting/#react-native-android)

# Credits
## Credits

Reactotron is developed by [Infinite Red](https://infinite.red), [@rmevans9](https://github.com/rmevans9), and 70+ amazing contributors! Special thanks to [@skellock](https://github.com/skellock) for originally creating Reactotron while at Infinite Red.

# Premium Support
## Premium Support

[Reactotron](https://infinite.red/reactotron), as an open source project, is free to use and always will be. [Infinite Red](https://infinite.red/) offers premium React and [React Native](https://infinite.red/react-native) mobile app design/development services. Email us at [hello@infinite.red](mailto:hello@infinite.red) to get in touch for more details.
88 changes: 88 additions & 0 deletions apps/example-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# 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
ios/.xcode.env.local

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

# node.js
#
node_modules/
npm-debug.log
yarn-error.log

# BUCK
buck-out/
\.buckd/
*.keystore
!debug.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
**/fastlane/test_output

# Bundle artifact
*.jsbundle

# Ignite-specific items below
# You can safely replace everything above this comment with whatever is
# in the default .gitignore generated by React-Native CLI

# VS Code
.vscode

# Expo
.expo/*
bin/Exponent.app
/android
/ios

## Secrets
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/

# Configurations
!env.js

/coverage
6 changes: 6 additions & 0 deletions apps/example-app/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
ios
android
.vscode
ignite/ignite.json
package.json
11 changes: 11 additions & 0 deletions apps/example-app/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import App from "./app/app"
import React from "react"
import * as SplashScreen from "expo-splash-screen"

SplashScreen.preventAutoHideAsync()

function IgniteApp() {
return <App hideSplashScreen={SplashScreen.hideAsync} />
}

export default IgniteApp
16 changes: 16 additions & 0 deletions apps/example-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Welcome to the Reactotron Example App

The sole purpose of this app is to aid in developing Reactotron. It contains an example configuration and code for exercising the functionality of Reactotron's packages.

The example app was generated with [Ignite](https://github.com/infinitered/ignite); the boilerplate that [Infinite Red](https://infinite.red) uses as a way to test bleeding-edge changes to our React Native stack.

## Quick Start

:::info
Before you start, run `yarn` in the root directory of the repo to make sure all of the dependencies have been installed successfully.
:::

1. From the parent directory, run `yarn build && yarn start` This will build the latest version of Reactotron and open it.
2. From the parent directory, run `yarn start:example` or inside of example app directory `yarn start`. (Check the example app's `package.json` for additional options.)
3. Select the host platform you'd like to build for.
4. Once the build has completed, there should be a connection on the home screen of Reactotron from the example app.
77 changes: 77 additions & 0 deletions apps/example-app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"name": "example-app",
"displayName": "example-app",
"expo": {
"name": "example-app",
"slug": "example-app",
"scheme": "example-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/app-icon-all.png",
"splash": {
"image": "./assets/images/splash-logo-all.png",
"resizeMode": "contain",
"backgroundColor": "#191015"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"jsEngine": "hermes",
"assetBundlePatterns": [
"**/*"
],
"android": {
"icon": "./assets/images/app-icon-android-legacy.png",
"package": "com.exampleapp",
"adaptiveIcon": {
"foregroundImage": "./assets/images/app-icon-android-adaptive-foreground.png",
"backgroundImage": "./assets/images/app-icon-android-adaptive-background.png"
},
"splash": {
"image": "./assets/images/splash-logo-android-universal.png",
"resizeMode": "contain",
"backgroundColor": "#191015"
}
},
"ios": {
"icon": "./assets/images/app-icon-ios.png",
"supportsTablet": true,
"bundleIdentifier": "com.exampleapp",
"splash": {
"image": "./assets/images/splash-logo-ios-mobile.png",
"tabletImage": "./assets/images/splash-logo-ios-tablet.png",
"resizeMode": "contain",
"backgroundColor": "#191015"
}
},
"web": {
"favicon": "./assets/images/app-icon-web-favicon.png",
"splash": {
"image": "./assets/images/splash-logo-web.png",
"resizeMode": "contain",
"backgroundColor": "#191015"
},
"bundler": "metro"
},
"plugins": [
"expo-localization",
[
"expo-build-properties",
{
"ios": {
"newArchEnabled": false
},
"android": {
"newArchEnabled": false
}
}
]
],
"experiments": {
"tsconfigPaths": true
}
},
"ignite": {
"version": "9.4.0"
}
}
117 changes: 117 additions & 0 deletions apps/example-app/app/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/* eslint-disable import/first */
/**
* Welcome to the main entry point of the app. In this file, we'll
* be kicking off our app.
*
* Most of this file is boilerplate and you shouldn't need to modify
* it very often. But take some time to look through and understand
* what is going on here.
*
* The app navigation resides in ./app/navigators, so head over there
* if you're interested in adding screens and navigators.
*/
if (__DEV__) {
// Load Reactotron configuration in development. We don't want to
// include this in our production bundle, so we are using `if (__DEV__)`
// to only execute this in development.
require("./devtools/ReactotronConfig.ts")
}
import "./i18n"
import "./utils/ignoreWarnings"
import { useFonts } from "expo-font"
import React from "react"
import { initialWindowMetrics, SafeAreaProvider } from "react-native-safe-area-context"
import * as Linking from "expo-linking"
import { useInitialRootStore } from "./models"
import { AppNavigator, useNavigationPersistence } from "./navigators"
import { ErrorBoundary } from "./screens/ErrorScreen/ErrorBoundary"
import * as storage from "./utils/storage"
import { customFontsToLoad } from "./theme"
import Config from "./config"
import { GestureHandlerRootView } from "react-native-gesture-handler"
import { ViewStyle } from "react-native"

export const NAVIGATION_PERSISTENCE_KEY = "NAVIGATION_STATE"

// Web linking configuration
const prefix = Linking.createURL("/")
const config = {
screens: {
Login: {
path: "",
},
Welcome: "welcome",
Demo: {
screens: {
DemoShowroom: {
path: "showroom/:queryIndex?/:itemIndex?",
},
DemoDebug: "debug",
DemoPodcastList: "podcast",
DemoCommunity: "community",
},
},
},
}

interface AppProps {
hideSplashScreen: () => Promise<boolean>
}

/**
* This is the root component of our app.
*/
function App(props: AppProps) {
const { hideSplashScreen } = props
const {
initialNavigationState,
onNavigationStateChange,
isRestored: isNavigationStateRestored,
} = useNavigationPersistence(storage, NAVIGATION_PERSISTENCE_KEY)

const [areFontsLoaded] = useFonts(customFontsToLoad)

const { rehydrated } = useInitialRootStore(() => {
// This runs after the root store has been initialized and rehydrated.

// If your initialization scripts run very fast, it's good to show the splash screen for just a bit longer to prevent flicker.
// Slightly delaying splash screen hiding for better UX; can be customized or removed as needed,
// Note: (vanilla Android) The splash-screen will not appear if you launch your app via the terminal or Android Studio. Kill the app and launch it normally by tapping on the launcher icon. https://stackoverflow.com/a/69831106
// Note: (vanilla iOS) You might notice the splash-screen logo change size. This happens in debug/development mode. Try building the app for release.
setTimeout(hideSplashScreen, 500)
})

// Before we show the app, we have to wait for our state to be ready.
// In the meantime, don't render anything. This will be the background
// color set in native by rootView's background color.
// In iOS: application:didFinishLaunchingWithOptions:
// In Android: https://stackoverflow.com/a/45838109/204044
// You can replace with your own loading component if you wish.
if (!rehydrated || !isNavigationStateRestored || !areFontsLoaded) return null

const linking = {
prefixes: [prefix],
config,
}

// otherwise, we're ready to render the app
return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
)
}

export default App

const $container: ViewStyle = {
flex: 1,
}

0 comments on commit c95e172

Please sign in to comment.