/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
shared/chat/conversation/normal/container.tsx
206 строк
7 KB
chrisnojima
build(mobile): harden gobuild.sh and go bind pipeline 2 (#29364)
08 июл 2026, 15:25
Не верифицирован
08 июл 2026, 15:25
19b55b3
Код
Авторство
О чём код?
import * as C from '@/constants' import {type State as ShellState, useShellState} from '@/stores/shell' import * as React from 'react' import {useEngineActionListener} from '@/engine/action-listener' import Normal from '.' import * as T from '@/constants/types' import {ThreadRefsProvider} from './context' import {OrangeLineContext, SetOrangeLineContext, useExplicitOrangeLineState} from '../orange-line-context' import {ChatTeamProvider} from '../team-hooks' import {ConversationCenterProvider} from '../center-context' import {ConversationInputProvider} from '../input-area/input-state' import { useConversationThreadID, useConversationThreadSelector, useThreadMeta, } from '../thread-context' import {ConversationThreadLoadStatusProvider} from '../thread-load-status-context' import {MaybeMentionProvider} from '@/common-adapters/markdown/maybe-mention/context' import {useChatThreadRouteParams} from '../thread-search-route' type OrangeLineState = { mobileAppState: ShellState['mobileAppState'] orangeLine: T.Chat.Ordinal } type OrangeLineKey = { conversationIDKey: T.Chat.ConversationIDKey mobileAppState: ShellState['mobileAppState'] } const noOrangeLine = T.Chat.numberToOrdinal(0) const getVisibleOrangeLine = ( state: OrangeLineState, mobileAppState: ShellState['mobileAppState'] ): T.Chat.Ordinal => { if (state.mobileAppState === mobileAppState || mobileAppState === 'active') { return state.orangeLine } return noOrangeLine } const useOrangeLine = ( id: T.Chat.ConversationIDKey, active: boolean, mobileAppState: ShellState['mobileAppState'] ) => { const [orangeLineState, setOrangeLineState] = React.useState<OrangeLineState>(() => ({ mobileAppState, orangeLine: noOrangeLine, })) const currentOrangeLineKeyRef = React.useRef<OrangeLineKey>({conversationIDKey: id, mobileAppState}) React.useLayoutEffect(() => { currentOrangeLineKeyRef.current = {conversationIDKey: id, mobileAppState} }, [id, mobileAppState]) const {maxVisibleMsgID, readMsgID} = useThreadMeta( C.useShallow(m => ({maxVisibleMsgID: m.maxVisibleMsgID, readMsgID: m.readMsgID})) ) // Keep the read position from when this conversation mounted. Mark-as-read updates // readMsgID shortly after navigation, but the open thread should retain its orange line. const [initialReadMsgID] = React.useState(() => readMsgID) const loadOrangeLine = React.useEffectEvent( (conversationIDKey: T.Chat.ConversationIDKey, readMsgID: T.Chat.MessageID) => { const f = async () => { const convID = T.Chat.keyToConversationID(conversationIDKey) const unreadlineRes = await T.RPCChat.localGetUnreadlineRpcPromise({ convID, identifyBehavior: T.RPCGen.TLFIdentifyBehavior.chatGui, readMsgID: readMsgID < 0 ? 0 : readMsgID, }) const nextOrangeLine = T.Chat.numberToOrdinal( unreadlineRes.unreadlineID ? unreadlineRes.unreadlineID : 0 ) const currentKey = currentOrangeLineKeyRef.current if (currentKey.conversationIDKey !== conversationIDKey) { return } setOrangeLineState(prev => { if (prev.orangeLine !== noOrangeLine) { return prev } return { mobileAppState: currentKey.mobileAppState, orangeLine: nextOrangeLine, } }) } C.ignorePromise(f()) } ) const loaded = useConversationThreadSelector(s => s.loaded) // Wait for loaded so the Go service has messages in its local cache React.useEffect(() => { if (loaded) { loadOrangeLine(id, initialReadMsgID) } }, [id, loaded, initialReadMsgID]) // just use the rpc for orange line if we're not active // if we are active we want to keep whatever state we had so it is maintained React.useEffect(() => { if (!active) { loadOrangeLine(id, readMsgID) } }, [maxVisibleMsgID, active, id, readMsgID]) const setOrangeLine = React.useEffectEvent((ordinal: T.Chat.Ordinal) => { const currentKey = currentOrangeLineKeyRef.current if (currentKey.conversationIDKey !== id) { return } setOrangeLineState({ mobileAppState: currentKey.mobileAppState, orangeLine: ordinal, }) }) const explicitOrangeLine = useExplicitOrangeLineState(s => s.updates.get(id)) const explicitOrangeLineVersionRef = React.useRef(explicitOrangeLine?.version ?? 0) React.useEffect(() => { if (!explicitOrangeLine || explicitOrangeLine.version <= explicitOrangeLineVersionRef.current) { return } explicitOrangeLineVersionRef.current = explicitOrangeLine.version setOrangeLine(explicitOrangeLine.ordinal) }, [explicitOrangeLine, id]) return {orangeLine: getVisibleOrangeLine(orangeLineState, mobileAppState), setOrangeLine} } const useShowManageChannels = () => { const navigateAppend = C.Router2.navigateAppend const {teamID, teamname} = useThreadMeta( C.useShallow(m => ({teamID: m.teamID, teamname: m.teamname})) ) useEngineActionListener('chat.1.chatUi.chatShowManageChannels', action => { if ( teamID && teamID !== T.Teams.noTeamID && teamname && action.payload.params.teamname === teamname ) { navigateAppend({name: 'teamAddToChannels', params: {teamID}}) } }) } type OrangeLineProviderProps = React.PropsWithChildren<{ active: boolean conversationIDKey: T.Chat.ConversationIDKey mobileAppState: ShellState['mobileAppState'] }> const NormalOrangeLineProvider = (props: OrangeLineProviderProps) => { const {active, children, conversationIDKey, mobileAppState} = props const {orangeLine, setOrangeLine} = useOrangeLine(conversationIDKey, active, mobileAppState) return ( <OrangeLineContext value={orangeLine}> <SetOrangeLineContext value={setOrangeLine}>{children}</SetOrangeLineContext> </OrangeLineContext> ) } const NormalWrapper = function NormalWrapper() { const conversationIDKey = useConversationThreadID() const {active, mobileAppState} = useShellState( C.useShallow(s => ({active: s.active, mobileAppState: s.mobileAppState})) ) const routeParams = useChatThreadRouteParams() const skipThreadLoadOnSelection = !!routeParams?.highlightMessageID const allowMarkReadOnLoad = !routeParams?.highlightMessageID && !routeParams?.threadSearch useShowManageChannels() return ( <MaybeMentionProvider> <NormalOrangeLineProvider key={conversationIDKey} active={active} conversationIDKey={conversationIDKey} mobileAppState={mobileAppState} > <ChatTeamProvider> <ConversationThreadLoadStatusProvider allowMarkReadOnLoad={allowMarkReadOnLoad} key={conversationIDKey} id={conversationIDKey} skipThreadLoadOnSelection={skipThreadLoadOnSelection} > <ConversationCenterProvider id={conversationIDKey}> <ConversationInputProvider key={conversationIDKey} id={conversationIDKey}> <ThreadRefsProvider> <Normal /> </ThreadRefsProvider> </ConversationInputProvider> </ConversationCenterProvider> </ConversationThreadLoadStatusProvider> </ChatTeamProvider> </NormalOrangeLineProvider> </MaybeMentionProvider> ) } export default NormalWrapper