Skip to content
Open

slim 18 #29099

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9f95622
team slice
chrisnojima-zoom Mar 31, 2026
ade25ee
WIP
chrisnojima-zoom Mar 31, 2026
2ec6f85
WIP
chrisnojima-zoom Mar 31, 2026
17aceac
WIP
chrisnojima-zoom Mar 31, 2026
a4394e1
WIP
chrisnojima-zoom Mar 31, 2026
fd4e03a
WIP
chrisnojima-zoom Mar 31, 2026
99cd892
WIP
chrisnojima-zoom Mar 31, 2026
d4a2dbc
WIP
chrisnojima-zoom Mar 31, 2026
b08f970
WIP
chrisnojima-zoom Mar 31, 2026
666e7b7
WIP
chrisnojima-zoom Mar 31, 2026
74f5743
WIP
chrisnojima-zoom Mar 31, 2026
135d84e
WIP
chrisnojima-zoom Mar 31, 2026
86583c9
WIP
chrisnojima-zoom Mar 31, 2026
2820b9f
WIP
chrisnojima-zoom Mar 31, 2026
41e227a
WIP
chrisnojima-zoom Mar 31, 2026
6dc8160
WIP
chrisnojima-zoom Mar 31, 2026
d164b03
WIP
chrisnojima-zoom Mar 31, 2026
8bb5a70
WIP
chrisnojima-zoom Mar 31, 2026
3b25ce6
WIP
chrisnojima-zoom Mar 31, 2026
9e656dd
WIP
chrisnojima-zoom Apr 1, 2026
5881a08
WIP
chrisnojima-zoom Apr 1, 2026
acfaa3f
WIP
chrisnojima-zoom Apr 1, 2026
9b31dcf
WIP
chrisnojima-zoom Apr 1, 2026
696e306
WIP
chrisnojima-zoom Apr 1, 2026
4d15853
WIP
chrisnojima-zoom Apr 1, 2026
51e7bb0
WIP
chrisnojima-zoom Apr 1, 2026
bb57e3e
WIP
chrisnojima-zoom Apr 1, 2026
c53888e
WIP
chrisnojima-zoom Apr 1, 2026
9611dfb
WIP
chrisnojima-zoom Apr 1, 2026
9ec65f0
WIP
chrisnojima-zoom Apr 1, 2026
e34b11f
WIP
chrisnojima-zoom Apr 1, 2026
7ac7909
WIP
chrisnojima-zoom Apr 1, 2026
7d40855
WIP
chrisnojima-zoom Apr 1, 2026
611ce24
WIP
chrisnojima-zoom Apr 1, 2026
81a77df
WIP
chrisnojima-zoom Apr 1, 2026
af5baaf
WIP
chrisnojima-zoom Apr 1, 2026
bbb7bd0
WIP
chrisnojima-zoom Apr 1, 2026
08f2b0e
WIP
chrisnojima-zoom Apr 1, 2026
3cc5650
WIP
chrisnojima-zoom Apr 1, 2026
cf77bc0
WIP
chrisnojima-zoom Apr 1, 2026
5053e73
WIP
chrisnojima-zoom Apr 1, 2026
f698324
WIP
chrisnojima-zoom Apr 1, 2026
b5b59f2
WIP
chrisnojima-zoom Apr 1, 2026
0ca6f11
WIP
chrisnojima-zoom Apr 1, 2026
3b3daf7
WIP
chrisnojima Apr 2, 2026
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 AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
- 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.
- Do not use `navigation.setOptions` for header state in this repo. Pass header-driving state through route params so `getOptions` can read it synchronously, or use [`shared/stores/modal-header.tsx`](/Users/ChrisNojima/SourceCode/go/src/github.com/keybase/client/shared/stores/modal-header.tsx) when the flow already uses the shared modal header mechanism.
- Components must not mutate Zustand stores directly with `useXState.setState`, `getState()`-based writes, or similar ad hoc store mutation. If a component needs to affect store state, route it through a store dispatch action or move the state out of the store.
- 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.
4 changes: 2 additions & 2 deletions shared/app/global-errors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ const useData = () => {
setGlobalError()
if (loggedIn) {
clearModals()
navigateAppend(settingsFeedbackTab)
navigateAppend({name: settingsFeedbackTab, params: {}})
} else {
navigateAppend('feedback')
navigateAppend({name: 'feedback', params: {}})
}
}
const onDismiss = () => {
Expand Down
2 changes: 1 addition & 1 deletion shared/chat/conversation/bot/install.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ const InstallBotPopup = (props: Props) => {
})
}
const onFeedback = () => {
navigateAppend('feedback')
navigateAppend({name: 'feedback', params: {}})
}

const refreshBotSettings = Chat.useChatContext(s => s.dispatch.refreshBotSettings)
Expand Down
2 changes: 1 addition & 1 deletion shared/chat/conversation/header-area/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {GetOptionsRet} from '@/constants/types/router'

declare function headerNavigationOptions(route: {
params: {conversationIDKey?: string}
params?: {conversationIDKey?: string}
}): Partial<GetOptionsRet>
export {headerNavigationOptions}
3 changes: 2 additions & 1 deletion shared/chat/conversation/input-area/normal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ const doInjectText = (inputRef: React.RefObject<InputRef | null>, text: string,

const ConnectedPlatformInput = function ConnectedPlatformInput() {
const route = useRoute<RootRouteProps<'chatConversation'> | RootRouteProps<'chatRoot'>>()
const infoPanelShowing = route.name === 'chatRoot' ? !!route.params?.infoPanel : false
const infoPanelShowing =
route.name === 'chatRoot' && 'infoPanel' in route.params ? !!route.params.infoPanel : false
const data = Chat.useChatContext(
C.useShallow(s => {
const {meta, id: conversationIDKey, editing: editOrdinal, messageMap, unsentText} = s
Expand Down
2 changes: 1 addition & 1 deletion shared/chat/conversation/messages/text/coinflip/errors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const CoinFlipError = (props: Props) => {
const CoinFlipGenericError = () => {
const navigateAppend = C.Router2.navigateAppend
const sendFeedback = () => {
navigateAppend('modalFeedback')
navigateAppend({name: 'modalFeedback', params: {}})
}
return (
<Kb.Text selectable={true} style={styles.error} type="BodySmall">
Expand Down
23 changes: 11 additions & 12 deletions shared/chat/inbox-and-conversation-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,30 @@ import * as Kb from '@/common-adapters'
import type {StyleOverride} from '@/common-adapters/markdown'
import SearchRow from './inbox/search-row'
import NewChatButton from './inbox/new-chat-button'
import {useRoute} from '@react-navigation/native'
import type {RootRouteProps} from '@/router-v2/route-params'
import {useRoute, type RouteProp} from '@react-navigation/native'
import {useUsersState} from '@/stores/users'
import {useCurrentUserState} from '@/stores/current-user'
import * as Teams from '@/stores/teams'

type ChatRootParams = {
conversationIDKey?: string
infoPanel?: object
}
type ChatRootRoute = RouteProp<{chatRoot: ChatRootParams}, 'chatRoot'>

const Header = () => {
const {params} = useRoute<RootRouteProps<'chatRoot'>>()
const {params} = useRoute<ChatRootRoute>()
return (
<Chat.ChatProvider
canBeNull={true}
id={
// eslint-disable-next-line
(params as {conversationIDKey?: string} | undefined)?.conversationIDKey ?? Chat.noConversationIDKey
}
>
<Chat.ChatProvider canBeNull={true} id={params.conversationIDKey ?? Chat.noConversationIDKey}>
<Header2 />
</Chat.ChatProvider>
)
}

const Header2 = () => {
const {params} = useRoute<RootRouteProps<'chatRoot'>>()
const {params} = useRoute<ChatRootRoute>()
const username = useCurrentUserState(s => s.username)
const infoPanelShowing = !!params?.infoPanel
const infoPanelShowing = !!params.infoPanel
const data = Chat.useChatContext(
C.useShallow(s => {
const {meta, id, dispatch} = s
Expand Down
6 changes: 3 additions & 3 deletions shared/chat/inbox-search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,14 @@ const OpenTeamRow = (p: OpenTeamProps) => {
const [hovering, setHovering] = React.useState(false)
const {name, description, memberCount, publicAdmins, inTeam, isSelected} = p
const showingDueToSelect = React.useRef(false)
const {joinTeam, showTeamByName} = useTeamsState(
const {showTeamByName} = useTeamsState(
C.useShallow(s => ({
joinTeam: s.dispatch.joinTeam,
showTeamByName: s.dispatch.showTeamByName,
}))
)

const clearModals = C.Router2.clearModals
const navigateAppend = C.Router2.navigateAppend
const makePopup = (p: Kb.Popup2Parms) => {
const {attachTo, hidePopup} = p
return (
Expand All @@ -402,7 +402,7 @@ const OpenTeamRow = (p: OpenTeamProps) => {
position="right center"
onChat={undefined}
onHidden={hidePopup}
onJoinTeam={() => joinTeam(name)}
onJoinTeam={() => navigateAppend({name: 'teamJoinTeamDialog', params: {initialTeamname: name}})}
onViewTeam={() => {
clearModals()
showTeamByName(name)
Expand Down
2 changes: 1 addition & 1 deletion shared/chat/inbox/row/build-team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function BuildTeam() {
launchNewTeamWizardOrModal()
}
const onJoinTeam = () => {
nav.safeNavigateAppend('teamJoinTeamDialog')
nav.safeNavigateAppend({name: 'teamJoinTeamDialog', params: {}})
}

return (
Expand Down
6 changes: 0 additions & 6 deletions shared/chat/new-team-dialog-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,21 @@ import * as C from '@/constants'
import * as Chat from '@/stores/chat'
import {CreateNewTeam} from '../teams/new-team'
import {useTeamsState} from '@/stores/teams'
import upperFirst from 'lodash/upperFirst'

const NewTeamDialog = () => {
const conversationIDKey = Chat.useChatContext(s => s.id)
const baseTeam = ''
const errorText = useTeamsState(s => upperFirst(s.errorInTeamCreation))
const navigateUp = C.Router2.navigateUp
const onCancel = () => {
navigateUp()
}
const resetErrorInTeamCreation = useTeamsState(s => s.dispatch.resetErrorInTeamCreation)
const createNewTeamFromConversation = useTeamsState(s => s.dispatch.createNewTeamFromConversation)
const onClearError = resetErrorInTeamCreation
const onSubmit = (teamname: string) => {
createNewTeamFromConversation(conversationIDKey, teamname)
}
const props = {
baseTeam,
errorText,
onCancel,
onClearError,
onSubmit,
}
return <CreateNewTeam {...props} />
Expand Down
100 changes: 76 additions & 24 deletions shared/chat/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,46 @@ import {useModalHeaderState} from '@/stores/modal-header'
import {ModalTitle} from '@/teams/common'
import inboxGetOptions from './inbox/get-options'
import inboxAndConvoGetOptions from './inbox-and-conversation-get-options'
import {defineRouteMap} from '@/constants/types/router'
import type {BlockModalContext} from './blocking/block-modal'
const Convo = React.lazy(async () => import('./conversation/container'))

type ChatAddToChannelRouteParams = {
conversationIDKey?: T.Chat.ConversationIDKey
teamID: T.Teams.TeamID
}
type ChatBlockingRouteParams = {
blockUserByDefault?: boolean
filterUserByDefault?: boolean
flagUserByDefault?: boolean
reportsUserByDefault?: boolean
context?: BlockModalContext
conversationIDKey?: T.Chat.ConversationIDKey
others?: Array<string>
team?: string
username?: string
}
type ChatConfirmRemoveBotRouteParams = {
botUsername: string
teamID?: T.Teams.TeamID
conversationIDKey?: T.Chat.ConversationIDKey
}
type ChatInstallBotRouteParams = {
botUsername: string
conversationIDKey?: T.Chat.ConversationIDKey
teamID?: T.Teams.TeamID
}
type ChatSearchBotsRouteParams = {
teamID?: T.Teams.TeamID
conversationIDKey?: T.Chat.ConversationIDKey
}
type ChatShowNewTeamDialogRouteParams = {
conversationIDKey?: T.Chat.ConversationIDKey
}
const emptyChatBlockingRouteParams: ChatBlockingRouteParams = {}
const emptyChatSearchBotsRouteParams: ChatSearchBotsRouteParams = {}
const emptyChatShowNewTeamDialogRouteParams: ChatShowNewTeamDialogRouteParams = {}

const PDFShareButton = ({url}: {url?: string}) => {
const showShareActionSheet = useConfigState(s => s.dispatch.defer.showShareActionSheet)
return (
Expand Down Expand Up @@ -86,7 +124,7 @@ const SendToChatHeaderLeft = ({canBack}: {canBack?: boolean}) => {
return <Kb.Text type="BodyBigLink" onClick={clearModals}>Cancel</Kb.Text>
}

export const newRoutes = {
export const newRoutes = defineRouteMap({
chatConversation: Chat.makeChatScreen(Convo, {
canBeNullConvoID: true,
getOptions: p => ({
Expand All @@ -98,17 +136,23 @@ export const newRoutes = {
screen: React.lazy(async () => import('./conversation/rekey/enter-paper-key')),
},
chatRoot: Chat.isSplit
? Chat.makeChatScreen(
React.lazy(async () => import('./inbox-and-conversation')),
{getOptions: inboxAndConvoGetOptions, skipProvider: true}
)
: Chat.makeChatScreen(
React.lazy(async () => import('./inbox/defer-loading')),
{getOptions: inboxGetOptions, skipProvider: true}
),
}
? {
...Chat.makeChatScreen(React.lazy(async () => import('./inbox-and-conversation')), {
getOptions: inboxAndConvoGetOptions,
skipProvider: true,
}),
initialParams: {},
}
: {
...Chat.makeChatScreen(React.lazy(async () => import('./inbox/defer-loading')), {
getOptions: inboxGetOptions,
skipProvider: true,
}),
initialParams: {},
},
})

export const newModalRoutes = {
export const newModalRoutes = defineRouteMap({
chatAddToChannel: Chat.makeChatScreen(
React.lazy(async () => import('./conversation/info-panel/add-to-channel')),
{
Expand All @@ -134,20 +178,22 @@ export const newModalRoutes = {
React.lazy(async () => import('./conversation/attachment-get-titles')),
{getOptions: {modalStyle: {height: 660, maxHeight: 660}}}
),
chatBlockingModal: Chat.makeChatScreen(React.lazy(async () => import('./blocking/block-modal')), {
getOptions: {headerTitle: () => <Kb.Icon type="iconfont-user-block" sizeType="Big" color={Kb.Styles.globalColors.red} />},
}),
chatBlockingModal: {
...Chat.makeChatScreen(React.lazy(async () => import('./blocking/block-modal')), {
getOptions: {
headerTitle: () => <Kb.Icon type="iconfont-user-block" sizeType="Big" color={Kb.Styles.globalColors.red} />,
},
}),
initialParams: emptyChatBlockingRouteParams,
},
chatChooseEmoji: Chat.makeChatScreen(React.lazy(async () => import('./emoji-picker/container')), {
getOptions: {headerShown: false},
}),
chatConfirmNavigateExternal: Chat.makeChatScreen(
React.lazy(async () => import('./punycode-link-warning')),
{skipProvider: true}
),
chatConfirmRemoveBot: Chat.makeChatScreen(
React.lazy(async () => import('./conversation/bot/confirm')),
{canBeNullConvoID: true}
),
chatConfirmRemoveBot: Chat.makeChatScreen(React.lazy(async () => import('./conversation/bot/confirm')), {canBeNullConvoID: true}),
chatCreateChannel: Chat.makeChatScreen(
React.lazy(async () => import('./create-channel')),
{skipProvider: true}
Expand Down Expand Up @@ -194,10 +240,13 @@ export const newModalRoutes = {
overlayStyle: {alignSelf: 'stretch'},
}),
}),
chatSearchBots: Chat.makeChatScreen(
React.lazy(async () => import('./conversation/bot/search')),
{canBeNullConvoID: true, getOptions: {title: 'Add a bot'}}
),
chatSearchBots: {
...Chat.makeChatScreen(React.lazy(async () => import('./conversation/bot/search')), {
canBeNullConvoID: true,
getOptions: {title: 'Add a bot'},
}),
initialParams: emptyChatSearchBotsRouteParams,
},
chatSendToChat: Chat.makeChatScreen(
React.lazy(async () => import('./send-to-chat')),
{
Expand All @@ -208,9 +257,12 @@ export const newModalRoutes = {
skipProvider: true,
}
),
chatShowNewTeamDialog: Chat.makeChatScreen(React.lazy(async () => import('./new-team-dialog-container'))),
chatShowNewTeamDialog: {
...Chat.makeChatScreen(React.lazy(async () => import('./new-team-dialog-container'))),
initialParams: emptyChatShowNewTeamDialogRouteParams,
},
chatUnfurlMapPopup: Chat.makeChatScreen(
React.lazy(async () => import('./conversation/messages/text/unfurl/unfurl-list/map-popup')),
{getOptions: {title: 'Location'}}
),
}
})
5 changes: 3 additions & 2 deletions shared/common-adapters/markdown/maybe-mention/team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ const TeamMention = (ownProps: OwnProps) => {
const previewConversation = Chat.useChatState(s => s.dispatch.previewConversation)
const showTeamByName = useTeamsState(s => s.dispatch.showTeamByName)
const clearModals = C.Router2.clearModals
const navigateAppend = C.Router2.navigateAppend
const _onViewTeam = (teamname: string) => {
clearModals()
showTeamByName(teamname)
}
const joinTeam = useTeamsState(s => s.dispatch.joinTeam)
const onJoinTeam = joinTeam
const onJoinTeam = (teamname: string) =>
navigateAppend({name: 'teamJoinTeamDialog', params: {initialTeamname: teamname}})

const convID = _convID ? T.Chat.stringToConversationIDKey(_convID) : undefined
const onChat = convID
Expand Down
4 changes: 2 additions & 2 deletions shared/common-adapters/reload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ const ReloadContainer = (ownProps: OwnProps) => {
const _onFeedback = (loggedIn: boolean) => {
if (loggedIn) {
navigateAppend(C.Tabs.settingsTab)
navigateAppend(settingsFeedbackTab)
navigateAppend({name: settingsFeedbackTab, params: {}})
} else {
navigateAppend('feedback')
navigateAppend({name: 'feedback', params: {}})
}
}

Expand Down
4 changes: 1 addition & 3 deletions shared/common-adapters/team-with-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,6 @@ const ConnectedTeamWithPopup = (ownProps: OwnProps) => {
memberCount: meta.memberCount,
teamID,
}
const joinTeam = Teams.useTeamsState(s => s.dispatch.joinTeam)
const _onJoinTeam = joinTeam
const clearModals = C.Router2.clearModals
const navigateAppend = C.Router2.navigateAppend
const _onViewTeam = (teamID: T.Teams.TeamID) => {
Expand All @@ -129,7 +127,7 @@ const ConnectedTeamWithPopup = (ownProps: OwnProps) => {
isMember: stateProps.isMember,
isOpen: stateProps.isOpen,
memberCount: stateProps.memberCount,
onJoinTeam: () => _onJoinTeam(ownProps.teamName),
onJoinTeam: () => navigateAppend({name: 'teamJoinTeamDialog', params: {initialTeamname: ownProps.teamName}}),
onViewTeam: () => _onViewTeam(stateProps.teamID),
prefix: ownProps.prefix,
shouldLoadTeam: ownProps.shouldLoadTeam,
Expand Down
2 changes: 1 addition & 1 deletion shared/constants/deeplinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ const handleKeybaseLink = (link: string) => {
}
break
case 'team-invite-link':
useTeamsState.getState().dispatch.openInviteLink(parts[1] ?? '', parts[2] || '')
navigateAppend({name: 'teamInviteLinkJoin', params: {inviteID: parts[1] ?? '', inviteKey: parts[2] || ''}})
return
default:
break
Expand Down
2 changes: 1 addition & 1 deletion shared/constants/init/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ export const initPlatformListener = () => {
routeName = cur
}
const ap = getVisiblePath()
ap.some(r => {
ap.some((r: ReturnType<typeof getVisiblePath>[number]) => {
if (r.name === 'chatConversation') {
const rParams = r.params as undefined | {conversationIDKey?: T.Chat.ConversationIDKey}
param = {selectedConversationIDKey: rParams?.conversationIDKey}
Expand Down
Loading