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

Gyroscope-driven animations of empty chats #23737

Merged
merged 31 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5677c9c
Gyroscope
wojtus7 Jul 11, 2023
a88ddb6
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Jul 26, 2023
ca0fb68
Make animations better (I think)
wojtus7 Jul 27, 2023
311ba60
Revert changes
wojtus7 Jul 27, 2023
95bc009
Add new line
wojtus7 Jul 27, 2023
b8dc279
Add permissions for android
wojtus7 Jul 27, 2023
fe804f9
Lint
wojtus7 Jul 27, 2023
4eb50dc
Prettier
wojtus7 Jul 27, 2023
fa2d7de
Return props
wojtus7 Jul 27, 2023
7520ffe
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Aug 2, 2023
06c0786
Add mocks in reanimated patch to fix tests
wojtus7 Aug 2, 2023
ae0469b
Test of reanimated 3.4.2 to see if CI works
wojtus7 Aug 3, 2023
712c340
Use reanimated 3.4.2
wojtus7 Aug 4, 2023
a84745d
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Aug 4, 2023
8d133f0
Improvements
wojtus7 Aug 8, 2023
5cf9633
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Aug 8, 2023
2952c0b
Revert change of cocoapods version
wojtus7 Aug 8, 2023
353ac37
Remove animation boost
wojtus7 Aug 10, 2023
bab35a7
Create AnimatedEmptyStateBackground
wojtus7 Aug 10, 2023
e086a59
Remove redundant isSmallScreenWidth prop
wojtus7 Aug 10, 2023
4da5ddd
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Aug 11, 2023
09480c1
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Aug 23, 2023
9d58b64
Merge remote-tracking branch 'upstream/main' into gyroscope
wojtus7 Sep 4, 2023
8051ce2
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Sep 12, 2023
a750eec
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Sep 15, 2023
5ecaef9
Fix types
wojtus7 Sep 15, 2023
1289ebd
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Sep 20, 2023
ded2f0b
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Sep 25, 2023
0f7a852
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Sep 25, 2023
d9bd159
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Sep 27, 2023
bb74a0c
Merge remote-tracking branch 'origin/main' into gyroscope
wojtus7 Oct 3, 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
1 change: 1 addition & 0 deletions android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning">
<meta-data
android:name="firebase_performance_logcat_enabled"
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>

<!-- android:hardwareAccelerated is essential for Android performance: https://developer.android.com/topic/performance/hardware-accel -->
<application
Expand Down
10 changes: 3 additions & 7 deletions src/components/ReportActionItem/MoneyReportView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {View, Image} from 'react-native';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import reportPropTypes from '../../pages/reportPropTypes';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
Expand All @@ -13,8 +13,8 @@ import Icon from '../Icon';
import * as Expensicons from '../Icon/Expensicons';
import variables from '../../styles/variables';
import * as CurrencyUtils from '../../libs/CurrencyUtils';
import EmptyStateBackgroundImage from '../../../assets/images/empty-state_background-fade.png';
import useLocalize from '../../hooks/useLocalize';
import AnimatedEmptyStateBackground from '../../pages/home/report/AnimatedEmptyStateBackground';
import SpacerView from '../SpacerView';

const propTypes = {
Expand All @@ -35,11 +35,7 @@ function MoneyReportView(props) {
return (
<View>
<View style={[StyleUtils.getReportWelcomeContainerStyle(props.isSmallScreenWidth), StyleUtils.getMinimumHeight(CONST.EMPTY_STATE_BACKGROUND.MONEY_REPORT.MIN_HEIGHT)]}>
<Image
pointerEvents="none"
source={EmptyStateBackgroundImage}
style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
/>
<AnimatedEmptyStateBackground />
</View>
<View style={[styles.flexRow, styles.menuItemTextContainer, styles.pointerEventsNone, styles.containerWithSpaceBetween, styles.ph5, styles.pv2]}>
<View style={[styles.flex1, styles.justifyContentCenter]}>
Expand Down
9 changes: 2 additions & 7 deletions src/components/ReportActionItem/MoneyRequestView.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ import CONST from '../../CONST';
import * as Expensicons from '../Icon/Expensicons';
import iouReportPropTypes from '../../pages/iouReportPropTypes';
import * as CurrencyUtils from '../../libs/CurrencyUtils';
import EmptyStateBackgroundImage from '../../../assets/images/empty-state_background-fade.png';
import useLocalize from '../../hooks/useLocalize';
import AnimatedEmptyStateBackground from '../../pages/home/report/AnimatedEmptyStateBackground';
import * as ReceiptUtils from '../../libs/ReceiptUtils';
import useWindowDimensions from '../../hooks/useWindowDimensions';
import transactionPropTypes from '../transactionPropTypes';
import Image from '../Image';
import Text from '../Text';
import Switch from '../Switch';
import ReportActionItemImage from './ReportActionItemImage';
Expand Down Expand Up @@ -138,11 +137,7 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should
return (
<View>
<View style={[StyleUtils.getReportWelcomeContainerStyle(isSmallScreenWidth), StyleUtils.getMinimumHeight(CONST.EMPTY_STATE_BACKGROUND.MONEY_REPORT.MIN_HEIGHT)]}>
<Image
pointerEvents="none"
source={EmptyStateBackgroundImage}
style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
/>
<AnimatedEmptyStateBackground />
Copy link
Contributor

Choose a reason for hiding this comment

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

The addition of AnimatedEmptyStateBackground caused a scrolling issue #29038 which we fixed in #29102

</View>

{hasReceipt && (
Expand Down
14 changes: 13 additions & 1 deletion src/libs/NumberUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ function generateHexadecimalValue(num: number): string {
return result.join('').toUpperCase();
}

/**
* Clamp a number in a range.
* This is a worklet so it should be used only from UI thread.

* @returns clamped value between min and max
*/
function clampWorklet(num: number, min: number, max: number): number {
'worklet';

return Math.min(Math.max(num, min), max);
}

/**
* Generates a random integer between a and b
* It's and equivalent of _.random(a, b)
Expand All @@ -59,4 +71,4 @@ function generateRandomInt(a: number, b: number): number {
return Math.floor(lower + Math.random() * (upper - lower + 1));
}

export {rand64, generateHexadecimalValue, generateRandomInt};
export {rand64, generateHexadecimalValue, generateRandomInt, clampWorklet};
47 changes: 47 additions & 0 deletions src/pages/home/report/AnimatedEmptyStateBackground.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import Animated, {SensorType, useAnimatedSensor, useAnimatedStyle, useSharedValue, withSpring} from 'react-native-reanimated';
import useWindowDimensions from '../../../hooks/useWindowDimensions';
import * as NumberUtils from '../../../libs/NumberUtils';
import EmptyStateBackgroundImage from '../../../../assets/images/empty-state_background-fade.png';
import * as StyleUtils from '../../../styles/StyleUtils';

const IMAGE_OFFSET_Y = 75;

function AnimatedEmptyStateBackground() {
const {windowWidth, isSmallScreenWidth} = useWindowDimensions();
const IMAGE_OFFSET_X = windowWidth / 2;

// Get data from phone rotation sensor and prep other variables for animation
const animatedSensor = useAnimatedSensor(SensorType.GYROSCOPE);
const xOffset = useSharedValue(0);
const yOffset = useSharedValue(0);

// Apply data to create style object
const animatedStyles = useAnimatedStyle(() => {
if (!isSmallScreenWidth) {
return {};
}
/*
* We use x and y gyroscope velocity and add it to position offset to move background based on device movements.
* Position the phone was in while entering the screen is the initial position for background image.
*/
const {x, y} = animatedSensor.sensor.value;
// The x vs y here seems wrong but is the way to make it feel right to the user
xOffset.value = NumberUtils.clampWorklet(xOffset.value + y, -IMAGE_OFFSET_X, IMAGE_OFFSET_X);
yOffset.value = NumberUtils.clampWorklet(yOffset.value - x, -IMAGE_OFFSET_Y, IMAGE_OFFSET_Y);
return {
transform: [{translateX: withSpring(-IMAGE_OFFSET_X - xOffset.value)}, {translateY: withSpring(yOffset.value)}],
};
});

return (
<Animated.Image
pointerEvents="none"
source={EmptyStateBackgroundImage}
style={[StyleUtils.getReportWelcomeBackgroundImageStyle(isSmallScreenWidth), animatedStyles]}
/>
);
}

AnimatedEmptyStateBackground.displayName = 'AnimatedEmptyStateBackground';
export default AnimatedEmptyStateBackground;
10 changes: 3 additions & 7 deletions src/pages/home/report/ReportActionItemCreated.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {memo} from 'react';
import {View, Image} from 'react-native';
import {View} from 'react-native';
import lodashGet from 'lodash/get';
import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
Expand All @@ -11,14 +11,14 @@ import styles from '../../../styles/styles';
import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
import * as Report from '../../../libs/actions/Report';
import reportPropTypes from '../../reportPropTypes';
import EmptyStateBackgroundImage from '../../../../assets/images/empty-state_background-fade.png';
import * as StyleUtils from '../../../styles/StyleUtils';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
import compose from '../../../libs/compose';
import withLocalize from '../../../components/withLocalize';
import PressableWithoutFeedback from '../../../components/Pressable/PressableWithoutFeedback';
import MultipleAvatars from '../../../components/MultipleAvatars';
import CONST from '../../../CONST';
import AnimatedEmptyStateBackground from './AnimatedEmptyStateBackground';

const propTypes = {
/** The id of the report */
Expand Down Expand Up @@ -64,11 +64,7 @@ function ReportActionItemCreated(props) {
needsOffscreenAlphaCompositing
>
<View style={StyleUtils.getReportWelcomeContainerStyle(props.isSmallScreenWidth)}>
<Image
pointerEvents="none"
source={EmptyStateBackgroundImage}
style={StyleUtils.getReportWelcomeBackgroundImageStyle(props.isSmallScreenWidth)}
/>
<AnimatedEmptyStateBackground />
<View
accessibilityLabel={props.translate('accessibilityHints.chatWelcomeMessage')}
style={[styles.p5, StyleUtils.getReportWelcomeTopMarginStyle(props.isSmallScreenWidth)]}
Expand Down
2 changes: 1 addition & 1 deletion src/styles/StyleUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ function getReportWelcomeBackgroundImageStyle(isSmallScreenWidth: boolean): View
if (isSmallScreenWidth) {
return {
height: CONST.EMPTY_STATE_BACKGROUND.SMALL_SCREEN.IMAGE_HEIGHT,
width: '100%',
width: '200%',
position: 'absolute',
};
}
Expand Down
Loading