Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance optimization #1676

Merged
merged 35 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a6188c8
upgrade sentry to support profiling monitoring
ansh Oct 3, 2023
cacf906
remove console logs in production builds
ansh Oct 3, 2023
ac5b479
feeds tab bar and bottom bar animation centralized
ansh Oct 4, 2023
a5b5b04
refactor FeedPage out of Home
ansh Oct 4, 2023
d3c2b02
add script to start in production mode
ansh Oct 4, 2023
427c483
move FAB inner to reanimated
ansh Oct 4, 2023
40af020
move FABInner back to `Animated` RN animation
ansh Oct 4, 2023
0a3fb10
add perf commands
ansh Oct 10, 2023
9e7d34e
add testing with Maestro and perf with Flashlight
ansh Oct 10, 2023
4995dda
Merge branch 'main' into performance-optimization-1
ansh Oct 10, 2023
0b15b5f
fix merge conflicts
ansh Oct 10, 2023
5ad826b
fix resourceClass name in eas.json
ansh Oct 10, 2023
9744e94
fix onEndReachedThreshold in Feed
ansh Oct 11, 2023
1cb537b
memoize styles
ansh Oct 11, 2023
48e26e4
go back to old styling for LoadLatestBtn
ansh Oct 12, 2023
84b07f7
Merge branch 'main' into performance-optimization-1
ansh Oct 12, 2023
c1543a7
remove reanimated code from useMinimalShellMode
ansh Oct 12, 2023
18265c0
move shell animations to hook/reanimated for perf
ansh Oct 12, 2023
bff08d7
fix empty state issue
ansh Oct 12, 2023
f436117
make shell animation feel smoother
ansh Oct 12, 2023
b75285a
make shell animation more smooth
ansh Oct 12, 2023
3364ac6
run animation with autorun
ansh Oct 13, 2023
281b274
specify keys for tab bar properly
ansh Oct 13, 2023
3a424ee
remove comments
ansh Oct 13, 2023
4b03d89
Merge branch 'main' into performance-optimization-1
ansh Oct 13, 2023
47e0ad4
remove already imported dep
ansh Oct 13, 2023
5926f29
fix lint
ansh Oct 13, 2023
db303d4
add testing instructions
ansh Oct 13, 2023
daca563
mock sentry-expo for jest
ansh Oct 13, 2023
79ae5da
fix jest mocks
ansh Oct 13, 2023
23c6964
Fix the load-latest button on desktop and tablet
pfrazee Oct 13, 2023
83bb06e
Fix: don't move the FAB in tablet mode
pfrazee Oct 13, 2023
078baf2
Fix type error
pfrazee Oct 13, 2023
834064a
Fix tabs bar positioning on tablet
pfrazee Oct 14, 2023
256230a
Fix types
pfrazee Oct 14, 2023
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ ios/
.env.*

# Firebase (Android) Google services
google-services.json
google-services.json

# Performance results (Flashlight)
.perf/
77 changes: 77 additions & 0 deletions __e2e__/maestro/scroll.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# flow.yaml

appId: xyz.blueskyweb.app
---
- launchApp
# Login
# - runFlow:
# when:
# - tapOn: "Sign In"
# - tapOn: "Username or email address"
# - inputText: "ansh.bsky.team"
# - tapOn: "Password"
# - inputText: "PASSWORd"
# - tapOn: "Next"
# Allow notifications if popup is visible
# - runFlow:
# when:
# visible: "Notifications"
# commands:
# - tapOn: "Allow"
# Scroll in main feed
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
# Swipe between feeds
- swipe:
direction: "LEFT"
- swipe:
direction: "LEFT"
- swipe:
direction: "LEFT"
- swipe:
direction: "RIGHT"
- swipe:
direction: "RIGHT"
- swipe:
direction: "RIGHT"
# Go to Notifications
- tapOn:
id: "viewHeaderDrawerBtn"
- tapOn: "Notifications"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- swipe:
direction: "DOWN" # Make header visible
# Go to Feeds tab
- tapOn:
id: "viewHeaderDrawerBtn"
- tapOn: "Feeds"
- scrollUntilVisible:
element: "Discover"
direction: UP
- tapOn: "Discover"
- waitForAnimationToEnd
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"
# Click on post
- tapOn:
id: "postText"
index: 0
- "scroll"
- "scroll"
- "scroll"
- "scroll"
- "scroll"

10 changes: 10 additions & 0 deletions __mocks__/sentry-expo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
jest.mock('sentry-expo', () => ({
init: () => jest.fn(),
Native: {
ReactNativeTracing: jest.fn().mockImplementation(() => ({
start: jest.fn(),
stop: jest.fn(),
})),
ReactNavigationInstrumentation: jest.fn(),
},
}))
5 changes: 5 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,10 @@ module.exports = function (api) {
],
'react-native-reanimated/plugin', // NOTE: this plugin MUST be last
],
env: {
production: {
plugins: ['transform-remove-console'],
},
},
}
}
14 changes: 14 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Testing instructions

### Using Maestro E2E tests
1. Install Maestro by following [these instuctions](https://maestro.mobile.dev/getting-started/installing-maestro). This will help us run the E2E tests.
2. You can write Maestro tests in `__e2e__/maestro` directory by creating a new `.yaml` file or by modifying an existing one.
3. You can also use [Maestro Studio](https://maestro.mobile.dev/getting-started/maestro-studio) which automatically generates commands by recording your actions on the app. Therefore, you can create realistic tests without having to manually write any code. Use the `maestro studio` command to start recording your actions.


### Using Flashlight for Performance Testing
1. Make sure Maestro is installed (optional: only for auomated testing) by following the instructions above
2. Install Flashlight by following [these instructions](https://docs.flashlight.dev/)
3. The simplest way to get started is by running `yarn perf:measure` which will run a live preview of the performance test results. You can [see a demo here](https://github.com/bamlab/flashlight/assets/4534323/4038a342-f145-4c3b-8cde-17949bf52612)
4. The `yarn perf:test:measure` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml` and give the results in `.perf/results.json` which can be viewed by running `yarn:perf:results`
5. You can also run your own tests by running `yarn perf:test <path_to_test>` where `<path_to_test>` is the path to your test file. For example, `yarn perf:test __e2e__/maestro/scroll.yaml` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml`.
8 changes: 4 additions & 4 deletions eas.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@
"distribution": "internal",
"ios": {
"simulator": true,
"resourceClass": "m-large"
"resourceClass": "large"
},
"channel": "development"
},
"development-device": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"resourceClass": "m-large"
"resourceClass": "large"
},
"channel": "development"
},
"preview": {
"distribution": "internal",
"ios": {
"resourceClass": "m-large"
"resourceClass": "large"
},
"channel": "preview"
},
"production": {
"ios": {
"resourceClass": "m-large"
"resourceClass": "large"
},
"channel": "production"
},
Expand Down
11 changes: 11 additions & 0 deletions jest/jestSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,14 @@ jest.mock('lande', () => ({
__esModule: true, // this property makes it work
default: jest.fn().mockReturnValue([['eng']]),
}))

jest.mock('sentry-expo', () => ({
init: () => jest.fn(),
Native: {
ReactNativeTracing: jest.fn().mockImplementation(() => ({
start: jest.fn(),
stop: jest.fn(),
})),
ReactNavigationInstrumentation: jest.fn(),
},
}))
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"web": "expo start --web",
"build-web": "expo export:web && node ./scripts/post-web-build.js && cp --verbose ./web-build/static/js/*.* ./bskyweb/static/js/",
"start": "expo start --dev-client",
"start:prod": "expo start --dev-client --no-dev --minify",
"clean-cache": "rm -rf node_modules/.cache/babel-loader/*",
"test": "jest --forceExit --testTimeout=20000 --bail",
"test-watch": "jest --watchAll",
Expand All @@ -22,6 +23,11 @@
"e2e:metro": "RN_SRC_EXT=e2e.ts,e2e.tsx expo run:ios",
"e2e:build": "detox build -c ios.sim.debug",
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all",
"perf:test": "maestro test",
"perf:test:run": "maestro test __e2e__/maestro/scroll.yaml",
"perf:test:measure": "flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json",
"perf:test:results": "flashlight report .perf/results.json",
"perf:measure": "flashlight measure",
"build:apk": "eas build -p android --profile dev-android-apk"
},
"dependencies": {
Expand Down Expand Up @@ -53,7 +59,7 @@
"@segment/analytics-react": "^1.0.0-rc1",
"@segment/analytics-react-native": "^2.10.1",
"@segment/sovran-react-native": "^0.4.5",
"@sentry/react-native": "5.5.0",
"@sentry/react-native": "5.10.0",
"@tanstack/react-query": "^4.33.0",
"@tiptap/core": "^2.0.0-beta.220",
"@tiptap/extension-document": "^2.0.0-beta.220",
Expand All @@ -71,6 +77,7 @@
"@zxing/text-encoding": "^0.9.0",
"array.prototype.findlast": "^1.2.3",
"await-lock": "^2.2.2",
"babel-plugin-transform-remove-console": "^6.9.4",
"base64-js": "^1.5.1",
"bcp-47-match": "^2.0.3",
"email-validator": "^2.0.4",
Expand Down Expand Up @@ -148,7 +155,7 @@
"react-native-web-linear-gradient": "^1.1.2",
"react-responsive": "^9.0.2",
"rn-fetch-blob": "^0.12.0",
"sentry-expo": "~7.0.0",
"sentry-expo": "~7.0.1",
"tippy.js": "^6.3.7",
"tlds": "^1.234.0",
"zeego": "^1.6.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js b/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
index 7e0b4cd..3fd7406 100644
index 7e0b4cd..177454c 100644
--- a/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
+++ b/node_modules/@sentry/react-native/dist/js/utils/ignorerequirecyclelogs.js
@@ -3,6 +3,8 @@ import { LogBox } from 'react-native';
Expand All @@ -12,3 +12,4 @@ index 7e0b4cd..3fd7406 100644
+ } catch (e) {}
}
//# sourceMappingURL=ignorerequirecyclelogs.js.map
\ No newline at end of file
66 changes: 45 additions & 21 deletions src/lib/hooks/useMinimalShellMode.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,60 @@
import React from 'react'
import {autorun} from 'mobx'
import {useStores} from 'state/index'
import {Animated} from 'react-native'
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
import {
Easing,
interpolate,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated'

export function useMinimalShellMode() {
const store = useStores()
const minimalShellInterp = useAnimatedValue(0)
const footerMinimalShellTransform = {
opacity: Animated.subtract(1, minimalShellInterp),
transform: [{translateY: Animated.multiply(minimalShellInterp, 50)}],
}
const minimalShellInterp = useSharedValue(0)
const footerMinimalShellTransform = useAnimatedStyle(() => {
return {
opacity: interpolate(minimalShellInterp.value, [0, 1], [1, 0]),
transform: [
{translateY: interpolate(minimalShellInterp.value, [0, 1], [0, 25])},
],
}
})
const headerMinimalShellTransform = useAnimatedStyle(() => {
return {
opacity: interpolate(minimalShellInterp.value, [0, 1], [1, 0]),
transform: [
{translateY: interpolate(minimalShellInterp.value, [0, 1], [0, -25])},
],
}
})
const fabMinimalShellTransform = useAnimatedStyle(() => {
return {
transform: [
{translateY: interpolate(minimalShellInterp.value, [0, 1], [-44, 0])},
],
}
})

React.useEffect(() => {
return autorun(() => {
if (store.shell.minimalShellMode) {
Animated.timing(minimalShellInterp, {
toValue: 1,
duration: 150,
useNativeDriver: true,
isInteraction: false,
}).start()
minimalShellInterp.value = withTiming(1, {
duration: 125,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
})
} else {
Animated.timing(minimalShellInterp, {
toValue: 0,
duration: 150,
useNativeDriver: true,
isInteraction: false,
}).start()
minimalShellInterp.value = withTiming(0, {
duration: 125,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
})
}
})
}, [minimalShellInterp, store])
}, [minimalShellInterp, store.shell.minimalShellMode])

return {footerMinimalShellTransform}
return {
footerMinimalShellTransform,
headerMinimalShellTransform,
fabMinimalShellTransform,
}
}
Loading