diff --git a/shared/chat/conversation/messages/wrapper/wrapper.tsx b/shared/chat/conversation/messages/wrapper/wrapper.tsx index 71b35b04ba24..dbcd1ab46fad 100644 --- a/shared/chat/conversation/messages/wrapper/wrapper.tsx +++ b/shared/chat/conversation/messages/wrapper/wrapper.tsx @@ -108,13 +108,13 @@ function AuthorSection(p: AuthorProps) { const {author, botAlias, isAdhocBot, teamID, teamType, teamname, timestamp, showUsername} = p const authorRoleInTeam = useTeamsState(s => s.teamIDToMembers.get(teamID)?.get(author)?.type) - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const onAuthorClick = () => { if (C.isMobile) { navToProfile(showUsername) } else { - showUser(showUsername, true) + showTracker(showUsername) } } diff --git a/shared/common-adapters/mention-container.tsx b/shared/common-adapters/mention-container.tsx index ba3fdc19b0de..0c7d4ad187ac 100644 --- a/shared/common-adapters/mention-container.tsx +++ b/shared/common-adapters/mention-container.tsx @@ -24,12 +24,12 @@ const Container = (ownProps: OwnProps) => { } })() - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const _onClick = () => { if (C.isMobile) { navToProfile(username) } else { - showUser(username, true) + showTracker(username) } } const onClick = Chat.isSpecialMention(username) ? undefined : _onClick diff --git a/shared/common-adapters/name-with-icon.tsx b/shared/common-adapters/name-with-icon.tsx index 30cb776a5f33..5d425a356f08 100644 --- a/shared/common-adapters/name-with-icon.tsx +++ b/shared/common-adapters/name-with-icon.tsx @@ -426,9 +426,9 @@ const ConnectedNameWithIcon = (p: OwnProps) => { navigateAppend({name: 'team', params: {teamID}}) } } - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const onOpenTracker = () => { - username && showUser(username, true) + username && showTracker(username) } const onOpenUserProfile = () => { username && navToProfile(username) diff --git a/shared/common-adapters/profile-card.tsx b/shared/common-adapters/profile-card.tsx index 559ff605e32e..c9b419275857 100644 --- a/shared/common-adapters/profile-card.tsx +++ b/shared/common-adapters/profile-card.tsx @@ -159,10 +159,10 @@ const ProfileCard = ({ bio: userDetailsBio, fullname: userDetailsFullname, } = userDetails - const showUser = useTrackerState(s => s.dispatch.showUser) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) React.useEffect(() => { - userDetailsState === 'unknown' && showUser(username, false, true) - }, [showUser, username, userDetailsState]) + userDetailsState === 'unknown' && loadProfile(username) + }, [loadProfile, username, userDetailsState]) // signal layout change when it happens, to prevent popup cutoff. React.useEffect(() => { onLayoutChange?.() diff --git a/shared/common-adapters/proof-broken-banner.tsx b/shared/common-adapters/proof-broken-banner.tsx index 8f94cdae7358..63a8deb281e5 100644 --- a/shared/common-adapters/proof-broken-banner.tsx +++ b/shared/common-adapters/proof-broken-banner.tsx @@ -8,12 +8,12 @@ type Props = {users?: Array} type ProofBrokenBannerNonEmptyProps = {users: Array} const ProofBrokenBannerNonEmpty = (props: ProofBrokenBannerNonEmptyProps) => { - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const onClickUsername = (username: string) => { if (C.isMobile) { navToProfile(username) } else { - showUser(username, true) + showTracker(username) } } const content: Array void}> = diff --git a/shared/common-adapters/usernames.tsx b/shared/common-adapters/usernames.tsx index 2ed26104db17..21e57e31ad32 100644 --- a/shared/common-adapters/usernames.tsx +++ b/shared/common-adapters/usernames.tsx @@ -94,7 +94,7 @@ function Username(p: UsernameProps) { if (onUsernameClicked === 'tracker') { onClicked = (evt?: React.BaseSyntheticEvent) => { evt?.stopPropagation() - useTrackerState.getState().dispatch.showUser(username, true) + useTrackerState.getState().dispatch.showTracker(username) } } else if (onUsernameClicked === 'profile') { onClicked = (evt?: React.BaseSyntheticEvent) => { diff --git a/shared/constants/init/shared.tsx b/shared/constants/init/shared.tsx index 9e6f0e1ec2ed..4e854e101612 100644 --- a/shared/constants/init/shared.tsx +++ b/shared/constants/init/shared.tsx @@ -331,9 +331,6 @@ export const initTracker2Callbacks = () => { ...currentState.dispatch, defer: { ...currentState.dispatch.defer, - onShowUserProfile: (username: string) => { - navToProfile(username) - }, onUsersUpdates: (updates: ReadonlyArray<{name: string; info: Partial}>) => { useUsersState.getState().dispatch.updates(updates) }, diff --git a/shared/fs/banner/reset-banner.tsx b/shared/fs/banner/reset-banner.tsx index f0939d5dcfb7..7ce0d9cb160f 100644 --- a/shared/fs/banner/reset-banner.tsx +++ b/shared/fs/banner/reset-banner.tsx @@ -3,7 +3,6 @@ import * as T from '@/constants/types' import {folderNameWithoutUsers} from '@/util/kbfs' import * as Kb from '@/common-adapters' import * as RowTypes from '@/fs/browser/rows/types' -import {useTrackerState} from '@/stores/tracker' import {useFSState} from '@/stores/fs' import * as FS from '@/stores/fs' import {navToProfile} from '@/constants/router' @@ -25,9 +24,8 @@ const ConnectedBanner = (ownProps: OwnProps) => { letResetUserBackIn(id, username) } - const showUser = useTrackerState(s => s.dispatch.showUser) - const onViewProfile = (username: string) => () => { - C.isMobile ? navToProfile(username) : showUser(username, true) + const onOpenProfile = (username: string) => () => { + navToProfile(username) } const onOpenWithoutResetUsers = () => _onOpenWithoutResetUsers( @@ -100,7 +98,7 @@ const ConnectedBanner = (ownProps: OwnProps) => { diff --git a/shared/git/row.tsx b/shared/git/row.tsx index db871cbd82d9..189b8d0093e1 100644 --- a/shared/git/row.tsx +++ b/shared/git/row.tsx @@ -7,6 +7,7 @@ import {openURL} from '@/util/misc' import {useTrackerState} from '@/stores/tracker' import * as FS from '@/stores/fs' import {useCurrentUserState} from '@/stores/current-user' +import {navToProfile} from '@/constants/router' export const NewContext = React.createContext>(new Set()) @@ -77,9 +78,13 @@ function ConnectedRow(ownProps: OwnProps) { ) } - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const openUserTracker = (username: string) => { - showUser(username, true) + if (C.isMobile) { + navToProfile(username) + } else { + showTracker(username) + } } const onBrowseGitRepo = () => diff --git a/shared/people/todo.tsx b/shared/people/todo.tsx index 6b3a2e98819f..79387726a343 100644 --- a/shared/people/todo.tsx +++ b/shared/people/todo.tsx @@ -9,7 +9,6 @@ import * as Kb from '@/common-adapters' import {useSettingsEmailState} from '@/stores/settings-email' import {settingsAccountTab, settingsGitTab} from '@/constants/settings' import type {AppTab} from '@/constants/tabs' -import {useTrackerState} from '@/stores/tracker' import {useCurrentUserState} from '@/stores/current-user' import {navToProfile} from '@/constants/router' @@ -138,10 +137,8 @@ const AvatarUserTask = (props: TodoOwnProps) => ( const BioTask = (props: TodoOwnProps) => { const myUsername = useCurrentUserState(s => s.username) - const showUser = useTrackerState(s => s.dispatch.showUser) const onConfirm = () => { - // Ensure tracker state exists and the profile view is up to date. - showUser(myUsername, false) + navToProfile(myUsername) } return } diff --git a/shared/profile/edit-profile.tsx b/shared/profile/edit-profile.tsx index fbf64227b52a..393b53e2df48 100644 --- a/shared/profile/edit-profile.tsx +++ b/shared/profile/edit-profile.tsx @@ -3,13 +3,12 @@ import * as Kb from '@/common-adapters' import * as React from 'react' import {useTrackerState} from '@/stores/tracker' import {useCurrentUserState} from '@/stores/current-user' -import {generateGUIID} from '@/constants/utils' import * as T from '@/constants/types' const Container = () => { const username = useCurrentUserState(s => s.username) const d = useTrackerState(s => s.getDetails(username)) - const loadProfile = useTrackerState(s => s.dispatch.load) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) const _bio = d.bio || '' const _fullname = d.fullname || '' const _location = d.location || '' @@ -20,7 +19,7 @@ const Container = () => { editProfile( [{bio, fullName: fullname, location}, C.waitingKeyTracker], () => { - loadProfile({assertion: username, guiID: generateGUIID(), inTracker: false, reason: ''}) + loadProfile(username, false) navigateUp() }, () => {} diff --git a/shared/profile/generic/proofs-list.tsx b/shared/profile/generic/proofs-list.tsx index 9a5bc1c6a628..dbd4af6830b5 100644 --- a/shared/profile/generic/proofs-list.tsx +++ b/shared/profile/generic/proofs-list.tsx @@ -12,7 +12,7 @@ import {useConfigState} from '@/stores/config' import {openURL as openUrl} from '@/util/misc' import {subtitle} from '@/util/platforms' import {useCurrentUserState} from '@/stores/current-user' -import {generateGUIID, ignorePromise} from '@/constants/utils' +import {ignorePromise} from '@/constants/utils' import {RPCError} from '@/util/errors' import logger from '@/logger' import {navToProfile} from '@/constants/router' @@ -108,7 +108,7 @@ type Step = const Container = ({platform, reason = 'profile'}: Props) => { const currentUsername = useCurrentUserState(s => s.username) - const loadProfile = useTrackerState(s => s.dispatch.load) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) const proofSuggestions = useTrackerState(s => s.proofSuggestions) const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const registerCryptoAddress = C.useRPC(T.RPCGen.cryptocurrencyRegisterAddressRpcPromise) @@ -168,8 +168,7 @@ const Container = ({platform, reason = 'profile'}: Props) => { } }, []) - const loadCurrentProfile = () => - loadProfile({assertion: currentUsername, guiID: generateGUIID(), inTracker: false, reason: ''}) + const loadCurrentProfile = () => loadProfile(currentUsername, false) const closeModal = () => { cancelSession() diff --git a/shared/profile/revoke.tsx b/shared/profile/revoke.tsx index d2e6750c6812..fd66c734075d 100644 --- a/shared/profile/revoke.tsx +++ b/shared/profile/revoke.tsx @@ -8,7 +8,6 @@ import * as T from '@/constants/types' import Modal from './modal' import {useCurrentUserState} from '@/stores/current-user' import {useTrackerState} from '@/stores/tracker' -import {generateGUIID} from '@/constants/utils' import {navToProfile} from '@/constants/router' type OwnProps = { @@ -22,14 +21,14 @@ const RevokeProof = (ownProps: OwnProps) => { const [errorMessage, setErrorMessage] = React.useState('') const currentUsername = useCurrentUserState(s => s.username) const assertions = useTrackerState(s => s.getDetails(currentUsername).assertions) - const loadProfile = useTrackerState(s => s.dispatch.load) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) const revokeKey = C.useRPC(T.RPCGen.revokeRevokeKeyRpcPromise) const revokeSigs = C.useRPC(T.RPCGen.revokeRevokeSigsRpcPromise) const clearModals = C.Router2.clearModals const proof = assertions ? [...assertions.values()].find(a => a.sigID === proofId) : undefined const onSuccess = () => { navToProfile(currentUsername) - loadProfile({assertion: currentUsername, guiID: generateGUIID(), inTracker: false, reason: ''}) + loadProfile(currentUsername, false) clearModals() } const onCancel = () => { diff --git a/shared/profile/showcase-team-offer.tsx b/shared/profile/showcase-team-offer.tsx index 02fe39c0934a..cae69d8466e1 100644 --- a/shared/profile/showcase-team-offer.tsx +++ b/shared/profile/showcase-team-offer.tsx @@ -19,13 +19,7 @@ const Container = () => { React.useEffect(() => { return () => { setTimeout(() => { - useTrackerState.getState().dispatch.load({ - assertion: you, - guiID: C.generateGUIID(), - ignoreCache: true, - inTracker: false, - reason: '', - }) + useTrackerState.getState().dispatch.loadProfile(you) }, 500) } }, [you]) diff --git a/shared/profile/user/actions/index.tsx b/shared/profile/user/actions/index.tsx index 2a55da4cfb9d..c362484001b4 100644 --- a/shared/profile/user/actions/index.tsx +++ b/shared/profile/user/actions/index.tsx @@ -40,9 +40,9 @@ const Container = (ownProps: OwnProps) => { navigateAppend({name: 'chatBlockingModal', params: {username}}) const _onOpenPrivateFolder = (myUsername: string, theirUsername: string) => FS.navToPath(T.FS.stringToPath(`/keybase/private/${theirUsername},${myUsername}`)) - const showUser = useTrackerState(s => s.dispatch.showUser) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) const _onReload = (username: string) => { - showUser(username, false) + loadProfile(username) } const onAccept = () => _onFollow(_guiID, true) const onAddToTeam = () => _onAddToTeam(username) diff --git a/shared/profile/user/hooks.tsx b/shared/profile/user/hooks.tsx index 2d124adf0d61..aafc19f9ba0a 100644 --- a/shared/profile/user/hooks.tsx +++ b/shared/profile/user/hooks.tsx @@ -38,12 +38,13 @@ const useUserData = (username: string) => { d: s.getDetails(username), getProofSuggestions: s.dispatch.getProofSuggestions, loadNonUserProfile: s.dispatch.loadNonUserProfile, + loadProfile: s.dispatch.loadProfile, nonUserDetails: s.getNonUserDetails(username), - showUser: s.dispatch.showUser, } }) ) - const {d, getProofSuggestions, loadNonUserProfile, nonUserDetails, showUser, _suggestionKeys} = trackerState + const {d, getProofSuggestions, loadProfile, loadNonUserProfile, nonUserDetails, _suggestionKeys} = + trackerState const notAUser = d.state === 'notAUserYet' const commonProps = { @@ -138,7 +139,7 @@ const useUserData = (username: string) => { loadNonUserProfile(username) } if (state !== 'notAUserYet') { - showUser(username, false, true) + loadProfile(username) if (isYou) { getProofSuggestions() diff --git a/shared/settings/contacts-joined.tsx b/shared/settings/contacts-joined.tsx index feadb0911506..9e31d2192b9c 100644 --- a/shared/settings/contacts-joined.tsx +++ b/shared/settings/contacts-joined.tsx @@ -25,14 +25,14 @@ export const FollowButton = (props: FollowProps) => { const followsYou = useFollowerState(s => s.followers.has(username)) const {guiID} = userDetails - const showUser = useTrackerState(s => s.dispatch.showUser) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) const changeFollow = useTrackerState(s => s.dispatch.changeFollow) React.useEffect(() => { if (!guiID) { - showUser(username, false, true) + loadProfile(username) } - }, [username, guiID, showUser]) + }, [username, guiID, loadProfile]) const onFollow = () => changeFollow(guiID, true) const onUnfollow = () => changeFollow(guiID, false) diff --git a/shared/stores/tests/tracker.test.ts b/shared/stores/tests/tracker.test.ts index 40845309c439..4168dbf0b727 100644 --- a/shared/stores/tests/tracker.test.ts +++ b/shared/stores/tests/tracker.test.ts @@ -43,22 +43,17 @@ test('closeTracker removes the shown tracker entry by guiID and updateResult cha expect(useTrackerState.getState().showTrackerSet.has('alice')).toBe(false) }) -test('showUser delegates to load and the deferred profile callback', () => { +test('loadProfile delegates to load with a profile load', () => { const load = jest.fn() - const onShowUserProfile = jest.fn() useTrackerState.setState(s => ({ ...s, dispatch: { ...s.dispatch, - defer: { - ...s.dispatch.defer, - onShowUserProfile, - }, load: load as never, }, })) - useTrackerState.getState().dispatch.showUser('alice', false) + useTrackerState.getState().dispatch.loadProfile('alice') expect(load).toHaveBeenCalledWith( expect.objectContaining({ @@ -69,7 +64,29 @@ test('showUser delegates to load and the deferred profile callback', () => { reason: '', }) ) - expect(onShowUserProfile).toHaveBeenCalledWith('alice') +}) + +test('showTracker delegates to load with a tracker load', () => { + const load = jest.fn() + useTrackerState.setState(s => ({ + ...s, + dispatch: { + ...s.dispatch, + load: load as never, + }, + })) + + useTrackerState.getState().dispatch.showTracker('alice') + + expect(load).toHaveBeenCalledWith( + expect.objectContaining({ + assertion: 'alice', + forceDisplay: true, + ignoreCache: true, + inTracker: true, + reason: '', + }) + ) }) test('notifySummary and notifyRow enrich an existing tracker entry', () => { diff --git a/shared/stores/tracker.tsx b/shared/stores/tracker.tsx index 6e2526d63a8b..9b37b207db4e 100644 --- a/shared/stores/tracker.tsx +++ b/shared/stores/tracker.tsx @@ -164,7 +164,6 @@ const initialStore: Store = { export type State = Store & { dispatch: { defer: { - onShowUserProfile?: (username: string) => void onUsersUpdates?: (updates: ReadonlyArray<{name: string; info: Partial}>) => void } changeFollow: (guiID: string, follow: boolean) => void @@ -180,6 +179,7 @@ export type State = Store & { reason: string inTracker: boolean }) => void + loadProfile: (username: string, ignoreCache?: boolean) => void loadNonUserProfile: (assertion: string) => void notifyCard: (guiID: string, card: T.RPCGen.UserCard) => void notifyReset: (guiID: string) => void @@ -189,7 +189,7 @@ export type State = Store & { onEngineIncomingImpl: (action: EngineGen.Actions) => void replace: (usernameToDetails: Map) => void resetState: () => void - showUser: (username: string, asTracker: boolean, skipNav?: boolean) => void + showTracker: (username: string) => void updateResult: (guiID: string, result: T.Tracker.DetailsState, reason?: string) => void } getDetails: (username: string) => T.Tracker.Details @@ -232,9 +232,6 @@ export const useTrackerState = Z.createZustand('tracker', (set, get) => { }) }, defer: { - onShowUserProfile: () => { - throw new Error('onShowUserProfile not implemented') - }, onUsersUpdates: () => { throw new Error('onUsersUpdates not implemented') }, @@ -396,7 +393,10 @@ export const useTrackerState = Z.createZustand('tracker', (set, get) => { const fullName = res.contact?.contactName ?? '' set(s => { const old = s.usernameToNonUserDetails.get(assertion) ?? noNonUserDetails - s.usernameToNonUserDetails.set(assertion, T.castDraft({...old, ...common, formattedName, fullName})) + s.usernameToNonUserDetails.set( + assertion, + T.castDraft({...old, ...common, formattedName, fullName}) + ) }) } } @@ -408,6 +408,17 @@ export const useTrackerState = Z.createZustand('tracker', (set, get) => { } ignorePromise(f()) }, + loadProfile: (username, ignoreCache = true) => { + get().dispatch.load({ + assertion: username, + forceDisplay: false, + fromDaemon: false, + guiID: generateGUIID(), + ignoreCache, + inTracker: false, + reason: '', + }) + }, notifyCard: (guiID, card) => { const username = guiIDToUsername(get(), guiID) set(s => { @@ -582,21 +593,16 @@ export const useTrackerState = Z.createZustand('tracker', (set, get) => { }) }, resetState: Z.defaultReset, - showUser: (username, asTracker, skipNav) => { + showTracker: username => { get().dispatch.load({ assertion: username, - // with new nav we never show trackers from inside the app - forceDisplay: false, + forceDisplay: true, fromDaemon: false, guiID: generateGUIID(), ignoreCache: true, - inTracker: asTracker, + inTracker: true, reason: '', }) - if (!skipNav) { - // go to profile page - get().dispatch.defer.onShowUserProfile?.(username) - } }, updateResult: (guiID, result, reason) => { set(s => { diff --git a/shared/teams/team/rows/bot-row/bot.tsx b/shared/teams/team/rows/bot-row/bot.tsx index 64d944fc7475..a7e35c785765 100644 --- a/shared/teams/team/rows/bot-row/bot.tsx +++ b/shared/teams/team/rows/bot-row/bot.tsx @@ -179,12 +179,12 @@ const Container = (ownProps: OwnProps) => { const roleType = info.type const status = info.status const username = info.username - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const _onShowTracker = (username: string) => { if (C.isMobile) { navToProfile(username) } else { - showUser(username, true) + showTracker(username) } } const navigateAppend = C.Router2.navigateAppend diff --git a/shared/teams/team/rows/member-row.tsx b/shared/teams/team/rows/member-row.tsx index 57addfa3f0cb..521142222e7a 100644 --- a/shared/teams/team/rows/member-row.tsx +++ b/shared/teams/team/rows/member-row.tsx @@ -330,12 +330,12 @@ const Container = (ownProps: OwnProps) => { const onRemoveFromTeam = () => { removeMember(teamID, username) } - const showUser = useTrackerState(s => s.dispatch.showUser) + const showTracker = useTrackerState(s => s.dispatch.showTracker) const onShowTracker = () => { if (C.isMobile) { navToProfile(username) } else { - showUser(username, true) + showTracker(username) } } const props = { diff --git a/shared/tracker/assertion.tsx b/shared/tracker/assertion.tsx index 4e9c9b30d039..b6762d5e5586 100644 --- a/shared/tracker/assertion.tsx +++ b/shared/tracker/assertion.tsx @@ -10,7 +10,6 @@ import {formatTimeForAssertionPopup} from '@/util/timestamp' import {useColorScheme} from 'react-native' import * as Tracker from '@/stores/tracker' import {useTrackerState} from '@/stores/tracker' -import {generateGUIID} from '@/constants/utils' import {navToProfile} from '@/constants/router' type OwnProps = { @@ -75,7 +74,7 @@ const Container = (ownProps: OwnProps) => { ) const {color, metas: _metas, proofURL, sigID, siteIcon, stellarHidden, notAUser} = data const {siteIconDarkmode, siteIconFull, siteIconFullDarkmode, siteURL, state, timestamp, type, value} = data - const loadProfile = useTrackerState(s => s.dispatch.load) + const loadProfile = useTrackerState(s => s.dispatch.loadProfile) const hideStellar = C.useRPC(T.RPCGen.apiserverPostRpcPromise) const recheckProof = C.useRPC(T.RPCGen.proveCheckProofRpcPromise) const navigateAppend = C.Router2.navigateAppend @@ -92,7 +91,7 @@ const Container = (ownProps: OwnProps) => { [{sigID}, C.waitingKeyProfile], () => { navToProfile(ownProps.username) - loadProfile({assertion: ownProps.username, guiID: generateGUIID(), inTracker: false, reason: ''}) + loadProfile(ownProps.username, false) }, () => {} )