Skip to content

Commit 29f47e7

Browse files
authored
refactor: remove no ai feed flag (#5885)
1 parent ccde725 commit 29f47e7

File tree

13 files changed

+6
-614
lines changed

13 files changed

+6
-614
lines changed

packages/shared/src/components/MainFeedLayout.tsx

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ import { checkIsExtension } from '../lib/func';
7575
import { useReadingReminderHero } from '../hooks/notifications/useReadingReminderHero';
7676
import { useTrackQuestClientEvent } from '../hooks/useTrackQuestClientEvent';
7777
import { useReadingReminderVariation } from '../hooks/notifications/useReadingReminderVariation';
78-
import { useNoAiFeed } from '../hooks/useNoAiFeed';
7978

8079
const FeedExploreHeader = dynamic(
8180
() =>
@@ -225,8 +224,6 @@ export default function MainFeedLayout({
225224
hasUser: !!user,
226225
});
227226
const { isCustomDefaultFeed, defaultFeedId } = useCustomDefaultFeed();
228-
const shouldEvaluateNoAi =
229-
feedName === SharedFeedPage.MyFeed && !isCustomDefaultFeed;
230227
const isLaptop = useViewSize(ViewSize.Laptop);
231228
const feedVersion = useFeature(feature.feedVersion);
232229
const { time, contentCurationFilter } = useSearchContextProvider();
@@ -306,14 +303,6 @@ export default function MainFeedLayout({
306303
feature: featureFeedV2Highlights,
307304
shouldEvaluate: shouldEvaluateFeedV2Highlights,
308305
});
309-
const {
310-
isNoAi,
311-
isNoAiAvailable,
312-
isLoaded: isNoAiLoaded,
313-
toggleNoAi,
314-
} = useNoAiFeed({
315-
shouldEvaluate: shouldEvaluateNoAi,
316-
});
317306

318307
const { isSearchPageLaptop } = useSearchResultsLayout();
319308

@@ -389,7 +378,6 @@ export default function MainFeedLayout({
389378
highlightsLimit: FEED_V2_HIGHLIGHTS_LIMIT,
390379
}
391380
: {}),
392-
...(shouldEvaluateNoAi && isNoAi ? { noAi: true } : {}),
393381
version:
394382
isDevelopment && !isProductionAPI
395383
? 1
@@ -411,8 +399,6 @@ export default function MainFeedLayout({
411399
tokenRefreshed,
412400
feedVersion,
413401
isFeedV2HighlightsEnabled,
414-
isNoAi,
415-
shouldEvaluateNoAi,
416402
]);
417403

418404
const [selectedAlgo, setSelectedAlgo, loadedAlgo] = usePersistentContext(
@@ -465,10 +451,6 @@ export default function MainFeedLayout({
465451
return null;
466452
}
467453

468-
if (shouldEvaluateNoAi && !isNoAiLoaded) {
469-
return null;
470-
}
471-
472454
if (feedNameProp === 'default' && isCustomDefaultFeed) {
473455
if (!defaultFeedId) {
474456
return null;
@@ -491,15 +473,6 @@ export default function MainFeedLayout({
491473
<SearchControlHeader
492474
algoState={[selectedAlgo, handleSelectedAlgoChange]}
493475
feedName={feedName}
494-
noAiState={
495-
shouldEvaluateNoAi
496-
? {
497-
isAvailable: isNoAiAvailable,
498-
isEnabled: isNoAi,
499-
onToggle: toggleNoAi,
500-
}
501-
: undefined
502-
}
503476
/>
504477
),
505478
};
@@ -579,15 +552,6 @@ export default function MainFeedLayout({
579552
<SearchControlHeader
580553
algoState={[selectedAlgo, handleSelectedAlgoChange]}
581554
feedName={feedName}
582-
noAiState={
583-
shouldEvaluateNoAi
584-
? {
585-
isAvailable: isNoAiAvailable,
586-
isEnabled: isNoAi,
587-
onToggle: toggleNoAi,
588-
}
589-
: undefined
590-
}
591555
/>
592556
),
593557
};
@@ -619,11 +583,6 @@ export default function MainFeedLayout({
619583
isLaptop,
620584
loadedAlgo,
621585
tokenRefreshed,
622-
shouldEvaluateNoAi,
623-
isNoAiLoaded,
624-
isNoAiAvailable,
625-
isNoAi,
626-
toggleNoAi,
627586
]);
628587

629588
useEffect(() => {

packages/shared/src/components/feeds/FeedSettings/sections/FeedSettingsContentPreferencesSection.tsx

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ import React, { useContext, useMemo } from 'react';
33
import { FeedSettingsEditContext } from '../FeedSettingsEditContext';
44
import useFeedSettings from '../../../../hooks/useFeedSettings';
55
import { useAdvancedSettings } from '../../../../hooks/feed/useAdvancedSettings';
6-
import { useConditionalFeature, useToastNotification } from '../../../../hooks';
7-
import { useLogContext } from '../../../../contexts/LogContext';
8-
import { useSettingsContext } from '../../../../contexts/SettingsContext';
96
import {
107
getAdvancedContentTypes,
118
getContentCurationList,
@@ -17,33 +14,21 @@ import {
1714
TypographyType,
1815
} from '../../../typography/Typography';
1916
import { FilterCheckbox } from '../../../fields/FilterCheckbox';
20-
import { Switch } from '../../../fields/Switch';
2117
import { FeedType } from '../../../../graphql/feed';
22-
import { featureNoAiFeed } from '../../../../lib/featureManagement';
23-
import { SidebarSettingsFlags } from '../../../../graphql/settings';
24-
import { labels } from '../../../../lib/labels';
25-
import { LogEvent, Origin, TargetId } from '../../../../lib/log';
2618

2719
export const TOGGLEABLE_TYPES = ['Videos', 'Polls', 'Social'];
2820
const CUSTOM_FEEDS_ONLY = ['Article'];
2921
const ADVANCED_SETTINGS_KEY = 'advancedSettings';
3022

3123
export const FeedSettingsContentPreferencesSection = (): ReactElement => {
3224
const { feed, editFeedSettings } = useContext(FeedSettingsEditContext);
33-
const { flags, updateFlag } = useSettingsContext();
34-
const { displayToast } = useToastNotification();
35-
const { logEvent } = useLogContext();
3625
const { advancedSettings } = useFeedSettings({ feedId: feed?.id });
3726
const {
3827
selectedSettings,
3928
onToggleSettings,
4029
checkSourceBlocked,
4130
onToggleSource,
4231
} = useAdvancedSettings({ feedId: feed?.id });
43-
const { value: isNoAiFeatureEnabled } = useConditionalFeature({
44-
feature: featureNoAiFeed,
45-
shouldEvaluate: feed?.type === FeedType.Main,
46-
});
4732
const toggleableTypes = useMemo(
4833
() =>
4934
getAdvancedContentTypes(
@@ -113,47 +98,6 @@ export const FeedSettingsContentPreferencesSection = (): ReactElement => {
11398
})}
11499
</div>
115100
</div>
116-
{feed?.type === FeedType.Main && isNoAiFeatureEnabled && (
117-
<div className="flex flex-col gap-4">
118-
<div className="flex flex-col gap-1">
119-
<Typography bold type={TypographyType.Body}>
120-
No AI mode
121-
</Typography>
122-
<Typography
123-
type={TypographyType.Callout}
124-
color={TypographyColor.Tertiary}
125-
>
126-
Keep AI topics filtered out across My Feed. You can hide the
127-
homepage toggle once this is set.
128-
</Typography>
129-
</div>
130-
<Switch
131-
inputId="no-ai-feed-preference-switch"
132-
name="no_ai_feed_preference"
133-
compact={false}
134-
checked={flags?.noAiFeedEnabled ?? false}
135-
onClick={() => {
136-
const newState = !(flags?.noAiFeedEnabled ?? false);
137-
138-
editFeedSettings(() =>
139-
updateFlag(SidebarSettingsFlags.NoAiFeedEnabled, newState),
140-
);
141-
displayToast(
142-
newState ? labels.feed.noAi.hidden : labels.feed.noAi.visible,
143-
);
144-
logEvent({
145-
event_name: LogEvent.ToggleNoAiFeed,
146-
target_id: newState ? TargetId.On : TargetId.Off,
147-
extra: JSON.stringify({
148-
origin: Origin.Settings,
149-
}),
150-
});
151-
}}
152-
>
153-
Keep AI topics filtered out
154-
</Switch>
155-
</div>
156-
)}
157101
<div className="flex flex-col gap-4">
158102
<div className="flex flex-col gap-1">
159103
<Typography bold type={TypographyType.Body}>

packages/shared/src/components/layout/common.spec.tsx

Lines changed: 2 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
2+
import { render, screen } from '@testing-library/react';
33
import SettingsContext from '../../contexts/SettingsContext';
44
import { useAuthContext } from '../../contexts/AuthContext';
55
import { useLogContext } from '../../contexts/LogContext';
@@ -10,7 +10,6 @@ import { useFeedName } from '../../hooks/feed/useFeedName';
1010
import { useQueryState } from '../../hooks/utils/useQueryState';
1111
import { checkIsExtension, getCurrentBrowserName } from '../../lib/func';
1212
import { ActionType } from '../../graphql/actions';
13-
import { LogEvent, Origin, TargetId } from '../../lib/log';
1413
import { SharedFeedPage } from '../utilities';
1514
import { SearchControlHeader } from './common';
1615

@@ -96,12 +95,10 @@ const mockGetCurrentBrowserName = getCurrentBrowserName as jest.Mock;
9695

9796
const createActionsState = ({
9897
dismissedInstallExtension = false,
99-
dismissedNoAiToggle = false,
10098
isActionsFetched = true,
10199
completeAction = jest.fn(),
102100
}: {
103101
dismissedInstallExtension?: boolean;
104-
dismissedNoAiToggle?: boolean;
105102
isActionsFetched?: boolean;
106103
completeAction?: jest.Mock;
107104
} = {}) => ({
@@ -110,31 +107,18 @@ const createActionsState = ({
110107
return dismissedInstallExtension;
111108
}
112109

113-
if (type === ActionType.DismissNoAiFeedToggle) {
114-
return dismissedNoAiToggle;
115-
}
116-
117110
return false;
118111
}),
119112
completeAction,
120113
isActionsFetched,
121114
});
122115

123-
const renderComponent = ({
124-
noAiState,
125-
}: {
126-
noAiState?: {
127-
isAvailable: boolean;
128-
isEnabled: boolean;
129-
onToggle: () => Promise<void>;
130-
};
131-
} = {}) =>
116+
const renderComponent = () =>
132117
render(
133118
<SettingsContext.Provider value={{ sortingEnabled: false } as never}>
134119
<SearchControlHeader
135120
feedName={SharedFeedPage.MyFeed}
136121
algoState={[0, jest.fn()]}
137-
noAiState={noAiState}
138122
/>
139123
</SettingsContext.Provider>,
140124
);
@@ -219,103 +203,4 @@ describe('SearchControlHeader', () => {
219203
screen.getByRole('link', { name: 'Get it for Chrome' }),
220204
).toBeInTheDocument();
221205
});
222-
223-
it('does not render the No AI switch when unavailable', () => {
224-
mockUseActions.mockReturnValue(
225-
createActionsState({ dismissedInstallExtension: true }),
226-
);
227-
228-
renderComponent({
229-
noAiState: {
230-
isAvailable: false,
231-
isEnabled: false,
232-
onToggle: jest.fn().mockResolvedValue(undefined),
233-
},
234-
});
235-
236-
expect(screen.queryByText('No AI mode')).not.toBeInTheDocument();
237-
expect(
238-
screen.queryByRole('checkbox', { name: 'Toggle No AI mode' }),
239-
).not.toBeInTheDocument();
240-
});
241-
242-
it('renders a No AI switch and logs when toggled', async () => {
243-
const onToggle = jest.fn().mockResolvedValue(undefined);
244-
const logEvent = jest.fn();
245-
mockUseLogContext.mockReturnValue({ logEvent });
246-
mockUseActions.mockReturnValue(
247-
createActionsState({ dismissedInstallExtension: true }),
248-
);
249-
250-
renderComponent({
251-
noAiState: {
252-
isAvailable: true,
253-
isEnabled: false,
254-
onToggle,
255-
},
256-
});
257-
258-
expect(screen.getByText('No AI mode')).toBeInTheDocument();
259-
const switchInput = screen.getByRole('checkbox', {
260-
name: 'Toggle No AI mode',
261-
});
262-
fireEvent.click(switchInput);
263-
264-
expect(onToggle).toHaveBeenCalledTimes(1);
265-
await waitFor(() => {
266-
expect(logEvent).toHaveBeenCalledWith({
267-
event_name: LogEvent.ToggleNoAiFeed,
268-
target_id: TargetId.On,
269-
extra: JSON.stringify({
270-
origin: Origin.Feed,
271-
}),
272-
});
273-
});
274-
});
275-
276-
it('does not render the No AI switch after dismissal', () => {
277-
mockUseActions.mockReturnValue(
278-
createActionsState({
279-
dismissedInstallExtension: true,
280-
dismissedNoAiToggle: true,
281-
}),
282-
);
283-
284-
renderComponent({
285-
noAiState: {
286-
isAvailable: true,
287-
isEnabled: false,
288-
onToggle: jest.fn().mockResolvedValue(undefined),
289-
},
290-
});
291-
292-
expect(screen.queryByText('No AI mode')).not.toBeInTheDocument();
293-
expect(
294-
screen.queryByRole('checkbox', { name: 'Toggle No AI mode' }),
295-
).not.toBeInTheDocument();
296-
});
297-
298-
it('dismisses the No AI header card', () => {
299-
const completeAction = jest.fn();
300-
mockUseActions.mockReturnValue(
301-
createActionsState({
302-
dismissedInstallExtension: true,
303-
completeAction,
304-
}),
305-
);
306-
307-
renderComponent({
308-
noAiState: {
309-
isAvailable: true,
310-
isEnabled: false,
311-
onToggle: jest.fn().mockResolvedValue(undefined),
312-
},
313-
});
314-
315-
fireEvent.click(screen.getByRole('button', { name: 'Dismiss No AI mode' }));
316-
317-
expect(completeAction).toHaveBeenCalledWith(
318-
ActionType.DismissNoAiFeedToggle,
319-
);
320-
});
321206
});

0 commit comments

Comments
 (0)