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

🍒 Cherry pick PR #18293 to staging 🍒 #19800

Merged
merged 2 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001032001
versionName "1.3.20-1"
versionCode 1001032002
versionName "1.3.20-2"
}

splits {
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.3.20.1</string>
<string>1.3.20.2</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.3.20.1</string>
<string>1.3.20.2</string>
</dict>
</plist>
4 changes: 2 additions & 2 deletions 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": "new.expensify",
"version": "1.3.20-1",
"version": "1.3.20-2",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
24 changes: 17 additions & 7 deletions src/Expensify.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ const propTypes = {
roomName: PropTypes.string,
}),

/** Whether the app is waiting for the server's response to determine if a room is public */
isCheckingPublicRoom: PropTypes.bool,

...withLocalizePropTypes,
};

Expand All @@ -81,6 +84,7 @@ const defaultProps = {
updateAvailable: false,
isSidebarLoaded: false,
screenShareRequest: null,
isCheckingPublicRoom: true,
};

function Expensify(props) {
Expand All @@ -90,7 +94,7 @@ function Expensify(props) {
const [isSplashHidden, setIsSplashHidden] = useState(false);

const isAuthenticated = useMemo(() => Boolean(lodashGet(props.session, 'authToken', null)), [props.session]);
const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded);
const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded) && !props.isCheckingPublicRoom;
const shouldHideSplash = shouldInit && !isSplashHidden;

const initializeClient = () => {
Expand Down Expand Up @@ -151,10 +155,10 @@ function Expensify(props) {
appStateChangeListener.current = AppState.addEventListener('change', initializeClient);

// If the app is opened from a deep link, get the reportID (if exists) from the deep link and navigate to the chat report
Linking.getInitialURL().then((url) => Report.openReportFromDeepLink(url));
Linking.getInitialURL().then((url) => Report.openReportFromDeepLink(url, isAuthenticated));

// Open chat report from a deep link (only mobile native)
Linking.addEventListener('url', (state) => Report.openReportFromDeepLink(state.url));
Linking.addEventListener('url', (state) => Report.openReportFromDeepLink(state.url, isAuthenticated));

return () => {
if (!appStateChangeListener.current) {
Expand Down Expand Up @@ -193,10 +197,12 @@ function Expensify(props) {
</>
)}

<NavigationRoot
onReady={setNavigationReady}
authenticated={isAuthenticated}
/>
{!props.isCheckingPublicRoom && (
<NavigationRoot
onReady={setNavigationReady}
authenticated={isAuthenticated}
/>
)}

{shouldHideSplash && <SplashScreenHider onHide={onSplashHide} />}
</DeeplinkWrapper>
Expand All @@ -208,6 +214,10 @@ Expensify.defaultProps = defaultProps;
export default compose(
withLocalize,
withOnyx({
isCheckingPublicRoom: {
key: ONYXKEYS.IS_CHECKING_PUBLIC_ROOM,
initWithStoredValues: false,
},
session: {
key: ONYXKEYS.SESSION,
},
Expand Down
6 changes: 6 additions & 0 deletions src/ONYXKEYS.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ export default {
// Whether the auth token is valid
IS_TOKEN_VALID: 'isTokenValid',

// Whether we're checking if the room is public or not
IS_CHECKING_PUBLIC_ROOM: 'isCheckingPublicRoom',

// A map of the user's security group IDs they belong to in specific domains
MY_DOMAIN_SECURITY_GROUPS: 'myDomainSecurityGroups',

// Report ID of the last report the user viewed as anonymous user
LAST_OPENED_PUBLIC_ROOM_ID: 'lastOpenedPublicRoomID',
};
58 changes: 58 additions & 0 deletions src/components/AnonymousReportFooter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import {View, Text} from 'react-native';
import Button from './Button';
import AvatarWithDisplayName from './AvatarWithDisplayName';
import ExpensifyWordmark from './ExpensifyWordmark';
import compose from '../libs/compose';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import reportPropTypes from '../pages/reportPropTypes';
import CONST from '../CONST';
import styles from '../styles/styles';
import * as Session from '../libs/actions/Session';

const propTypes = {
/** The report currently being looked at */
report: reportPropTypes,

...windowDimensionsPropTypes,
...withLocalizePropTypes,
};

const defaultProps = {
report: {},
};

const AnonymousReportFooter = (props) => (
<View style={styles.anonymousRoomFooter}>
<View style={[styles.flexRow]}>
<AvatarWithDisplayName
report={props.report}
size={CONST.AVATAR_SIZE.MEDIUM}
isAnonymous
/>
</View>
<View style={[styles.flexRow, styles.alignItemsCenter]}>
<View style={styles.mr4}>
<View style={[props.isSmallScreenWidth ? styles.alignItemsStart : styles.alignItemsEnd]}>
<ExpensifyWordmark style={styles.anonymousRoomFooterLogo} />
</View>
<Text style={[styles.textNormal, styles.textWhite]}>{props.translate('anonymousReportFooter.logoTagline')}</Text>
</View>
<View style={styles.anonymousRoomFooterSignInButton}>
<Button
medium
success
text={props.translate('common.signIn')}
onPress={() => Session.signOutAndRedirectToSignIn()}
/>
</View>
</View>
</View>
);

AnonymousReportFooter.propTypes = propTypes;
AnonymousReportFooter.defaultProps = defaultProps;
AnonymousReportFooter.displayName = 'AnonymousReportFooter';

export default compose(withWindowDimensions, withLocalize)(AnonymousReportFooter);
16 changes: 11 additions & 5 deletions src/components/AvatarWithDisplayName.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import DisplayNames from './DisplayNames';
import compose from '../libs/compose';
import * as OptionsListUtils from '../libs/OptionsListUtils';
import Text from './Text';
import * as StyleUtils from '../styles/StyleUtils';

const propTypes = {
/** The report currently being looked at */
Expand All @@ -33,24 +34,29 @@ const propTypes = {
/** Personal details of all the users */
personalDetails: PropTypes.objectOf(participantPropTypes),

/** Whether if it's an unauthenticated user */
isAnonymous: PropTypes.bool,

...windowDimensionsPropTypes,
...withLocalizePropTypes,
};

const defaultProps = {
personalDetails: {},
policies: {},
report: null,
report: {},
isAnonymous: false,
size: CONST.AVATAR_SIZE.DEFAULT,
};

const AvatarWithDisplayName = (props) => {
const title = ReportUtils.getDisplayNameForParticipant(props.report.ownerEmail, true);
const title = props.isAnonymous ? props.report.displayName : ReportUtils.getDisplayNameForParticipant(props.report.ownerEmail, true);
const subtitle = ReportUtils.getChatRoomSubtitle(props.report);
const isExpenseReport = ReportUtils.isExpenseReport(props.report);
const icons = ReportUtils.getIcons(props.report, props.personalDetails, props.policies);
const ownerPersonalDetails = OptionsListUtils.getPersonalDetailsForLogins([props.report.ownerEmail], props.personalDetails);
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(ownerPersonalDetails, false);
const avatarContainerStyle = StyleUtils.getEmptyAvatarStyle(props.size) || styles.emptyAvatar;
return (
<View style={[styles.appContentHeaderTitle, styles.flex1]}>
{Boolean(props.report && title) && (
Expand All @@ -70,7 +76,7 @@ const AvatarWithDisplayName = (props) => {
source={icons[0].source}
type={icons[0].type}
name={icons[0].name}
containerStyles={props.size === CONST.AVATAR_SIZE.SMALL ? styles.emptyAvatarSmall : styles.emptyAvatar}
containerStyles={avatarContainerStyle}
/>
)}
<View style={[styles.flex1, styles.flexColumn, styles.ml3]}>
Expand All @@ -79,8 +85,8 @@ const AvatarWithDisplayName = (props) => {
displayNamesWithTooltips={displayNamesWithTooltips}
tooltipEnabled
numberOfLines={1}
textStyles={[styles.headerText, styles.pre]}
shouldUseFullTitle={isExpenseReport}
textStyles={[props.isAnonymous ? styles.headerAnonymousFooter : styles.headerText, styles.pre]}
shouldUseFullTitle={isExpenseReport || props.isAnonymous}
/>
{!_.isEmpty(subtitle) && (
<Text
Expand Down
11 changes: 11 additions & 0 deletions src/components/ExpensifyWordmark.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import _ from 'underscore';
import ProductionLogo from '../../assets/images/expensify-wordmark.svg';
import DevLogo from '../../assets/images/expensify-logo--dev.svg';
import StagingLogo from '../../assets/images/expensify-logo--staging.svg';
Expand All @@ -14,10 +16,17 @@ import * as StyleUtils from '../styles/StyleUtils';
import variables from '../styles/variables';

const propTypes = {
/** Additional styles to add to the component */
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),

...environmentPropTypes,
...windowDimensionsPropTypes,
};

const defaultProps = {
style: {},
};

const logoComponents = {
[CONST.ENVIRONMENT.DEV]: DevLogo,
[CONST.ENVIRONMENT.STAGING]: StagingLogo,
Expand All @@ -34,6 +43,7 @@ const ExpensifyWordmark = (props) => {
StyleUtils.getSignInWordmarkWidthStyle(props.environment, props.isSmallScreenWidth),
StyleUtils.getHeight(props.isSmallScreenWidth ? variables.signInLogoHeightSmallScreen : variables.signInLogoHeight),
props.isSmallScreenWidth && (props.environment === CONST.ENVIRONMENT.DEV || props.environment === CONST.ENVIRONMENT.STAGING) ? styles.ml3 : {},
...(_.isArray(props.style) ? props.style : [props.style]),
]}
>
<LogoComponent fill={themeColors.success} />
Expand All @@ -43,5 +53,6 @@ const ExpensifyWordmark = (props) => {
};

ExpensifyWordmark.displayName = 'ExpensifyWordmark';
ExpensifyWordmark.defaultProps = defaultProps;
ExpensifyWordmark.propTypes = propTypes;
export default compose(withEnvironment, withWindowDimensions)(ExpensifyWordmark);
3 changes: 2 additions & 1 deletion src/components/Reactions/AddReactionBubble.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import getButtonState from '../../libs/getButtonState';
import * as EmojiPickerAction from '../../libs/actions/EmojiPickerAction';
import variables from '../../styles/variables';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import * as Session from '../../libs/actions/Session';

const propTypes = {
/** Whether it is for context menu so we can modify its style */
Expand Down Expand Up @@ -70,7 +71,7 @@ const AddReactionBubble = (props) => {
<Pressable
ref={ref}
style={({hovered, pressed}) => [styles.emojiReactionBubble, styles.userSelectNone, StyleUtils.getEmojiReactionBubbleStyle(hovered || pressed, false, props.isContextMenu)]}
onPress={onPress}
onPress={Session.checkIfActionIsAllowed(onPress)}
// Prevent text input blur when Add reaction is clicked
onMouseDown={(e) => e.preventDefault()}
>
Expand Down
5 changes: 3 additions & 2 deletions src/components/Reactions/MiniQuickEmojiReactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import compose from '../../libs/compose';
import ONYXKEYS from '../../ONYXKEYS';
import * as EmojiUtils from '../../libs/EmojiUtils';
import * as Session from '../../libs/actions/Session';

const propTypes = {
...baseQuickEmojiReactionsPropTypes,
Expand Down Expand Up @@ -65,14 +66,14 @@ const MiniQuickEmojiReactions = (props) => {
key={emoji.name}
isDelayButtonStateComplete={false}
tooltipText={`:${emoji.name}:`}
onPress={() => props.onEmojiSelected(emoji)}
onPress={Session.checkIfActionIsAllowed(() => props.onEmojiSelected(emoji))}
>
<Text style={[styles.miniQuickEmojiReactionText, styles.userSelectNone]}>{EmojiUtils.getPreferredEmojiCode(emoji, props.preferredSkinTone)}</Text>
</BaseMiniContextMenuItem>
))}
<BaseMiniContextMenuItem
ref={ref}
onPress={openEmojiPicker}
onPress={Session.checkIfActionIsAllowed(openEmojiPicker)}
isDelayButtonStateComplete={false}
tooltipText={props.translate('emojiReactions.addReactionTooltip')}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import styles from '../../../styles/styles';
import ONYXKEYS from '../../../ONYXKEYS';
import Tooltip from '../../Tooltip';
import * as EmojiUtils from '../../../libs/EmojiUtils';
import * as Session from '../../../libs/actions/Session';

const baseQuickEmojiReactionsPropTypes = {
/**
Expand Down Expand Up @@ -56,9 +57,7 @@ const BaseQuickEmojiReactions = (props) => (
<EmojiReactionBubble
emojiCodes={[EmojiUtils.getPreferredEmojiCode(emoji, props.preferredSkinTone)]}
isContextMenu
onPress={() => {
props.onEmojiSelected(emoji);
}}
onPress={Session.checkIfActionIsAllowed(() => props.onEmojiSelected(emoji))}
/>
</View>
</Tooltip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import compose from '../../libs/compose';
import Tooltip from '../Tooltip';
import {propTypes as videoChatButtonAndMenuPropTypes, defaultProps} from './videoChatButtonAndMenuPropTypes';
import * as Session from '../../libs/actions/Session';

const propTypes = {
/** Link to open when user wants to create a new google meet meeting */
Expand Down Expand Up @@ -103,7 +104,7 @@ class BaseVideoChatButtonAndMenu extends Component {
<Tooltip text={this.props.translate('videoChatButtonAndMenu.tooltip')}>
<Pressable
ref={(el) => (this.videoChatButton = el)}
onPress={() => {
onPress={Session.checkIfActionIsAllowed(() => {
// Drop focus to avoid blue focus ring.
this.videoChatButton.blur();

Expand All @@ -113,7 +114,7 @@ class BaseVideoChatButtonAndMenu extends Component {
return;
}
this.setMenuVisibility(true);
}}
})}
style={[styles.touchableButtonImage]}
>
<Icon
Expand Down
3 changes: 3 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ export default {
mi: 'mile',
km: 'kilometer',
},
anonymousReportFooter: {
logoTagline: 'Join in on the discussion.',
},
attachmentPicker: {
cameraPermissionRequired: 'Camera access',
expensifyDoesntHaveAccessToCamera: "Expensify can't take photos without access to your camera. Tap Settings to update permissions.",
Expand Down
3 changes: 3 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ export default {
mi: 'milla',
km: 'kilómetro',
},
anonymousReportFooter: {
logoTagline: 'Únete a la discussion.',
},
attachmentPicker: {
cameraPermissionRequired: 'Permiso para acceder a la cámara',
expensifyDoesntHaveAccessToCamera: 'Expensify no puede tomar fotos sin acceso a tu cámara. Haz click en Configuración para actualizar los permisos.',
Expand Down
Loading