Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cc36d8f
feat: add product training tooltips and context management
ishpaul777 Nov 29, 2024
7c500da
feat: update product training tooltips and refactor context imports
ishpaul777 Nov 30, 2024
9de9bc7
feat: remove workspace tooltip from ReportScreen and ReportFooter, in…
ishpaul777 Nov 30, 2024
3fa81f2
tooltip for QAB
ishpaul777 Nov 30, 2024
cb8b8f6
remove unused import
ishpaul777 Nov 30, 2024
32530d1
Merge branch 'main' into product-training-tooltips
ishpaul777 Dec 4, 2024
ee9a380
format
ishpaul777 Dec 4, 2024
030070c
Merge branch 'migrated-user-welcome-modal' into product-training-tool…
ishpaul777 Dec 4, 2024
128411e
clean variable namings
ishpaul777 Dec 4, 2024
1df261f
remove unneccessary comment
ishpaul777 Dec 4, 2024
0122698
fix translations
ishpaul777 Dec 4, 2024
d1b92d3
refactor ProductTrainingContextProvider styles and dependencies
ishpaul777 Dec 5, 2024
7f2472f
Merge branch 'main' into product-training-tooltips
ishpaul777 Dec 5, 2024
163f6b0
Merge branch 'migrated-user-welcome-modal' into product-training-tool…
ishpaul777 Dec 5, 2024
9684fda
refactor tooltip visibility logic by removing unnecessary conditions
ishpaul777 Dec 5, 2024
0451ea1
depreaciate saved search ONYXKEY
ishpaul777 Dec 5, 2024
5fe13b3
remove unused onyx keys
ishpaul777 Dec 5, 2024
10b9ec4
Merge branch 'migrated-user-welcome-modal' into product-training-tool…
ishpaul777 Dec 6, 2024
117c0fa
Merge branch 'main' into product-training-tooltips
ishpaul777 Dec 8, 2024
3c2ed79
resolve conflcts
ishpaul777 Dec 8, 2024
903e30d
Remove unused NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER key and related logic
ishpaul777 Dec 8, 2024
a8c9a61
Refactor product training tooltip logic to improve registration and v…
ishpaul777 Dec 8, 2024
2600133
Refactor useProductTrainingContext to improve tooltip visibility logic
ishpaul777 Dec 9, 2024
0c573ab
Refactor ProductTrainingContext to enhance tooltip rendering and upda…
ishpaul777 Dec 9, 2024
dbdf43a
improve tooltip visibility conditions
ishpaul777 Dec 9, 2024
a3ea05c
fix typing as per review
ishpaul777 Dec 10, 2024
000e112
Merge branch 'main' into product-training-tooltips
ishpaul777 Dec 10, 2024
f7696fa
refactor: simplify shouldShow logic in PRODUCT_TRAINING_TOOLTIP_DATA
ishpaul777 Dec 10, 2024
0eab9dd
fix: update shouldShowEducationalTooltip logic to use ReportUtils for…
ishpaul777 Dec 10, 2024
f9ec91d
fix: update productTrainingTooltip translations for improved clarity …
ishpaul777 Dec 10, 2024
d4610b2
Merge branch 'main' into product-training-tooltips
ishpaul777 Dec 11, 2024
d8f9018
Refactor product training tooltips to support multi-part translations…
ishpaul777 Dec 11, 2024
971a11a
Refactor product training tooltip rendering and remove EducationalToo…
ishpaul777 Dec 11, 2024
39361a4
add api changes
ishpaul777 Dec 11, 2024
615e4ac
Update to include permissions check and update Spanish translations
ishpaul777 Dec 11, 2024
a8ab5c6
changes as per review
ishpaul777 Dec 12, 2024
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
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import KeyboardProvider from './components/KeyboardProvider';
import {LocaleContextProvider} from './components/LocaleContextProvider';
import OnyxProvider from './components/OnyxProvider';
import PopoverContextProvider from './components/PopoverProvider';
import {ProductTrainingContextProvider} from './components/ProductTrainingContext';
import SafeArea from './components/SafeArea';
import ScrollOffsetContextProvider from './components/ScrollOffsetContextProvider';
import {SearchRouterContextProvider} from './components/Search/SearchRouter/SearchRouterContext';
Expand Down Expand Up @@ -95,6 +96,7 @@ function App({url}: AppProps) {
VideoPopoverMenuContextProvider,
KeyboardProvider,
SearchRouterContextProvider,
ProductTrainingContextProvider,
]}
>
<CustomStatusBarAndBackground />
Expand Down
7 changes: 7 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6404,6 +6404,13 @@ const CONST = {
},

MIGRATED_USER_WELCOME_MODAL: 'migratedUserWelcomeModal',

PRODUCT_TRAINING_TOOLTIP_NAMES: {
CONCEIRGE_LHN_GBR: 'conciergeLHNGBR',
RENAME_SAVED_SEARCH: 'renameSavedSearch',
QUICK_ACTION_BUTTON: 'quickActionButton',
WORKSAPCE_CHAT_CREATE: 'workspaceChatCreate',
},
} as const;

type Country = keyof typeof CONST.ALL_COUNTRIES;
Expand Down
16 changes: 0 additions & 16 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,6 @@ const ONYXKEYS = {

/** NVP keys */

/** Boolean flag only true when first set */
NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER: 'nvp_isFirstTimeNewExpensifyUser',

/** This NVP contains list of at most 5 recent attendees */
NVP_RECENT_ATTENDEES: 'nvp_expensify_recentAttendees',

Expand Down Expand Up @@ -216,18 +213,9 @@ const ONYXKEYS = {
/** The end date (epoch timestamp) of the workspace owner’s grace period after the free trial ends. */
NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END: 'nvp_private_billingGracePeriodEnd',

/** The NVP containing all information related to educational tooltip in workspace chat */
NVP_WORKSPACE_TOOLTIP: 'workspaceTooltip',

/** The NVP containing the target url to navigate to when deleting a transaction */
NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL: 'nvp_deleteTransactionNavigateBackURL',

/** Whether to show save search rename tooltip */
SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP: 'shouldShowSavedSearchRenameTooltip',

/** Whether to hide gbr tooltip */
NVP_SHOULD_HIDE_GBR_TOOLTIP: 'nvp_should_hide_gbr_tooltip',

/** Does this user have push notifications enabled for this device? */
PUSH_NOTIFICATIONS_ENABLED: 'pushNotificationsEnabled',

Expand Down Expand Up @@ -876,7 +864,6 @@ type OnyxCollectionValuesMapping = {
type OnyxValuesMapping = {
[ONYXKEYS.ACCOUNT]: OnyxTypes.Account;
[ONYXKEYS.ACCOUNT_MANAGER_REPORT_ID]: string;
[ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER]: boolean;

// NVP_ONBOARDING is an array for old users.
[ONYXKEYS.NVP_ONBOARDING]: Onboarding | [];
Expand Down Expand Up @@ -1017,17 +1004,14 @@ type OnyxValuesMapping = {
[ONYXKEYS.NVP_BILLING_FUND_ID]: number;
[ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: number;
[ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END]: number;
[ONYXKEYS.NVP_WORKSPACE_TOOLTIP]: OnyxTypes.WorkspaceTooltip;
[ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL]: string | undefined;
[ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP]: boolean;
[ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[];
[ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE]: string;
[ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflowOnyx;
[ONYXKEYS.IMPORTED_SPREADSHEET]: OnyxTypes.ImportedSpreadsheet;
[ONYXKEYS.LAST_ROUTE]: string;
[ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY]: boolean | undefined;
[ONYXKEYS.IS_USING_IMPORTED_STATE]: boolean;
[ONYXKEYS.SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP]: boolean;
[ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES]: Record<string, string>;
[ONYXKEYS.CONCIERGE_REPORT_ID]: string;
[ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING]: OnyxTypes.DismissedProductTraining;
Expand Down
44 changes: 10 additions & 34 deletions src/components/LHNOptionsList/OptionRowLHN.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import MultipleAvatars from '@components/MultipleAvatars';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import {useSession} from '@components/OnyxProvider';
import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction';
import {useProductTrainingContext} from '@components/ProductTrainingContext';
import SubscriptAvatar from '@components/SubscriptAvatar';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
Expand All @@ -22,7 +23,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import DateUtils from '@libs/DateUtils';
import DomUtils from '@libs/DomUtils';
import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import Parser from '@libs/Parser';
import Performance from '@libs/Performance';
Expand All @@ -32,7 +32,6 @@ import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportA
import FreeTrial from '@pages/settings/Subscription/FreeTrial';
import variables from '@styles/variables';
import Timing from '@userActions/Timing';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
Expand All @@ -48,18 +47,19 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti

// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${optionItem?.reportID || -1}`);
const [isFirstTimeNewExpensifyUser] = useOnyx(ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER);
const [isOnboardingCompleted = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {
selector: hasCompletedGuidedSetupFlowSelector,
});

const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const session = useSession();

// Guides are assigned for the MANAGE_TEAM onboarding action, except for emails that have a '+'.
const isOnboardingGuideAssigned = introSelected?.choice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM && !session?.email?.includes('+');
const shouldShowToooltipOnThisReport = isOnboardingGuideAssigned ? ReportUtils.isAdminRoom(report) : ReportUtils.isConciergeChatReport(report);
const [shouldHideGBRTooltip] = useOnyx(ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP, {initialValue: true});

const shouldShowGetStartedTooltip = shouldShowToooltipOnThisReport && isScreenFocused;
const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext(
CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.CONCEIRGE_LHN_GBR,
shouldShowGetStartedTooltip,
);
const {translate} = useLocalize();
const [isContextMenuActive, setIsContextMenuActive] = useState(false);

Expand All @@ -72,30 +72,6 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
}, []),
);

const renderGBRTooltip = useCallback(
() => (
<View style={[styles.alignItemsCenter, styles.flexRow, styles.justifyContentCenter, styles.flexWrap, styles.textAlignCenter, styles.gap1]}>
<Icon
src={Expensicons.Lightbulb}
fill={theme.tooltipHighlightText}
medium
/>
<Text style={styles.quickActionTooltipSubtitle}>{translate('sidebarScreen.tooltip')}</Text>
</View>
),
[
styles.alignItemsCenter,
styles.flexRow,
styles.justifyContentCenter,
styles.flexWrap,
styles.textAlignCenter,
styles.gap1,
styles.quickActionTooltipSubtitle,
theme.tooltipHighlightText,
translate,
],
);

const isInFocusMode = viewMode === CONST.OPTION_MODE.COMPACT;
const sidebarInnerRowStyle = StyleSheet.flatten<ViewStyle>(
isInFocusMode
Expand Down Expand Up @@ -180,17 +156,17 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
needsOffscreenAlphaCompositing
>
<EducationalTooltip
shouldRender={isFirstTimeNewExpensifyUser && !shouldHideGBRTooltip && isOnboardingCompleted && isScreenFocused && shouldUseNarrowLayout && shouldShowToooltipOnThisReport}
renderTooltipContent={renderGBRTooltip}
shouldRender={shouldShowProductTrainingTooltip}
renderTooltipContent={renderProductTrainingTooltip}
anchorAlignment={{
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
}}
shouldUseOverlay
shiftHorizontal={variables.gbrTooltipShiftHorizontal}
onHideTooltip={hideProductTrainingTooltip}
shiftVertical={variables.composerTooltipShiftVertical}
wrapperStyle={styles.quickActionTooltipWrapper}
onHideTooltip={User.dismissGBRTooltip}
>
<View>
<Hoverable>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type {ValueOf} from 'type-fest';
Copy link
Contributor

Choose a reason for hiding this comment

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

This all caps filename seems unusual. Is that usually how we name these?

import {dismissProductTraining} from '@libs/actions/Welcome';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';

const {CONCEIRGE_LHN_GBR, RENAME_SAVED_SEARCH, WORKSAPCE_CHAT_CREATE, QUICK_ACTION_BUTTON} = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES;

type ProductTrainingTooltipName = ValueOf<typeof CONST.PRODUCT_TRAINING_TOOLTIP_NAMES>;

type ShouldShowConditionProps = {
shouldUseNarrowLayout?: boolean;
};

type TooltipData = {
content: Array<{text: TranslationPaths; isBold: boolean}>;
onHideTooltip: () => void;
name: ProductTrainingTooltipName;
priority: number;
shouldShow: (props: ShouldShowConditionProps) => boolean;
};

const PRODUCT_TRAINING_TOOLTIP_DATA: Record<ProductTrainingTooltipName, TooltipData> = {
[CONCEIRGE_LHN_GBR]: {
content: [
{text: 'productTrainingTooltip.conciergeLHNGBR.part1', isBold: false},
{text: 'productTrainingTooltip.conciergeLHNGBR.part2', isBold: true},
],
onHideTooltip: () => dismissProductTraining(CONCEIRGE_LHN_GBR),
name: CONCEIRGE_LHN_GBR,
priority: 1300,
shouldShow: ({shouldUseNarrowLayout}) => !!shouldUseNarrowLayout,
},
[RENAME_SAVED_SEARCH]: {
content: [
{text: 'productTrainingTooltip.saveSearchTooltip.part1', isBold: true},
{text: 'productTrainingTooltip.saveSearchTooltip.part2', isBold: false},
],
onHideTooltip: () => dismissProductTraining(RENAME_SAVED_SEARCH),
name: RENAME_SAVED_SEARCH,
priority: 1250,
shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout,
},
[QUICK_ACTION_BUTTON]: {
content: [
{text: 'productTrainingTooltip.quickActionButton.part1', isBold: true},
{text: 'productTrainingTooltip.quickActionButton.part2', isBold: false},
],
onHideTooltip: () => dismissProductTraining(QUICK_ACTION_BUTTON),
name: QUICK_ACTION_BUTTON,
priority: 1200,
shouldShow: () => true,
},
[WORKSAPCE_CHAT_CREATE]: {
content: [
{text: 'productTrainingTooltip.workspaceChatCreate.part1', isBold: false},
{text: 'productTrainingTooltip.workspaceChatCreate.part2', isBold: true},
{text: 'productTrainingTooltip.workspaceChatCreate.part3', isBold: false},
],
onHideTooltip: () => dismissProductTraining(WORKSAPCE_CHAT_CREATE),
name: WORKSAPCE_CHAT_CREATE,
priority: 1100,
shouldShow: () => true,
},
};

export default PRODUCT_TRAINING_TOOLTIP_DATA;
export type {ProductTrainingTooltipName};
Loading