Skip to content

Commit

Permalink
feat(context-menu): add flag for disable context menu
Browse files Browse the repository at this point in the history
  • Loading branch information
onetdev committed Nov 26, 2024
1 parent 9b9603d commit d5bdbb3
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 4 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ The main idea is to gather the most annoying features of modern websites in one
- [ ] Push elements to navigation stack so that when the user tries to navigate back it will stay on the page
- [ ] Add flashing animation to flaim phone
- [ ] Adblocker detection
- [ ] Add advertisement content to clipboard when copying text

</details>

<details>
<summary>Completed</summary>

- [x] Prevent rightclick
- [x] Fake advertisements (free phone)
- [x] Add disabled mandatory experience checkboxes to settings
- [x] DILF advertisement and landing page
Expand Down
4 changes: 4 additions & 0 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@
},
"contentPaywall": "Content paywall",
"deadPixel": "Dead pixel",
"disableContextMenu": "Disable context (right click) menu",
"exitPrompt": "Exit prompt",
"mockChat": "Bubble chat",
"newsletterModal": "Newsletter popup modal",
Expand Down Expand Up @@ -501,5 +502,8 @@
"diamondColorB": "Diamond Color B",
"width": "Width",
"height": "Height"
},
"contextMenu": {
"disabled": "Hey, you can't right click here!"
}
}
28 changes: 28 additions & 0 deletions src/features/context_menu/hooks/useContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useTranslation } from 'next-i18next';
import { useCallback, useEffect } from 'react';

import { useExperienceFlagsStore } from '@/lib/state/experience_flags';

const useContextMenu = () => {
const { t } = useTranslation('common');
const isDisabled = useExperienceFlagsStore(
(state) => state.disableContextMenu,
);
const handleContextMenu = useCallback(
(e: MouseEvent) => {
e.preventDefault();
alert(t('contextMenu.disabled'));
},
[t],
);

useEffect(() => {
if (!isDisabled) return;

document.addEventListener('contextmenu', handleContextMenu);

return () => document.removeEventListener('contextmenu', handleContextMenu);
}, [handleContextMenu, isDisabled]);
};

export default useContextMenu;
1 change: 1 addition & 0 deletions src/features/context_menu/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as useContextMenu } from './hooks/useContextMenu';
8 changes: 8 additions & 0 deletions src/features/settings/components/ExperienceSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ const ExperienceSettings: FunctionComponent<ExperienceSettingsProps> = ({
onValueChange={experience.setDeadPixel}
/>
</LabeledChild>
<LabeledChild
label={t('settings.optionalExperienceFlags.disableContextMenu')}>
<FormCheckbox
name="disable_context"
checked={experience.disableContextMenu}
onValueChange={experience.setDisableContextMenu}
/>
</LabeledChild>
<LabeledChild label={t('settings.optionalExperienceFlags.exitPrompt')}>
<FormCheckbox
name="exit_prompt"
Expand Down
2 changes: 2 additions & 0 deletions src/lib/providers/ExperienceProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useTranslation } from 'next-i18next';
import { FunctionComponent, PropsWithChildren, useEffect } from 'react';
import { useBeforeUnload } from 'react-use';

import { useContextMenu } from '@/features/context_menu';
import { NewsletterModalExperienceHost } from '@/features/newsletter';
import { NotificationPermissionExperienceHost } from '@/features/notification';
import { PageTitleExperienceHost } from '@/features/page_title';
Expand All @@ -21,6 +22,7 @@ const ExperienceProvider: FunctionComponent<PropsWithChildren> = ({
useFirstInteractionListener();
useDocumentVisibilityListener();
useNavigationStats();
useContextMenu();
useBeforeUnload(exitPrompt, t('app.exitPrompt'));

useEffect(() => {
Expand Down
26 changes: 22 additions & 4 deletions src/lib/state/experience_flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface ExperienceFlagsState {
};
contentPaywall: boolean;
deadPixel: boolean;
disableContextMenu: boolean;
exitPrompt: boolean;
mockChat: boolean;
newsletterModal: boolean;
Expand All @@ -26,6 +27,7 @@ export interface ExperienceFlagsStateActions {
setGifts: (gifts: Partial<ExperienceFlagsState['gifts']>) => void;
setContentPaywall: (contentPaywall: boolean) => void;
setDeadPixel: (deadPixel: boolean) => void;
setDisableContextMenu: (disableContextMenu: boolean) => void;
setExitPrompt: (exitPrompt: boolean) => void;
setMockChat: (mockChat: boolean) => void;
setNewsletterModal: (newsletterModal: boolean) => void;
Expand All @@ -49,6 +51,7 @@ const initialState: ExperienceFlagsState = {
},
contentPaywall: true,
deadPixel: true,
disableContextMenu: true,
exitPrompt: true,
mockChat: true,
newsletterModal: true,
Expand All @@ -73,6 +76,8 @@ export const useExperienceFlagsStore = create(
set((state) => ({ gifts: { ...state.gifts, ...gifts } })),
setContentPaywall: (contentPaywall) => set({ contentPaywall }),
setDeadPixel: (deadPixel) => set({ deadPixel }),
setDisableContextMenu: (disableContextMenu) =>
set({ disableContextMenu: disableContextMenu }),
setExitPrompt: (exitPrompt) => set({ exitPrompt }),
setMockChat: (mockChat) => set({ mockChat }),
setNewsletterModal: (newsletterModal) => set({ newsletterModal }),
Expand All @@ -96,6 +101,7 @@ export const useExperienceFlagsStore = create(
},
contentPaywall: false,
deadPixel: false,
disableContextMenu: false,
exitPrompt: false,
mockChat: false,
newsletterModal: false,
Expand All @@ -113,7 +119,7 @@ export const useExperienceFlagsStore = create(
{
name: 'zustand-experience-flags-storage',
storage: createJSONStorage(() => localStorage),
version: 7,
version: 8,
migrate: (_persistedState, _version) => {
// Versions are supersets atm, don't need to juggle too much with
// type states
Expand All @@ -122,10 +128,22 @@ export const useExperienceFlagsStore = create(
return {
...persistedState,
gifts: {
flaps: persistedState.gifts.flaps ?? true,
oneByOne: persistedState.gifts.oneByOne ?? true,
flaps: persistedState.gifts?.flaps ?? initialState.gifts.flaps,
oneByOne:
persistedState.gifts?.oneByOne ?? initialState.gifts.oneByOne,
},
version: 7,
pageTitle: {
inactiveMarquee:
persistedState.pageTitle?.inactiveMarquee ??
initialState.pageTitle.inactiveMarquee,
randomGlitch:
persistedState.pageTitle?.randomGlitch ??
initialState.pageTitle.randomGlitch,
inactiveArrayPaged:
persistedState.pageTitle?.inactiveArrayPaged ??
initialState.pageTitle.inactiveArrayPaged,
},
version: 8,
};
},
},
Expand Down

0 comments on commit d5bdbb3

Please sign in to comment.