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
Expand Up @@ -4,6 +4,7 @@
- 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 using mount guards like `mountedRef`/`isMountedRef`, always set the ref to `true` inside the effect body and set it to `false` in cleanup. Never rely on `useRef(true)` alone across the component lifetime, because Strict Mode remounts can leave the guard stuck `false` and silently drop async results.
- When a component reads multiple adjacent values from the same store hook, prefer a consolidated selector with `C.useShallow(...)` instead of multiple separate subscriptions.
- Keep types accurate. Do not use casts or misleading annotations to mask a real type mismatch just to get around an issue; fix the type or fix the implementation.
- 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.
- During refactors, do not delete existing guards, conditionals, or platform/test-specific behavior unless you have proven they are dead and the user asked for that behavior change. Port checks like `androidIsTestDevice` forward into the new code path instead of silently dropping them.
- When addressing PR or review feedback, including bot or lint-style suggestions, do not apply it mechanically. Verify that the reported issue is real in this codebase and that the proposed fix is consistent with repo rules and improves correctness, behavior, or maintainability before making changes.
2 changes: 1 addition & 1 deletion shared/constants/types/team-building.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export type SearchKey = Array<SearchString /*| ServiceIdWithContact*/>
// Keyed so that we never get results that don't match the user's input (e.g. outdated results)
export type Query = string

export type SearchResults = Map<Query, Map<ServiceIdWithContact, Array<User>>>
export type SearchResults = Map<Query, Map<ServiceIdWithContact, ReadonlyArray<User>>>
export type ServiceResultCount = Map<SearchString, Map<ServiceIdWithContact, number>>

export type SelectedUser = {
Expand Down
31 changes: 22 additions & 9 deletions shared/team-building/contacts.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import * as React from 'react'
import * as C from '@/constants'
import * as Kb from '@/common-adapters'
import type * as T from '@/constants/types'
import {useSettingsContactsState} from '@/stores/settings-contacts'
import {useTBContext} from '@/stores/team-building'

const useContactsProps = () => {
const contactsImported = useSettingsContactsState(s => s.importEnabled)
const contactsPermissionStatus = useSettingsContactsState(s => s.permissionStatus)
const isImportPromptDismissed = useSettingsContactsState(s => s.importPromptDismissed)
const numContactsImported = useSettingsContactsState(s => s.importedCount || 0)

const importContactsLater = useSettingsContactsState(s => s.dispatch.importContactsLater)
const loadContactImportEnabled = useSettingsContactsState(s => s.dispatch.loadContactImportEnabled)
const editContactImportEnabled = useSettingsContactsState(s => s.dispatch.editContactImportEnabled)
const requestPermissions = useSettingsContactsState(s => s.dispatch.requestPermissions)
const {
contactsImported,
contactsPermissionStatus,
editContactImportEnabled,
importContactsLater,
isImportPromptDismissed,
loadContactImportEnabled,
numContactsImported,
requestPermissions,
} = useSettingsContactsState(
C.useShallow(s => ({
contactsImported: s.importEnabled,
contactsPermissionStatus: s.permissionStatus,
editContactImportEnabled: s.dispatch.editContactImportEnabled,
importContactsLater: s.dispatch.importContactsLater,
isImportPromptDismissed: s.importPromptDismissed,
loadContactImportEnabled: s.dispatch.loadContactImportEnabled,
numContactsImported: s.importedCount || 0,
requestPermissions: s.dispatch.requestPermissions,
}))
)

const onAskForContactsLater = importContactsLater
const onLoadContactsSetting = loadContactImportEnabled
Expand Down
12 changes: 7 additions & 5 deletions shared/team-building/filtered-service-tab-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import type * as T from '@/constants/types'
import {ServiceTabBar} from './service-tab-bar'
import * as TeamBuilding from '@/stores/team-building'

const getVisibleServices = (filterServices?: Array<T.TB.ServiceIdWithContact>) =>
filterServices
? TeamBuilding.allServices.filter(serviceId => filterServices.includes(serviceId))
: TeamBuilding.allServices

export const FilteredServiceTabBar = (
props: Omit<React.ComponentPropsWithoutRef<typeof ServiceTabBar>, 'services'> & {
filterServices?: Array<T.TB.ServiceIdWithContact>
}
) => {
const {selectedService, onChangeService} = props
const {servicesShown, minimalBorder, offset, filterServices} = props
const {selectedService, onChangeService, servicesShown, minimalBorder, offset, filterServices} = props
const services = getVisibleServices(filterServices)

const services = filterServices
? TeamBuilding.allServices.filter(serviceId => filterServices.includes(serviceId))
: TeamBuilding.allServices
return services.length === 1 && services[0] === 'keybase' ? null : (
<ServiceTabBar
services={services}
Expand Down
Loading