-
Notifications
You must be signed in to change notification settings - Fork 581
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: simplify bottom tabs logic (#11175)
* feat: simplify bottom tabs logic * chore: better comment * chore: remove old visual clue * chore: make text non selectable
- Loading branch information
1 parent
e91bac2
commit 8162eae
Showing
4 changed files
with
211 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { useColor, useSpace } from "@artsy/palette-mobile" | ||
import { renderHook } from "@testing-library/react-hooks" | ||
import { useVisualClue } from "app/utils/hooks/useVisualClue" | ||
import { useTabBarBadge } from "app/utils/useTabBarBadge" | ||
import { useBottomTabsBadges } from "./useBottomTabsBadges" | ||
|
||
// Mocking the necessary imports | ||
jest.mock("@artsy/palette-mobile", () => ({ | ||
useColor: jest.fn(), | ||
useSpace: jest.fn(), | ||
})) | ||
jest.mock("app/utils/hooks/useVisualClue", () => ({ | ||
useVisualClue: jest.fn(), | ||
})) | ||
|
||
jest.mock("app/utils/useTabBarBadge", () => ({ | ||
useTabBarBadge: jest.fn(), | ||
})) | ||
|
||
// Settings for the test | ||
describe("useBottomTabsBadges", () => { | ||
const mockUseColor = useColor as jest.Mock | ||
const mockUseSpace = useSpace as jest.Mock | ||
const mockUseVisualClue = useVisualClue as jest.Mock | ||
const mockUseTabBarBadge = useTabBarBadge as jest.Mock | ||
|
||
beforeEach(() => { | ||
mockUseColor.mockReturnValue((color: string) => color) | ||
mockUseSpace.mockReturnValue(() => 10) | ||
}) | ||
|
||
it("returns default badge states when no clues or notifications are present", () => { | ||
mockUseVisualClue.mockReturnValue({ showVisualClue: () => false }) | ||
mockUseTabBarBadge.mockReturnValue({ | ||
unreadConversationsCount: 0, | ||
hasUnseenNotifications: false, | ||
}) | ||
|
||
const { result } = renderHook(() => useBottomTabsBadges()) | ||
|
||
expect(result.current.tabsBadges).toMatchObject({ | ||
home: { badgeCount: undefined, badgeStyle: {} }, | ||
search: { badgeCount: undefined, badgeStyle: {} }, | ||
inbox: { badgeCount: undefined, badgeStyle: {} }, | ||
sell: { badgeCount: undefined, badgeStyle: {} }, | ||
profile: { badgeCount: undefined, badgeStyle: {} }, | ||
}) | ||
}) | ||
|
||
it('updates badge for "home" tab when unseen notifications are present', () => { | ||
mockUseVisualClue.mockReturnValue({ showVisualClue: () => false }) | ||
mockUseTabBarBadge.mockReturnValue({ | ||
hasUnseenNotifications: true, | ||
}) | ||
|
||
const { result } = renderHook(() => useBottomTabsBadges()) | ||
|
||
expect(result.current.tabsBadges.home).toMatchObject({ | ||
badgeCount: "", | ||
badgeStyle: { | ||
// Whatever style we have here | ||
}, | ||
}) | ||
}) | ||
|
||
it('updates badge for "inbox" tab when unseen notifications are present', () => { | ||
mockUseVisualClue.mockReturnValue({ showVisualClue: () => false }) | ||
mockUseTabBarBadge.mockReturnValue({ | ||
unreadConversationsCount: 5, | ||
}) | ||
|
||
const { result } = renderHook(() => useBottomTabsBadges()) | ||
|
||
expect(result.current.tabsBadges.inbox).toMatchObject({ | ||
badgeCount: 5, | ||
badgeStyle: { | ||
// Whatever style we have here | ||
}, | ||
}) | ||
}) | ||
|
||
it('prioritises conversations count over visual clues for "inbox" tab', () => { | ||
mockUseVisualClue.mockReturnValue({ showVisualClue: () => true }) | ||
mockUseTabBarBadge.mockReturnValue({ | ||
unreadConversationsCount: 5, | ||
}) | ||
|
||
const { result } = renderHook(() => useBottomTabsBadges()) | ||
|
||
expect(result.current.tabsBadges.inbox).toMatchObject({ | ||
badgeCount: 5, | ||
badgeStyle: { | ||
// Whatever style we have here | ||
}, | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { useColor, useSpace } from "@artsy/palette-mobile" | ||
import { BottomTabType } from "app/Scenes/BottomTabs/BottomTabType" | ||
import { bottomTabsConfig } from "app/Scenes/BottomTabs/bottomTabsConfig" | ||
import { useVisualClue } from "app/utils/hooks/useVisualClue" | ||
import { useTabBarBadge } from "app/utils/useTabBarBadge" | ||
import { StyleProp, TextStyle } from "react-native" | ||
|
||
const VISUAL_CLUE_HEIGHT = 10 | ||
|
||
type BadgeProps = { badgeCount?: string | number; badgeStyle: StyleProp<TextStyle> } | ||
/** | ||
* This hook is used to get badge details for each bottom tab | ||
* @returns an object with the badge count and style for each tab | ||
* @example { home: { badgeCount: 5, badgeStyle: { backgroundColor: "red" } }, search: { badgeCount: undefined, badgeStyle: {} } } | ||
*/ | ||
export const useBottomTabsBadges = () => { | ||
const color = useColor() | ||
const space = useSpace() | ||
|
||
const { showVisualClue } = useVisualClue() | ||
|
||
const { unreadConversationsCount, hasUnseenNotifications } = useTabBarBadge() | ||
|
||
const tabsBadges: Record<string, BadgeProps> = {} | ||
|
||
const visualClueStyles = { | ||
backgroundColor: color("blue100"), | ||
top: space(1), | ||
minWidth: VISUAL_CLUE_HEIGHT, | ||
maxHeight: VISUAL_CLUE_HEIGHT, | ||
borderRadius: VISUAL_CLUE_HEIGHT / 2, | ||
borderColor: color("white100"), | ||
borderWidth: 1, | ||
} | ||
|
||
const hasVisualCluesForTab = (tab: BottomTabType) => { | ||
const visualClues = bottomTabsConfig[tab].visualClues | ||
if (!visualClues) { | ||
return false | ||
} | ||
|
||
return visualClues?.find(showVisualClue) | ||
} | ||
|
||
Object.keys(bottomTabsConfig).forEach((tab) => { | ||
const defaultBadgeProps: BadgeProps = { | ||
badgeCount: undefined, | ||
badgeStyle: {}, | ||
} | ||
|
||
tabsBadges[tab] = defaultBadgeProps | ||
|
||
if (hasVisualCluesForTab(tab as BottomTabType)) { | ||
tabsBadges[tab] = { | ||
badgeCount: "", | ||
badgeStyle: { | ||
...visualClueStyles, | ||
}, | ||
} | ||
} | ||
|
||
switch (tab) { | ||
case "home": { | ||
if (hasUnseenNotifications) { | ||
tabsBadges[tab] = { | ||
badgeCount: "", | ||
badgeStyle: { | ||
...visualClueStyles, | ||
}, | ||
} | ||
} | ||
return | ||
} | ||
|
||
case "inbox": { | ||
if (unreadConversationsCount) { | ||
tabsBadges[tab] = { | ||
badgeCount: unreadConversationsCount, | ||
badgeStyle: { | ||
backgroundColor: color("red100"), | ||
}, | ||
} | ||
} | ||
return | ||
} | ||
} | ||
}) | ||
|
||
return { tabsBadges } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters