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

Ideal nav/workspaces order #30

Merged
merged 11 commits into from
Jan 22, 2024
2 changes: 1 addition & 1 deletion src/components/MultipleAvatars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ function MultipleAvatars({
<Avatar
source={icons[0].source}
size={size}
fill={icons[0].fill ?? theme.iconSuccessFill}
fill={icons[0].displayInDefaultIconColor ? undefined : (icons[0].fill ?? theme.iconSuccessFill)}
name={icons[0].name}
type={icons[0].type}
fallbackIcon={icons[0].fallbackIcon}
Expand Down
3 changes: 2 additions & 1 deletion src/components/OptionsSelector/optionsSelectorPropTypes.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
import sourcePropTypes from '@components/Image/sourcePropTypes';
import optionPropTypes from '@components/optionPropTypes';
import stylePropTypes from '@styles/stylePropTypes';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -139,7 +140,7 @@ const propTypes = {
nestedScrollEnabled: PropTypes.bool,

/** Left icon to display in TextInput */
textIconLeft: PropTypes.elementType,
textIconLeft: sourcePropTypes,
};

const defaultProps = {
Expand Down
15 changes: 10 additions & 5 deletions src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import usePermissions from '@hooks/usePermissions';
import {getPolicyMembersByIdWithoutCurrentUser} from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as App from '@userActions/App';
import ONYXKEYS from '@src/ONYXKEYS';
Expand All @@ -23,6 +24,8 @@ type ReportScreenIDSetterComponentProps = {

/** The report metadata */
reportMetadata: OnyxCollection<ReportMetadata>;

accountID?: number;
};

type ReportScreenIDSetterProps = ReportScreenIDSetterComponentProps & ReportScreenWrapperProps;
Expand Down Expand Up @@ -54,7 +57,7 @@ const getLastAccessedReportID = (
};

// This wrapper is reponsible for opening the last accessed report if there is no reportID specified in the route params
function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, navigation, isFirstTimeNewExpensifyUser = false, reportMetadata}: ReportScreenIDSetterProps) {
function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, navigation, isFirstTimeNewExpensifyUser = false, reportMetadata, accountID}: ReportScreenIDSetterProps) {
const {canUseDefaultRooms} = usePermissions();
const {activeWorkspaceID} = useActiveWorkspace();

Expand All @@ -70,9 +73,7 @@ function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, nav
return;
}

const policyMemberAccountIDs = policyMembers
? Object.keys(policyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${activeWorkspaceID}`] ?? {}).map((accountID) => Number(accountID))
: [];
const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policyMembers, activeWorkspaceID, accountID);

// If there is no reportID in route, try to find last accessed and use it for setParams
const reportID = getLastAccessedReportID(
Expand All @@ -93,7 +94,7 @@ function ReportScreenIDSetter({route, reports, policies, policyMembers = {}, nav
} else {
App.confirmReadyToOpenApp();
}
}, [route, navigation, reports, canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, reportMetadata, activeWorkspaceID, policyMembers]);
}, [route, navigation, reports, canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, reportMetadata, activeWorkspaceID, policyMembers, accountID]);

// The ReportScreen without the reportID set will display a skeleton
// until the reportID is loaded and set in the route param
Expand Down Expand Up @@ -125,4 +126,8 @@ export default withOnyx<ReportScreenIDSetterProps, ReportScreenIDSetterComponent
key: ONYXKEYS.COLLECTION.REPORT_METADATA,
allowStaleData: true,
},
accountID: {
key: ONYXKEYS.SESSION,
selector: (session) => session?.accountID,
},
})(ReportScreenIDSetter);
14 changes: 13 additions & 1 deletion src/libs/Navigation/linkingConfig/customGetPathFromState.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import {getPathFromState} from '@react-navigation/native';
import _ from 'lodash';
import getPolicyIdFromState from '@libs/Navigation/getPolicyIdFromState';
import getTopmostBottomTabRoute from '@libs/Navigation/getTopmostBottomTabRoute';
import type {RootStackParamList, State} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';

const removePolicyIDParamFromState = (state: State<RootStackParamList>) => {
const stateCopy = _.cloneDeep(state);
const bottomTabRoute = getTopmostBottomTabRoute(stateCopy);
if (bottomTabRoute?.name === SCREENS.HOME && bottomTabRoute?.params && 'policyID' in bottomTabRoute?.params) {
delete bottomTabRoute.params.policyID;
}
return stateCopy;
};

const customGetPathFromState: typeof getPathFromState = (state, options) => {
const path = getPathFromState(state, options);
const stateWithoutPolicyID = removePolicyIDParamFromState(state as State<RootStackParamList>);
// For the Home page we should remove policyID from the params,
const path = getPathFromState(stateWithoutPolicyID, options);
const policyIDFromState = getPolicyIdFromState(state as State<RootStackParamList>);
const isWorkspaceSettingsOpened = getTopmostBottomTabRoute(state as State<RootStackParamList>)?.name === SCREENS.WORKSPACE.INITIAL && path.includes('workspace');
return `${policyIDFromState && !isWorkspaceSettingsOpened ? `/w/${policyIDFromState}` : ''}${path}`;
Expand Down
10 changes: 9 additions & 1 deletion src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Str from 'expensify-common/lib/str';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetailsList, Policy, PolicyMembers, PolicyTag, PolicyTags} from '@src/types/onyx';
import type {PersonalDetailsList, Policy, PolicyMember, PolicyMembers, PolicyTag, PolicyTags} from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

Expand Down Expand Up @@ -203,6 +203,13 @@ const extractPolicyIDFromPath = (path: string) => path.match(/\/w\/([a-zA-Z0-9]+

const getPathWithoutPolicyID = (path: string) => path.replace(/\/w\/[a-zA-Z0-9]+(\/|$)/, '/');

const getPolicyMembersByIdWithoutCurrentUser = (policyMembers: OnyxCollection<PolicyMember>, currentPolicyID?: string, currentUserAccountID?: number) =>
policyMembers
? Object.keys(policyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${currentPolicyID}`] ?? {})
.map((policyMemberAccountID) => Number(policyMemberAccountID))
.filter((policyMemberAccountID) => policyMemberAccountID !== currentUserAccountID)
: [];
Comment on lines +207 to +211

Choose a reason for hiding this comment

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

Do we have to use the if/else here? TS doesn't allow policyMembers to be null/undefined.


export {
getActivePolicies,
hasPolicyMemberError,
Expand All @@ -226,4 +233,5 @@ export {
isPaidGroupPolicy,
extractPolicyIDFromPath,
getPathWithoutPolicyID,
getPolicyMembersByIdWithoutCurrentUser,
};
31 changes: 24 additions & 7 deletions src/pages/WorkspaceSwitcherPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import WorkspaceCardCreateAWorkspace from './workspace/card/WorkspaceCardCreateAWorkspace';

const sortWorkspacesBySelected = (workspace1, workspace2, selectedWorkspaceID) => {
if (workspace1.policyID === selectedWorkspaceID) {
return -1;
}
if (workspace2.policyID === selectedWorkspaceID) {
return 1;
}
return workspace1.text.toLowerCase().localeCompare(workspace2.text.toLowerCase());
};

const propTypes = {
/** The list of this user's policies */
policies: PropTypes.objectOf(
Expand Down Expand Up @@ -140,20 +150,25 @@ function WorkspaceSwitcherPage({policies}) {
boldStyle: hasUnreadData(policy.id),
keyForList: policy.id,
}))
.sortBy((policy) => policy.text.toLowerCase())
.value(),
[policies, getIndicatorTypeForPolicy, hasUnreadData],
);

const filteredUserWorkspaces = useMemo(() => _.filter(usersWorkspaces, (policy) => policy.text.toLowerCase().includes(searchTerm.toLowerCase())), [searchTerm, usersWorkspaces]);
const filteredAndSortedUserWorkspaces = useMemo(
() =>
_.filter(usersWorkspaces, (policy) => policy.text.toLowerCase().includes(searchTerm.toLowerCase())).sort((policy1, policy2) =>
sortWorkspacesBySelected(policy1, policy2, activeWorkspaceID),
),
[searchTerm, usersWorkspaces],
);

const usersWorkspacesSectionData = useMemo(
() => ({
data: filteredUserWorkspaces,
data: filteredAndSortedUserWorkspaces,
shouldShow: true,
indexOffset: 0,
}),
[filteredUserWorkspaces],
[filteredAndSortedUserWorkspaces],
);

const everythingSection = useMemo(() => {
Expand All @@ -164,6 +179,7 @@ function WorkspaceSwitcherPage({policies}) {
source: Expensicons.ExpensifyAppIcon,
name: EXPENSIFY_TITLE,
type: CONST.ICON_TYPE_AVATAR,
displayInDefaultIconColor: true,
},
],
brickRoadIndicator: getIndicatorTypeForPolicy(undefined),
Expand All @@ -182,12 +198,13 @@ function WorkspaceSwitcherPage({policies}) {
</View>
<View>
<OptionRow
option={{...option, brickRoadIndicator: option.policyID === activeWorkspaceID ? undefined : option.brickRoadIndicator}}
option={{...option, brickRoadIndicator: !activeWorkspaceID ? undefined : option.brickRoadIndicator}}
onSelectRow={selectPolicy}
showTitleTooltip={false}
shouldShowSubscript={false}
highlightSelected
isSelected={option.policyID === activeWorkspaceID}
isSelected={!activeWorkspaceID}
optionIsFocused={!activeWorkspaceID}
/>
</View>
</>
Expand Down Expand Up @@ -237,7 +254,7 @@ function WorkspaceSwitcherPage({policies}) {
highlightSelectedOptions
shouldShowOptions
autoFocus={false}
disableFocusOptions
disableFocusOptions={!activeWorkspaceID}
canSelectMultipleOptions={false}
shouldShowSubscript={false}
showTitleTooltip={false}
Expand Down
21 changes: 19 additions & 2 deletions src/pages/home/sidebar/SidebarLinksData.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import _ from 'underscore';
import networkPropTypes from '@components/networkPropTypes';
import {withNetwork} from '@components/OnyxProvider';
import withCurrentReportID from '@components/withCurrentReportID';
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
import withNavigationFocus from '@components/withNavigationFocus';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import {getPolicyMembersByIdWithoutCurrentUser} from '@libs/PolicyUtils';
import SidebarUtils from '@libs/SidebarUtils';
import reportPropTypes from '@pages/reportPropTypes';
import * as Policy from '@userActions/Policy';
Expand Down Expand Up @@ -72,12 +74,26 @@ const defaultProps = {
policyMembers: {},
};

function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingApp, onLinkClick, policies, priorityMode, network, policyMembers}) {
function SidebarLinksData({
isFocused,
allReportActions,
betas,
chatReports,
currentReportID,
insets,
isLoadingApp,
onLinkClick,
policies,
priorityMode,
network,
policyMembers,
session: {accountID},
}) {
const styles = useThemeStyles();
const {activeWorkspaceID} = useActiveWorkspace();
const {translate} = useLocalize();

const policyMemberAccountIDs = _.map(_.keys(policyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${activeWorkspaceID}`] ?? {}), (accountID) => Number(accountID));
const policyMemberAccountIDs = getPolicyMembersByIdWithoutCurrentUser(policyMembers, activeWorkspaceID, accountID);

// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => Policy.openWorkspace(activeWorkspaceID, policyMemberAccountIDs), [activeWorkspaceID]);
Expand Down Expand Up @@ -229,6 +245,7 @@ const policySelector = (policy) =>

export default compose(
withCurrentReportID,
withCurrentUserPersonalDetails,
withNavigationFocus,
withNetwork(),
withOnyx({
Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/OnyxCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type Icon = {

/** Fill color of the icon */
fill?: string;

/** Icon should be displayed in its own color */
displayInDefaultIconColor?: boolean;
kosmydel marked this conversation as resolved.
Show resolved Hide resolved
};

export type {Icon, PendingAction, PendingFields, ErrorFields, Errors, AvatarType};
Loading