@@ -10,7 +10,9 @@ import {
1010} from 'react'
1111import { useShallow } from 'zustand/react/shallow'
1212
13+ import { getAdsEnabled } from './commands/ads'
1314import { routeUserPrompt , addBashMessageToHistory } from './commands/router'
15+ import { AdBanner } from './components/ad-banner'
1416import { ChatInputBar } from './components/chat-input-bar'
1517import { LoadPreviousButton } from './components/load-previous-button'
1618import { MessageWithAgents } from './components/message-with-agents'
@@ -29,6 +31,7 @@ import {
2931import { useClipboard } from './hooks/use-clipboard'
3032import { useConnectionStatus } from './hooks/use-connection-status'
3133import { useElapsedTime } from './hooks/use-elapsed-time'
34+ import { useGravityAd } from './hooks/use-gravity-ad'
3235import { useEvent } from './hooks/use-event'
3336import { useExitHandler } from './hooks/use-exit-handler'
3437import { useInputHistory } from './hooks/use-input-history'
@@ -230,6 +233,7 @@ export const Chat = ({
230233
231234 const isConnected = useConnectionStatus ( handleReconnection )
232235 const mainAgentTimer = useElapsedTime ( )
236+ const { ad, reportActivity } = useGravityAd ( )
233237 const timerStartTime = mainAgentTimer . startTime
234238
235239 // Set initial mode from CLI flag on mount
@@ -415,6 +419,16 @@ export const Chat = ({
415419 const setInputMode = useChatStore ( ( state ) => state . setInputMode )
416420 const askUserState = useChatStore ( ( state ) => state . askUserState )
417421
422+ // Filter slash commands based on current ads state - only show the option that changes state
423+ const filteredSlashCommands = useMemo ( ( ) => {
424+ const adsEnabled = getAdsEnabled ( )
425+ return SLASH_COMMANDS . filter ( ( cmd ) => {
426+ if ( cmd . id === 'ads:enable' ) return ! adsEnabled
427+ if ( cmd . id === 'ads:disable' ) return adsEnabled
428+ return true
429+ } )
430+ } , [ inputValue ] ) // Re-evaluate when input changes (user may have just toggled)
431+
418432 const {
419433 slashContext,
420434 mentionContext,
@@ -428,7 +442,7 @@ export const Chat = ({
428442 disableAgentSuggestions : forceFileOnlyMentions || inputMode !== 'default' ,
429443 inputValue : inputMode === 'bash' ? '' : inputValue ,
430444 cursorPosition,
431- slashCommands : SLASH_COMMANDS ,
445+ slashCommands : filteredSlashCommands ,
432446 localAgents,
433447 fileTree,
434448 currentAgentMode : agentMode ,
@@ -872,6 +886,17 @@ export const Chat = ({
872886 useEffect ( ( ) => {
873887 inputValueRef . current = inputValue
874888 } , [ inputValue ] )
889+
890+ // Report activity on input changes for ad rotation (debounced via separate effect)
891+ const lastReportedActivityRef = useRef < number > ( 0 )
892+ useEffect ( ( ) => {
893+ const now = Date . now ( )
894+ // Throttle to max once per second to avoid excessive calls
895+ if ( now - lastReportedActivityRef . current > 1000 ) {
896+ lastReportedActivityRef . current = now
897+ reportActivity ( )
898+ }
899+ } , [ inputValue , reportActivity ] )
875900 useEffect ( ( ) => {
876901 cursorPositionRef . current = cursorPosition
877902 } , [ cursorPosition ] )
@@ -944,9 +969,11 @@ export const Chat = ({
944969 } , [ feedbackMode , askUserState , inputRef ] )
945970
946971 const handleSubmit = useCallback ( async ( ) => {
972+ // Report activity for ad rotation
973+ reportActivity ( )
947974 const result = await onSubmitPrompt ( inputValue , agentMode )
948975 handleCommandResult ( result )
949- } , [ onSubmitPrompt , inputValue , agentMode , handleCommandResult ] )
976+ } , [ onSubmitPrompt , inputValue , agentMode , handleCommandResult , reportActivity ] )
950977
951978 const totalMentionMatches = agentMatches . length + fileMatches . length
952979 const historyNavUpEnabled =
@@ -1325,8 +1352,20 @@ export const Chat = ({
13251352 ! feedbackMode &&
13261353 ( hasStatusIndicatorContent || shouldShowQueuePreview || ! isAtBottom )
13271354
1355+ // Track mouse movement for ad activity (throttled)
1356+ const lastMouseActivityRef = useRef < number > ( 0 )
1357+ const handleMouseActivity = useCallback ( ( ) => {
1358+ const now = Date . now ( )
1359+ // Throttle to max once per second
1360+ if ( now - lastMouseActivityRef . current > 1000 ) {
1361+ lastMouseActivityRef . current = now
1362+ reportActivity ( )
1363+ }
1364+ } , [ reportActivity ] )
1365+
13281366 return (
13291367 < box
1368+ onMouseMove = { handleMouseActivity }
13301369 style = { {
13311370 flexDirection : 'column' ,
13321371 gap : 0 ,
@@ -1429,6 +1468,8 @@ export const Chat = ({
14291468 />
14301469 ) }
14311470
1471+ { ad && getAdsEnabled ( ) && < AdBanner ad = { ad } /> }
1472+
14321473 < ChatInputBar
14331474 inputValue = { inputValue }
14341475 cursorPosition = { cursorPosition }
0 commit comments