Skip to content

Commit

Permalink
Merge branch 'Expensify:main' into arrow-feature-signed
Browse files Browse the repository at this point in the history
  • Loading branch information
JediWattson authored Jan 16, 2023
2 parents c97a7dc + 8662d3d commit 5684e41
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 114 deletions.
7 changes: 7 additions & 0 deletions assets/emojis.js
Original file line number Diff line number Diff line change
Expand Up @@ -2259,6 +2259,13 @@ const emojis = [
'meeting',
'shake',
],
types: [
'🤝🏿',
'🤝🏾',
'🤝🏽',
'🤝🏼',
'🤝🏻',
],
},
{
name: 'pray',
Expand Down
14 changes: 7 additions & 7 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
Expand Up @@ -99,7 +99,7 @@
"react-native-image-picker": "^4.10.2",
"react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#6b5ab5110dc3ed554f8eafbc38d7d87c17147972",
"react-native-modal": "^13.0.0",
"react-native-onyx": "1.0.32",
"react-native-onyx": "1.0.35",
"react-native-pdf": "^6.6.2",
"react-native-performance": "^4.0.0",
"react-native-permissions": "^3.0.1",
Expand Down
3 changes: 1 addition & 2 deletions src/components/AddPlaidBankAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ class AddPlaidBankAccount extends React.Component {
if (!plaidBankAccounts.length) {
return (
<FullPageOfflineBlockingView>
{(!token || this.props.plaidData.isLoading)
&& (
{this.props.plaidData.isLoading && (
<View style={[styles.flex1, styles.alignItemsCenter, styles.justifyContentCenter]}>
<ActivityIndicator color={themeColors.spinner} size="large" />
</View>
Expand Down
2 changes: 1 addition & 1 deletion src/components/RoomHeaderAvatars.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const RoomHeaderAvatars = (props) => {
<>
<View
style={[
styles.roomHeaderAvatar,
...iconStyle,
styles.roomHeaderAvatarOverlay,
]}
/>
Expand Down
57 changes: 11 additions & 46 deletions src/libs/actions/Report.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Linking} from 'react-native';
import moment from 'moment';
import _ from 'underscore';
import lodashGet from 'lodash/get';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
Expand Down Expand Up @@ -1110,6 +1109,10 @@ function subscribeToNewActionEvent(reportID, callback) {
* @param {Object} action
*/
function showReportActionNotification(reportID, action) {
if (ReportActionsUtils.isDeletedAction(action)) {
return;
}

if (!ActiveClientManager.isClientTheLeader()) {
Log.info('[LOCAL_NOTIFICATION] Skipping notification because this client is not the leader');
return;
Expand Down Expand Up @@ -1153,6 +1156,12 @@ function showReportActionNotification(reportID, action) {
Navigation.navigate(ROUTES.getReportRoute(reportID));
},
});

// Notify the ReportActionsView that a new comment has arrived
if (reportID === newActionSubscriber.reportID) {
const isFromCurrentUser = action.actorAccountID === currentUserAccountID;
newActionSubscriber.callback(isFromCurrentUser, action.reportActionID);
}
}

/**
Expand All @@ -1164,51 +1173,6 @@ function clearIOUError(reportID) {
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {errorFields: {iou: null}});
}

// We are using this map to ensure actions are only handled once
const handledReportActions = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
initWithStoredValues: false,
callback: (actions, key) => {
// reportID can be derived from the Onyx key
const reportID = key.split('_')[1];
if (!reportID) {
return;
}

_.each(actions, (action) => {
if (lodashGet(handledReportActions, [reportID, action.sequenceNumber])) {
return;
}

if (ReportActionsUtils.isDeletedAction(action)) {
return;
}

if (!action.created) {
return;
}

// If we are past the deadline to notify for this comment don't do it
if (moment.utc(moment(action.created).unix() * 1000).isBefore(moment.utc().subtract(10, 'seconds'))) {
handledReportActions[reportID] = handledReportActions[reportID] || {};
handledReportActions[reportID][action.sequenceNumber] = true;
return;
}

// Notify the ReportActionsView that a new comment has arrived
if (reportID === newActionSubscriber.reportID) {
const isFromCurrentUser = action.actorAccountID === currentUserAccountID;
newActionSubscriber.callback(isFromCurrentUser, action.reportActionID);
}

showReportActionNotification(reportID, action);
handledReportActions[reportID] = handledReportActions[reportID] || {};
handledReportActions[reportID][action.sequenceNumber] = true;
});
},
});

export {
addComment,
addAttachment,
Expand Down Expand Up @@ -1240,4 +1204,5 @@ export {
clearIOUError,
getMaxSequenceNumber,
subscribeToNewActionEvent,
showReportActionNotification,
};
14 changes: 1 addition & 13 deletions src/libs/actions/Session/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,26 +55,14 @@ Onyx.connect({
function signOut() {
Log.info('Flushing logs before signing out', true, {}, true);

const optimisticData = [
{
onyxMethod: CONST.ONYX.METHOD.SET,
key: ONYXKEYS.SESSION,
value: null,
},
{
onyxMethod: CONST.ONYX.METHOD.SET,
key: ONYXKEYS.CREDENTIALS,
value: {},
},
];
API.write('LogOut', {
// Send current authToken because we will immediately clear it once triggering this command
authToken: NetworkStore.getAuthToken(),
partnerUserID: lodashGet(credentials, 'autoGeneratedLogin', ''),
partnerName: CONFIG.EXPENSIFY.PARTNER_NAME,
partnerPassword: CONFIG.EXPENSIFY.PARTNER_PASSWORD,
shouldRetry: false,
}, {optimisticData});
});

Timing.clearData();
}
Expand Down
52 changes: 17 additions & 35 deletions src/libs/actions/SignInRedirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@ import * as Localize from '../Localize';
import * as PersistedRequests from './PersistedRequests';
import NetworkConnection from '../NetworkConnection';

let currentActiveClients;
Onyx.connect({
key: ONYXKEYS.ACTIVE_CLIENTS,
callback: (val) => {
currentActiveClients = !val ? [] : val;
},
});

let currentPreferredLocale;
Onyx.connect({
key: ONYXKEYS.NVP_PREFERRED_LOCALE,
callback: val => currentPreferredLocale = val,
});

let currentIsOffline;
let currentShouldForceOffline;
Onyx.connect({
Expand All @@ -37,31 +23,27 @@ Onyx.connect({
* @param {String} errorMessage
*/
function clearStorageAndRedirect(errorMessage) {
const activeClients = currentActiveClients;
const preferredLocale = currentPreferredLocale;
const isOffline = currentIsOffline;
const shouldForceOffline = currentShouldForceOffline;
// Under certain conditions, there are key-values we'd like to keep in storage even when a user is logged out.
// We pass these into the clear() method in order to avoid having to reset them on a delayed tick and getting
// flashes of unwanted default state.
const keysToPreserve = [];
keysToPreserve.push(ONYXKEYS.NVP_PREFERRED_LOCALE);
keysToPreserve.push(ONYXKEYS.ACTIVE_CLIENTS);

// Clearing storage discards the authToken. This causes a redirect to the SignIn screen
Onyx.clear()
.then(() => {
if (preferredLocale) {
Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale);
}
if (activeClients && activeClients.length > 0) {
Onyx.set(ONYXKEYS.ACTIVE_CLIENTS, activeClients);
}
// After signing out, set ourselves as offline if we were offline before logging out and we are not forcing it.
// If we are forcing offline, ignore it while signed out, otherwise it would require a refresh because there's no way to toggle the switch to go back online while signed out.
if (currentIsOffline && !currentShouldForceOffline) {
keysToPreserve.push(ONYXKEYS.NETWORK);
}

// After signing out, set ourselves as offline if we were offline before logging out and we are not forcing it.
// If we are forcing offline, ignore it while signed out, otherwise it would require a refresh because there's no way to toggle the switch to go back online while signed out.
if (isOffline && !shouldForceOffline) {
Onyx.set(ONYXKEYS.NETWORK, {isOffline});
Onyx.clear(keysToPreserve)
.then(() => {
if (!errorMessage) {
return;
}

// `Onyx.clear` reinitialize the Onyx instance with initial values so use `Onyx.merge` instead of `Onyx.set`
if (errorMessage) {
Onyx.merge(ONYXKEYS.SESSION, {errors: {[DateUtils.getMicroseconds()]: Localize.translateLocal(errorMessage)}});
}
// `Onyx.clear` reinitializes the Onyx instance with initial values so use `Onyx.merge` instead of `Onyx.set`
Onyx.merge(ONYXKEYS.SESSION, {errors: {[DateUtils.getMicroseconds()]: Localize.translateLocal(errorMessage)}});
});
}

Expand Down
18 changes: 18 additions & 0 deletions src/libs/actions/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as Localize from '../Localize';
import * as Link from './Link';
import * as SequentialQueue from '../Network/SequentialQueue';
import PusherUtils from '../PusherUtils';
import * as Report from './Report';

let currentUserAccountID = '';
Onyx.connect({
Expand Down Expand Up @@ -256,6 +257,22 @@ function deletePaypalMeAddress() {
Growl.show(Localize.translateLocal('paymentsPage.deletePayPalSuccess'), CONST.GROWL.SUCCESS, 3000);
}

function triggerNotifications(onyxUpdates) {
_.each(onyxUpdates, (update) => {
if (!update.shouldNotify) {
return;
}

const reportID = update.key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, '');
const reportAction = _.chain(update.value)
.values()
.compact()
.first()
.value();
Report.showReportActionNotification(reportID, reportAction);
});
}

/**
* Initialize our pusher subscription to listen for user changes
*/
Expand All @@ -271,6 +288,7 @@ function subscribeToUserEvents() {
PusherUtils.subscribeToPrivateUserChannelEvent(Pusher.TYPE.ONYX_API_UPDATE, currentUserAccountID, (pushJSON) => {
SequentialQueue.getCurrentRequest().then(() => {
Onyx.update(pushJSON);
triggerNotifications(pushJSON);
});
});

Expand Down
1 change: 0 additions & 1 deletion src/pages/GetAssistancePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ const GetAssistancePage = props => (
onPress: () => Link.openExternalLink(CONST.NEWHELP_URL),
icon: Expensicons.QuestionMark,
shouldShowRightIcon: true,
iconFill: themeColors.success,
wrapperStyle: [styles.cardMenuItem],
},
]}
Expand Down
22 changes: 15 additions & 7 deletions src/pages/workspace/WorkspaceInvitePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class WorkspaceInvitePage extends React.Component {
selectedOptions: [],
userToInvite,
welcomeNote: this.getWelcomeNote(),
shouldDisableButton: false,
};
}

Expand All @@ -108,8 +109,13 @@ class WorkspaceInvitePage extends React.Component {
}

getExcludedUsers() {
const policyMemberList = _.keys(lodashGet(this.props, 'policyMemberList', {}));
return [...CONST.EXPENSIFY_EMAILS, ...policyMemberList];
const policyMemberList = lodashGet(this.props, 'policyMemberList', {});
const usersToExclude = _.filter(_.keys(policyMemberList), policyMember => (
this.props.network.isOffline
|| policyMemberList[policyMember].pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE
|| !_.isEmpty(policyMemberList[policyMember].errors)
));
return [...CONST.EXPENSIFY_EMAILS, ...usersToExclude];
}

/**
Expand Down Expand Up @@ -250,10 +256,12 @@ class WorkspaceInvitePage extends React.Component {
return;
}

const logins = _.map(this.state.selectedOptions, option => option.login);
const filteredLogins = _.uniq(_.compact(_.map(logins, login => login.toLowerCase().trim())));
Policy.addMembersToWorkspace(filteredLogins, this.state.welcomeNote || this.getWelcomeNote(), this.props.route.params.policyID);
Navigation.goBack();
this.setState({shouldDisableButton: true}, () => {
const logins = _.map(this.state.selectedOptions, option => option.login);
const filteredLogins = _.uniq(_.compact(_.map(logins, login => login.toLowerCase().trim())));
Policy.addMembersToWorkspace(filteredLogins, this.state.welcomeNote || this.getWelcomeNote(), this.props.route.params.policyID);
Navigation.goBack();
});
}

/**
Expand Down Expand Up @@ -331,7 +339,7 @@ class WorkspaceInvitePage extends React.Component {
/>
</View>
<FormAlertWithSubmitButton
isDisabled={!this.state.selectedOptions.length}
isDisabled={!this.state.selectedOptions.length || this.state.shouldDisableButton}
isAlertVisible={this.getShouldShowAlertPrompt()}
buttonText={this.props.translate('common.invite')}
onSubmit={this.inviteUser}
Expand Down
Loading

0 comments on commit 5684e41

Please sign in to comment.