diff --git a/src/components/post/expando/expando.module.css b/src/components/post/expando/expando.module.css index 28d1fc66..e7846b47 100644 --- a/src/components/post/expando/expando.module.css +++ b/src/components/post/expando/expando.module.css @@ -177,6 +177,7 @@ unicode-bidi: isolate; font-size: small; margin-bottom: 10px; + display: inline-block; } .alwaysShowNsfwNotice p { diff --git a/src/components/post/expando/expando.tsx b/src/components/post/expando/expando.tsx index 085e8ec9..a6daff89 100644 --- a/src/components/post/expando/expando.tsx +++ b/src/components/post/expando/expando.tsx @@ -5,6 +5,7 @@ import Embed from '../embed'; import { CommentMediaInfo } from '../../../lib/utils/media-utils'; import Markdown from '../../markdown'; import { useTranslation } from 'react-i18next'; +import useFilterSettingsStore from '../../../stores/use-filter-settings-store'; interface ExpandoProps { authorEditReason?: string; @@ -36,8 +37,8 @@ const Expando = ({ toggleExpanded, }: ExpandoProps) => { const { t } = useTranslation(); - - const [hideContent, setHideContent] = useState(true); + const { blurNsfwThumbnails, setBlurNsfwThumbnails } = useFilterSettingsStore(); + const [hideContent, setHideContent] = useState(blurNsfwThumbnails); const [alwaysShowNsfw, setAlwaysShowNsfw] = useState(false); useEffect(() => { @@ -46,6 +47,12 @@ const Expando = ({ } }, [expanded]); + const handleAlwaysShowNsfw = () => { + setBlurNsfwThumbnails(false); + setHideContent(false); + setAlwaysShowNsfw(true); + }; + let mediaComponent = null; if (commentMediaInfo?.type === 'image' || commentMediaInfo?.type === 'gif') { @@ -64,13 +71,13 @@ const Expando = ({
{link && !removed && commentMediaInfo?.type !== 'webpage' && (
setHideContent(false)}> - {(nsfw || spoiler) && hideContent && link && commentMediaInfo?.type !== 'webpage' && !(deleted || removed) && ( + {((nsfw && blurNsfwThumbnails) || spoiler) && hideContent && link && commentMediaInfo?.type !== 'webpage' && !(deleted || removed) && ( <>
- {nsfw && spoiler ? 'CLICK TO SEE NSFW SPOILER' : spoiler ? t('view_spoiler') : nsfw ? 'CLICK TO SEE NSFW' : ''} + {nsfw && spoiler ? t('see_nsfw_spoiler') : spoiler ? t('view_spoiler') : nsfw ? t('see_nsfw') : ''} {nsfw && ( - setAlwaysShowNsfw(!alwaysShowNsfw)}> - Always show NSFW media? + + {t('always_show_nsfw')} )} @@ -89,9 +96,11 @@ const Expando = ({
)} {alwaysShowNsfw && ( -
-

Ok, we changed your preferences to always show NSFW media.

- +
+
+

{t('always_show_nsfw_notice')}

+ +
)} {content && showContent && ( diff --git a/src/components/post/post.tsx b/src/components/post/post.tsx index c751d53e..a0305ae0 100644 --- a/src/components/post/post.tsx +++ b/src/components/post/post.tsx @@ -96,7 +96,6 @@ const Post = ({ index, post = {} }: PostProps) => { link, linkHeight, linkWidth, - nsfw, pinned, reason, removed, @@ -108,6 +107,7 @@ const Post = ({ index, post = {} }: PostProps) => { title, upvoteCount, } = post || {}; + const nsfw = true; const { displayName, shortAddress } = author || {}; const { shortAuthorAddress, authorAddressChanged } = useAuthorAddress({ comment: post }); diff --git a/src/components/post/thumbnail/thumbnail.tsx b/src/components/post/thumbnail/thumbnail.tsx index 2ec24eab..ac3af336 100644 --- a/src/components/post/thumbnail/thumbnail.tsx +++ b/src/components/post/thumbnail/thumbnail.tsx @@ -2,6 +2,7 @@ import styles from './thumbnail.module.css'; import { Link } from 'react-router-dom'; import { CommentMediaInfo } from '../../../lib/utils/media-utils'; import useFetchGifFirstFrame from '../../../hooks/use-fetch-gif-first-frame'; +import useFilterSettingsStore from '../../../stores/use-filter-settings-store'; interface ThumbnailProps { cid?: string; @@ -84,7 +85,9 @@ const Thumbnail = ({ mediaComponent = ; } - if (isNsfw) { + const { blurNsfwThumbnails } = useFilterSettingsStore(); + + if (isNsfw && blurNsfwThumbnails) { mediaComponent = ; } diff --git a/src/hooks/use-default-subplebbits.ts b/src/hooks/use-default-subplebbits.ts index 99f27b28..3b588b26 100644 --- a/src/hooks/use-default-subplebbits.ts +++ b/src/hooks/use-default-subplebbits.ts @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from 'react'; import { useParams } from 'react-router-dom'; import { useAccount } from '@plebbit/plebbit-react-hooks'; import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; +import useFilterSettingsStore from '../stores/use-filter-settings-store'; interface Subplebbit { title?: string; @@ -28,10 +29,9 @@ export const categorizeSubplebbits = (subplebbits: Subplebbit[]) => { return { plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs }; }; -const nsfwTags = ['gore', 'adult', 'anti']; - export const useDefaultSubplebbits = () => { const [subplebbits, setSubplebbits] = useState([]); + const { hideAdultCommunities, hideGoreCommunities, hideAntiCommunities } = useFilterSettingsStore(); useEffect(() => { if (cache) { @@ -39,13 +39,16 @@ export const useDefaultSubplebbits = () => { } (async () => { try { - const multisub = await fetch( - 'https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json', - // { cache: 'no-cache' } - ).then((res) => res.json()); + const multisub = await fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json').then((res) => res.json()); const filteredSubplebbits = multisub.subplebbits.filter((subplebbit: Subplebbit) => { - return !subplebbit.tags?.some((tag) => nsfwTags.includes(tag)); + const tags = subplebbit.tags || []; + + if (hideAdultCommunities && tags.includes('adult')) return false; + if (hideGoreCommunities && tags.includes('gore')) return false; + if (hideAntiCommunities && tags.includes('anti')) return false; + + return true; }); cache = filteredSubplebbits; @@ -54,7 +57,7 @@ export const useDefaultSubplebbits = () => { console.warn(e); } })(); - }, []); + }, [hideAdultCommunities, hideGoreCommunities, hideAntiCommunities]); return cache || subplebbits; }; diff --git a/src/stores/use-filter-settings-store.ts b/src/stores/use-filter-settings-store.ts new file mode 100644 index 00000000..db7aa63f --- /dev/null +++ b/src/stores/use-filter-settings-store.ts @@ -0,0 +1,33 @@ +import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; + +interface FilterSettingsState { + blurNsfwThumbnails: boolean; + hideAdultCommunities: boolean; + hideGoreCommunities: boolean; + hideAntiCommunities: boolean; + setBlurNsfwThumbnails: (blur: boolean) => void; + setHideAdultCommunities: (hide: boolean) => void; + setHideGoreCommunities: (hide: boolean) => void; + setHideAntiCommunities: (hide: boolean) => void; +} + +const useFilterSettingsStore = create()( + persist( + (set) => ({ + blurNsfwThumbnails: true, + hideAdultCommunities: true, + hideGoreCommunities: true, + hideAntiCommunities: true, + setBlurNsfwThumbnails: (blur) => set({ blurNsfwThumbnails: blur }), + setHideAdultCommunities: (hide) => set({ hideAdultCommunities: hide }), + setHideGoreCommunities: (hide) => set({ hideGoreCommunities: hide }), + setHideAntiCommunities: (hide) => set({ hideAntiCommunities: hide }), + }), + { + name: 'filter-settings', + }, + ), +); + +export default useFilterSettingsStore; diff --git a/src/views/settings/settings.module.css b/src/views/settings/settings.module.css index 5fe523e0..a1650964 100644 --- a/src/views/settings/settings.module.css +++ b/src/views/settings/settings.module.css @@ -104,3 +104,17 @@ .highlightedSetting { background-color: var(--yellow-highlight); } + +.filterSettingTitle { + font-style: italic; + text-transform: capitalize; +} + +.filters input[type='checkbox'] { + margin: 2px 0.5em 0 0; +} + +.filters label { + margin-top: 5px; + margin-right: 5px; +} diff --git a/src/views/settings/settings.tsx b/src/views/settings/settings.tsx index 2b180587..fafada4a 100644 --- a/src/views/settings/settings.tsx +++ b/src/views/settings/settings.tsx @@ -3,13 +3,14 @@ import { useLocation } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; import { setAccount, useAccount } from '@plebbit/plebbit-react-hooks'; import { isSettingsPlebbitOptionsView } from '../../lib/utils/view-utils'; -import styles from './settings.module.css'; +import useFilterSettingsStore from '../../stores/use-filter-settings-store'; +import useTheme from '../../hooks/use-theme'; import AccountSettings from './account-settings'; import AddressSettings from './address-settings'; import AvatarSettings from './avatar-settings'; import PlebbitOptions from './plebbit-options'; import WalletSettings from './wallet-settings'; -import useTheme from '../../hooks/use-theme'; +import styles from './settings.module.css'; import packageJson from '../../../package.json'; import _ from 'lodash'; @@ -111,6 +112,39 @@ const ThemeSettings = () => { ); }; +const FiltersSettings = () => { + const { t } = useTranslation(); + const { + blurNsfwThumbnails, + hideAdultCommunities, + hideGoreCommunities, + hideAntiCommunities, + setBlurNsfwThumbnails, + setHideAdultCommunities, + setHideGoreCommunities, + setHideAntiCommunities, + } = useFilterSettingsStore(); + + return ( +
+
{t('nsfw_content')}
+ setBlurNsfwThumbnails(e.target.checked)} /> + +
+
+
{t('nsfw_communities')}
+ setHideAdultCommunities(e.target.checked)} /> + +
+ setHideGoreCommunities(e.target.checked)} /> + +
+ setHideAntiCommunities(e.target.checked)} /> + +
+ ); +}; + const DisplayNameSetting = () => { const { t } = useTranslation(); const account = useAccount(); @@ -192,6 +226,12 @@ const GeneralSettings = () => {
+
+ {t('filters')} + + + +
{t('avatar')}