Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Repo Notes

- This repo uses React Compiler. Assume React Compiler patterns are enabled when editing React code, and avoid adding `useMemo`/`useCallback` by default unless they are clearly needed for correctness or compatibility with existing code.
- Treat React mount/unmount effects as Strict-Mode-safe. Do not assume a component only mounts once; route-driven async startup and cleanup logic must be idempotent and must not leave refs or guards stuck false after a dev remount.
- When a component reads multiple adjacent values from the same store hook, prefer a consolidated selector with `C.useShallow(...)` instead of multiple separate subscriptions.
- Do not add new exported functions, types, or constants unless they are required outside the file. Prefer file-local helpers for one-off implementation details and tests.
5 changes: 2 additions & 3 deletions shared/chat/blocking/invitation-to-block.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as Chat from '@/stores/chat'
import {useProfileState} from '@/stores/profile'
import * as Kb from '@/common-adapters'
import {useSafeNavigation} from '@/util/safe-navigation'
import {useCurrentUserState} from '@/stores/current-user'
import {navToProfile} from '@/constants/router'

const BlockButtons = () => {
const nav = useSafeNavigation()
Expand All @@ -16,7 +16,6 @@ const BlockButtons = () => {
})
const participantInfo = Chat.useChatContext(s => s.participants)
const currentUser = useCurrentUserState(s => s.username)
const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const dismissBlockButtons = Chat.useChatContext(s => s.dispatch.dismissBlockButtons)
if (!blockButtonInfo) {
return null
Expand All @@ -26,7 +25,7 @@ const BlockButtons = () => {
person => person !== currentUser && person !== adder && !Chat.isAssertion(person)
)

const onViewProfile = () => showUserProfile(adder)
const onViewProfile = () => navToProfile(adder)
const onViewTeam = () => nav.safeNavigateAppend({name: 'team', params: {teamID}})
const onBlock = () =>
nav.safeNavigateAppend({
Expand Down
5 changes: 2 additions & 3 deletions shared/chat/conversation/header-area/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as C from '@/constants'
import * as Chat from '@/stores/chat'
import {useProfileState} from '@/stores/profile'
import * as Kb from '@/common-adapters'
import type {HeaderBackButtonProps} from '@react-navigation/elements'
import {HeaderLeftButton} from '@/common-adapters/header-buttons'
Expand All @@ -10,6 +9,7 @@ import {assertionToDisplay} from '@/common-adapters/usernames'
import {useSafeAreaFrame} from 'react-native-safe-area-context'
import {useUsersState} from '@/stores/users'
import {useCurrentUserState} from '@/stores/current-user'
import {navToProfile} from '@/constants/router'

export const HeaderAreaRight = () => {
const conversationIDKey = Chat.useChatContext(s => s.id)
Expand Down Expand Up @@ -221,9 +221,8 @@ const UsernameHeader = () => {
return {participants, theirFullname}
})
)
const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const onShowProfile = (username: string) => {
showUserProfile(username)
navToProfile(username)
}

const maxWidthStyle = useMaxWidthStyle()
Expand Down
5 changes: 2 additions & 3 deletions shared/chat/conversation/info-panel/members.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as C from '@/constants'
import * as Chat from '@/stores/chat'
import {useProfileState} from '@/stores/profile'
import * as Teams from '@/stores/teams'
import * as React from 'react'
import * as Kb from '@/common-adapters'
import * as T from '@/constants/types'
import Participant from './participant'
import {useUsersState} from '@/stores/users'
import {navToProfile} from '@/constants/router'

type Props = {
commonSections: ReadonlyArray<Section>
Expand Down Expand Up @@ -88,8 +88,7 @@ const MembersTab = (props: Props) => {
return l.username.localeCompare(r.username)
})

const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const onShowProfile = showUserProfile
const onShowProfile = navToProfile

const participantSection: Section = {
data: showSpinner
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react'
import {useProfileState} from '@/stores/profile'
import * as Kb from '@/common-adapters'
import {formatTimeForPopup, formatTimeForRevoked, msToDHMS} from '@/util/timestamp'
import {addTicker, removeTicker} from '@/util/second-timer'
import {navToProfile} from '@/constants/router'

type Props = {
explodesAt: number
Expand Down Expand Up @@ -36,9 +36,8 @@ const ExplodingPopupHeader = (props: Props) => {
}
}, [explodesAt])

const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const onUsernameClicked = (user: string) => {
showUserProfile(user)
navToProfile(user)
onHidden()
}

Expand Down
5 changes: 2 additions & 3 deletions shared/chat/conversation/messages/message-popup/header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Kb from '@/common-adapters'
import {useProfileState} from '@/stores/profile'
import {formatTimeForPopup, formatTimeForRevoked} from '@/util/timestamp'
import type * as T from '@/constants/types'
import {navToProfile} from '@/constants/router'

const iconNameForDeviceType = Kb.Styles.isMobile
? (deviceType: string, isRevoked: boolean, isLocation: boolean): Kb.IconType => {
Expand Down Expand Up @@ -53,9 +53,8 @@ const MessagePopupHeader = (props: Props) => {
const iconName = iconNameForDeviceType(deviceType, !!deviceRevokedAt, isLocation)
const whoRevoked = yourMessage ? 'You' : author

const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const onUsernameClicked = (user: string) => {
showUserProfile(user)
navToProfile(user)
onHidden()
}

Expand Down
9 changes: 4 additions & 5 deletions shared/chat/conversation/messages/message-popup/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import * as C from '@/constants'
import * as Chat from '@/stores/chat'
import * as Teams from '@/stores/teams'
import {useConfigState} from '@/stores/config'
import {useProfileState} from '@/stores/profile'
import {useCurrentUserState} from '@/stores/current-user'
import {linkFromConvAndMessage} from '@/constants/deeplinks'
import ReactionItem from './reactionitem'
import MessagePopupHeader from './header'
import ExplodingPopupHeader from './exploding-header'
import {formatTimeForPopup, formatTimeForRevoked} from '@/util/timestamp'
import {navToProfile} from '@/constants/router'

const emptyText = Chat.makeMessageText({})

Expand Down Expand Up @@ -232,11 +232,10 @@ export const useItems = (ordinal: T.Chat.Ordinal, onHidden: () => void) => {
] as const)
: []

const _showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const showUserProfile = () => {
_showUserProfile(author)
const onShowProfile = () => {
navToProfile(author)
}
const onViewProfile = author && !yourMessage ? showUserProfile : undefined
const onViewProfile = author && !yourMessage ? onShowProfile : undefined
const profileSubtitle = `${deviceName} ${deviceRevokedAt ? 'REVOKED at' : '-'} ${
deviceRevokedAt ? `${formatTimeForRevoked(deviceRevokedAt)}` : formatTimeForPopup(timestamp)
}`
Expand Down
5 changes: 2 additions & 3 deletions shared/chat/conversation/messages/reset-user.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Chat from '@/stores/chat'
import {useProfileState} from '@/stores/profile'
import * as Kb from '@/common-adapters'
import {navToProfile} from '@/constants/router'

const ResetUser = () => {
const meta = Chat.useChatContext(s => s.meta)
Expand All @@ -9,8 +9,7 @@ const ResetUser = () => {
const resetLetThemIn = Chat.useChatContext(s => s.dispatch.resetLetThemIn)
const _participants = participantInfo.all
const _resetParticipants = meta.resetParticipants
const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const _viewProfile = showUserProfile
const _viewProfile = navToProfile
const username = [..._resetParticipants][0] || ''
const nonResetUsers = new Set(_participants)
_resetParticipants.forEach(r => nonResetUsers.delete(r))
Expand Down
7 changes: 3 additions & 4 deletions shared/chat/conversation/messages/separator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as T from '@/constants/types'
import {formatTimeForConversationList, formatTimeForChat} from '@/util/timestamp'
import {OrangeLineContext} from '../orange-line-context'
import {useTrackerState} from '@/stores/tracker'
import {useProfileState} from '@/stores/profile'
import {navToProfile} from '@/constants/router'

const missingMessage = Chat.makeMessageDeleted({})

Expand Down Expand Up @@ -86,18 +86,17 @@ type AuthorProps = {
showUsername: string
}

// Separate component so useTeamsState/useProfileState/useTrackerState only
// Separate component so useTeamsState/useTrackerState only
// subscribe when there's actually an author to show.
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 showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const showUser = useTrackerState(s => s.dispatch.showUser)

const onAuthorClick = () => {
if (C.isMobile) {
showUserProfile(showUsername)
navToProfile(showUsername)
} else {
showUser(showUsername, true)
}
Expand Down
4 changes: 2 additions & 2 deletions shared/chat/conversation/rekey/container.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as C from '@/constants'
import * as Chat from '@/stores/chat'
import {useProfileState} from '@/stores/profile'
import {useCurrentUserState} from '@/stores/current-user'
import * as T from '@/constants/types'
import ParticipantRekey from './participant-rekey'
import YouRekey from './you-rekey'
import {navToProfile} from '@/constants/router'

const Container = () => {
const _you = useCurrentUserState(s => s.username)
Expand All @@ -23,7 +23,7 @@ const Container = () => {
)
}

const onShowProfile = useProfileState(s => s.dispatch.showUserProfile)
const onShowProfile = navToProfile

return rekeyers.has(_you) ? (
<YouRekey onEnterPaperkey={onEnterPaperkey} onBack={onBack} onRekey={onRekey} />
Expand Down
5 changes: 2 additions & 3 deletions shared/common-adapters/mention-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import * as C from '@/constants'
import * as Chat from '@/stores/chat'
import Mention, {type OwnProps} from './mention'
import {useTrackerState} from '@/stores/tracker'
import {useProfileState} from '@/stores/profile'
import {useFollowerState} from '@/stores/followers'
import {useCurrentUserState} from '@/stores/current-user'
import {navToProfile} from '@/constants/router'

const Container = (ownProps: OwnProps) => {
let {username} = ownProps
Expand All @@ -24,11 +24,10 @@ const Container = (ownProps: OwnProps) => {
}
})()

const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const showUser = useTrackerState(s => s.dispatch.showUser)
const _onClick = () => {
if (C.isMobile) {
showUserProfile(username)
navToProfile(username)
} else {
showUser(username, true)
}
Expand Down
5 changes: 2 additions & 3 deletions shared/common-adapters/name-with-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import Text from './text'
import type {TextType, StylesTextCrossPlatform, AllowedColors, TextTypeBold} from './text.shared'
import ConnectedUsernames from './usernames'
import {useTrackerState} from '@/stores/tracker'
import {useProfileState} from '@/stores/profile'
import {useFollowerState} from '@/stores/followers'
import {navToProfile} from '@/constants/router'

type AvatarSize = 128 | 96 | 64 | 48 | 32 | 24 | 16

Expand Down Expand Up @@ -430,9 +430,8 @@ const ConnectedNameWithIcon = (p: OwnProps) => {
const onOpenTracker = () => {
username && showUser(username, true)
}
const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const onOpenUserProfile = () => {
username && showUserProfile(username)
username && navToProfile(username)
}

let functionOnClick: NameWithIconProps['onClick']
Expand Down
5 changes: 2 additions & 3 deletions shared/common-adapters/profile-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {_setWithProfileCardPopup} from './usernames'
import FloatingMenu from './floating-menu'
import Icon from './icon'
import Meta from './meta'
import {useProfileState} from '@/stores/profile'
import {useFollowerState} from '@/stores/followers'
import {useCurrentUserState} from '@/stores/current-user'
import ProgressIndicator from './progress-indicator'
Expand All @@ -23,6 +22,7 @@ import {type default as FollowButtonType} from '../profile/user/actions/follow-b
import type ChatButtonType from '../chat/chat-button'
import {useTrackerState} from '@/stores/tracker'
import type {MeasureRef} from './measure-ref'
import {navToProfile} from '@/constants/router'

const positionFallbacks = ['top center', 'bottom center'] as const

Expand Down Expand Up @@ -178,9 +178,8 @@ const ProfileCard = ({
const changeFollow = useTrackerState(s => s.dispatch.changeFollow)
const _changeFollow = (follow: boolean) => changeFollow(userDetails.guiID, follow)

const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const openProfile = () => {
showUserProfile(username)
navToProfile(username)
onHide?.()
}

Expand Down
5 changes: 2 additions & 3 deletions shared/common-adapters/proof-broken-banner.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import * as C from '@/constants'
import {Banner, BannerParagraph} from './banner'
import {useTrackerState} from '@/stores/tracker'
import {useProfileState} from '@/stores/profile'
import {navToProfile} from '@/constants/router'

const Kb = {Banner}
type Props = {users?: Array<string>}
type ProofBrokenBannerNonEmptyProps = {users: Array<string>}

const ProofBrokenBannerNonEmpty = (props: ProofBrokenBannerNonEmptyProps) => {
const showUserProfile = useProfileState(s => s.dispatch.showUserProfile)
const showUser = useTrackerState(s => s.dispatch.showUser)
const onClickUsername = (username: string) => {
if (C.isMobile) {
showUserProfile(username)
navToProfile(username)
} else {
showUser(username, true)
}
Expand Down
4 changes: 2 additions & 2 deletions shared/common-adapters/usernames.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import type {TextType, Background, StylesTextCrossPlatform, AllowedColors, LineC
import type {e164ToDisplay as e164ToDisplayType} from '@/util/phone-numbers'
import {useTrackerState} from '@/stores/tracker'
import {useUsersState} from '@/stores/users'
import {useProfileState} from '@/stores/profile'
import {useFollowerState} from '@/stores/followers'
import {useCurrentUserState} from '@/stores/current-user'
import {navToProfile} from '@/constants/router'

export type User = {
username: string
Expand Down Expand Up @@ -99,7 +99,7 @@ function Username(p: UsernameProps) {
} else if (onUsernameClicked === 'profile') {
onClicked = (evt?: React.BaseSyntheticEvent) => {
evt?.stopPropagation()
useProfileState.getState().dispatch.showUserProfile(username)
navToProfile(username)
}
} else if (typeof onUsernameClicked === 'function') {
onClicked = () => onUsernameClicked(username)
Expand Down
9 changes: 4 additions & 5 deletions shared/constants/deeplinks.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import logger from '@/logger'
import * as T from '@/constants/types'
import {navigateAppend, navToThread, switchTab} from './router'
import {navigateAppend, navToProfile, navToThread, switchTab} from './router'
import * as Tabs from './tabs'
import {useChatState} from '@/stores/chat'
import {useProfileState} from '@/stores/profile'
import {useTeamsState} from '@/stores/teams'

const prefix = 'keybase://'
Expand Down Expand Up @@ -69,12 +68,12 @@ const handleKeybaseLink = (link: string) => {
case 'profile':
if (parts[1] === 'show' && parts[2]) {
switchTab(Tabs.peopleTab)
useProfileState.getState().dispatch.showUserProfile(parts[2])
navToProfile(parts[2])
return
}
if (parts[1] === 'new-proof' && (parts.length === 3 || parts.length === 4)) {
parts.length === 4 && parts[3] && useProfileState.getState().dispatch.showUserProfile(parts[3])
useProfileState.getState().dispatch.addProof(parts[2]!, 'appLink')
parts.length === 4 && parts[3] && navToProfile(parts[3])
navigateAppend({name: 'profileProofsList', params: {platform: parts[2]!, reason: 'appLink'}})
return
}
break
Expand Down
10 changes: 0 additions & 10 deletions shared/constants/init/index.desktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {useConfigState} from '@/stores/config'
import * as ConfigConstants from '@/stores/config'
import {useDaemonState} from '@/stores/daemon'
import {useFSState} from '@/stores/fs'
import {useProfileState} from '@/stores/profile'
import {useRouterState} from '@/stores/router'
import type * as EngineGen from '@/constants/rpc'
import * as T from '@/constants/types'
import InputMonitor from '@/util/platform-specific/input-monitor.desktop'
Expand Down Expand Up @@ -410,14 +408,6 @@ export const initPlatformListener = () => {
}
}))

useProfileState.setState(s => {
s.dispatch.editAvatar = () => {
useRouterState
.getState()
.dispatch.navigateAppend({name: 'profileEditAvatar', params: {image: undefined}})
}
})

useDaemonState.setState(s => {
s.dispatch.onRestartHandshakeNative = () => {
const {handshakeFailedReason} = useDaemonState.getState()
Expand Down
Loading