diff --git a/src/components/directory-modal/directory-modal.module.css b/src/components/directory-modal/directory-modal.module.css new file mode 100644 index 00000000..c98312e8 --- /dev/null +++ b/src/components/directory-modal/directory-modal.module.css @@ -0,0 +1,119 @@ +.backdrop { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(128, 128, 128, 0.5); + z-index: 999; +} + +.directoryDialog { + position: absolute; + width: 500px; + top: 50px; + left: 50%; + margin-left: -251px; + background-color: rgb(255, 255, 255); + border: 1px solid rgb(136, 0, 0); + color: rgb(136, 0, 0); + box-shadow: rgba(0, 0, 0, 0.1) 2px 2px 0px 1px; + font-family: arial, helvetica, clean, sans-serif; + font-size: 13px; + line-height: 16.003px; + z-index: 1000; +} + +@media (max-width: 600px) { + .directoryDialog { + width: calc(100% - 20px); + margin-left: -50%; + left: 50%; + max-width: 500px; + } +} + +.hd { + position: relative; + background-color: rgb(136, 0, 0); + color: rgb(255, 255, 255); + padding: 4px 6px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.hd h2 { + margin: 0; + padding: 0; + font-size: 131%; + font-weight: bold; +} + +.closeButton { + all: unset; + cursor: pointer; + width: 16px; + height: 16px; + position: absolute; + top: 4px; + right: 4px; + background-image: var(--disclaimer-modal-close-button-background-image); + background-size: 100%; + background-position: center; + background-repeat: no-repeat; +} + +.bd { + padding: 10px; +} + +.introMessage { + font-size: 15px; + margin: 10px 0 20px 0; + text-align: center; +} + +.introMessage strong { + font-weight: bold; +} + +.section { + margin-bottom: 20px; +} + +.section:last-child { + margin-bottom: 0; +} + +.section h3 { + margin: 0 0 8px 0; + padding: 0; + font-size: 13px; + font-weight: bold; + color: rgb(136, 0, 0); +} + +.section p { + margin: 0 0 12px 0; + font-size: 13px; + line-height: 16.003px; +} + +.section p:last-child { + margin-bottom: 0; +} + +.bd a { + color: rgb(136, 0, 0); + text-decoration: underline; +} + +.directoryFooter { + padding: 10px; + display: flex; + justify-content: center; + gap: 10px; +} + + diff --git a/src/components/directory-modal/directory-modal.tsx b/src/components/directory-modal/directory-modal.tsx new file mode 100644 index 00000000..527b6d02 --- /dev/null +++ b/src/components/directory-modal/directory-modal.tsx @@ -0,0 +1,105 @@ +import useDirectoryModalStore from '../../stores/use-directory-modal-store'; +import styles from './directory-modal.module.css'; + +const DirectoryModal = () => { + const { showModal, closeDirectoryModal } = useDirectoryModalStore(); + + if (!showModal) { + return null; + } + + const handleBackdropClick = (e: React.MouseEvent) => { + if (e.target === e.currentTarget) { + closeDirectoryModal(); + } + }; + + return ( +
+
+
+

Submit a Board to a Directory

+
+
+

+ The board you clicked on doesn't exist yet, but it can be yours! +

+ +
+

What is a directory board vs a regular board?

+

+ On 5chan, anyone can create and connect to any board using its address. A "directory board" is simply a board that has been assigned to a specific + directory category (like "Anime & Manga" or "Video Games") in the boards list on the homepage. This assignment is temporary and + handpicked by the devs until DAO curation is implemented. +

+

+ Important: Anyone can create a board and users can access it at any time, regardless of whether it's assigned to a directory or not. + You can use the search bar on the homepage to connect to any board address peer-to-peer, even if it's not added as a directory. Additionally, every + board has a "[Subscribe]" button—when you subscribe to a board, it will appear in the top bar on the boards page, making it easy to access your + favorite boards regardless of directory assignment. +

+
+ +
+

How to create your own board

+

+ You can create a board using either the{' '} + + Seedit GUI client + {' '} + or the{' '} + + plebbit-cli command line interface + + . Once created, anyone can connect to your board using its address, regardless of whether it's assigned to a directory or not. +

+
+ +
+

Requirements for directory assignment

+

+ To have your board assigned to a directory, it should be active, well-moderated, and relevant to the directory category. Most importantly, it should have + 99% uptime, since a board acts like its own server (it's a P2P node). The devs review submissions and reserve the right to approve or reject them based + on these criteria. +

+
+ +
+

How to submit your board

+

+ To request your board be added to a directory, open a pull request on GitHub by editing the{' '} + + 5chan-multisub.json file + + . Add your board's entry with its title, address, and NSFW status (if applicable). The devs will review your PR and merge it if approved. +

+
+ +
+

Future roadmap

+

+ In the future, directory board assignments will be determined through gasless voting using pubsub. Community members will vote on which board should be + assigned to each directory, and the highest voted board will automatically become the directory board. This will make the process fully decentralized and + community-driven. +

+
+ +
+

Dev veto power

+

+ While the devs reserve the right to change directory resolutions, this is done through commits in the fully open-source repository. There is no centralized + or server-side action required—anyone can change the directory resolution by modifying the code and redeploying to their own domain. 5chan is adminless, and + the app itself has no owner or central authority. +

+
+
+
+ +
+
+
+ ); +}; + +export default DirectoryModal; diff --git a/src/components/directory-modal/index.ts b/src/components/directory-modal/index.ts new file mode 100644 index 00000000..08c007a5 --- /dev/null +++ b/src/components/directory-modal/index.ts @@ -0,0 +1 @@ +export { default } from './directory-modal'; diff --git a/src/components/topbar/topbar.tsx b/src/components/topbar/topbar.tsx index 246f508c..519f015c 100644 --- a/src/components/topbar/topbar.tsx +++ b/src/components/topbar/topbar.tsx @@ -6,6 +6,7 @@ import { useAccount, useAccountComment, useAccountSubplebbits } from '@plebbit/p import { isAllView, isCatalogView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits'; import { TimeFilter } from '../board-buttons'; +import useDirectoryModalStore from '../../stores/use-directory-modal-store'; import styles from './topbar.module.css'; import _, { debounce } from 'lodash'; @@ -75,6 +76,7 @@ const TopBarDesktop = () => { const params = useParams(); const isInCatalogView = isCatalogView(location.pathname, params); const [showSearchBar, setShowSearchBar] = useState(false); + const { openDirectoryModal } = useDirectoryModalStore(); const subscriptions = account?.subscriptions; @@ -108,16 +110,8 @@ const TopBarDesktop = () => { )} [ - - - {t('create_board')} - - - ] [ - - - {t('vote')} - + + {t('create_board')} ] diff --git a/src/stores/use-directory-modal-store.ts b/src/stores/use-directory-modal-store.ts new file mode 100644 index 00000000..873aae9c --- /dev/null +++ b/src/stores/use-directory-modal-store.ts @@ -0,0 +1,25 @@ +import { create } from 'zustand'; + +interface DirectoryModalState { + showModal: boolean; + openDirectoryModal: () => void; + closeDirectoryModal: () => void; +} + +const useDirectoryModalStore = create((set) => ({ + showModal: false, + + openDirectoryModal: () => { + set({ + showModal: true, + }); + }, + + closeDirectoryModal: () => { + set({ + showModal: false, + }); + }, +})); + +export default useDirectoryModalStore; diff --git a/src/views/home/boards-list/boards-list.tsx b/src/views/home/boards-list/boards-list.tsx index e30ede60..121b9c7a 100644 --- a/src/views/home/boards-list/boards-list.tsx +++ b/src/views/home/boards-list/boards-list.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'; import { useDefaultSubplebbitsState, MultisubSubplebbit } from '../../../hooks/use-default-subplebbits'; import LoadingEllipsis from '../../../components/loading-ellipsis'; import useDisclaimerModalStore from '../../../stores/use-disclaimer-modal-store'; +import useDirectoryModalStore from '../../../stores/use-directory-modal-store'; import useBoardsFilterStore from '../../../stores/use-boards-filter-store'; import BoardsFilterModal from './boards-filter-modal'; import styles from '../home.module.css'; @@ -31,6 +32,7 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { const navigate = useNavigate(); const { loading, error } = useDefaultSubplebbitsState(); const { showDisclaimerModal } = useDisclaimerModalStore(); + const { openDirectoryModal } = useDirectoryModalStore(); const { useCatalogLinks, boardFilter } = useBoardsFilterStore(); const handleLinkClick = (e: React.MouseEvent, address: string) => { @@ -44,6 +46,12 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { return `/p/${address}${useCatalogLinks ? '/catalog' : ''}`; }; + // Handler for placeholder board links + const handlePlaceholderClick = (e: React.MouseEvent) => { + e.preventDefault(); + openDirectoryModal(); + }; + if (loading) { return (
@@ -108,32 +116,32 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { {(showAll || showWorksafeOnly) && ( <>
  • - e.preventDefault()} className={styles.placeholder}> + Anime & Manga
  • - e.preventDefault()} className={styles.placeholder}> + Anime/Cute
  • - e.preventDefault()} className={styles.placeholder}> + Anime/Wallpapers
  • - e.preventDefault()} className={styles.placeholder}> + Mecha
  • - e.preventDefault()} className={styles.placeholder}> + Cosplay & EGL
  • - e.preventDefault()} className={styles.placeholder}> + Cute/Male
  • @@ -141,7 +149,7 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { )} {(showAll || showNsfwOnly) && (
  • - e.preventDefault()} className={styles.placeholder}> + Flash
  • @@ -149,17 +157,17 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { {(showAll || showWorksafeOnly) && ( <>
  • - e.preventDefault()} className={styles.placeholder}> + Transportation
  • - e.preventDefault()} className={styles.placeholder}> + Otaku Culture
  • - e.preventDefault()} className={styles.placeholder}> + Virtual YouTubers
  • @@ -175,42 +183,42 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {

    Video Games

    • - e.preventDefault()} className={styles.placeholder}> + Video Games
    • - e.preventDefault()} className={styles.placeholder}> + Video Game Generals
    • - e.preventDefault()} className={styles.placeholder}> + Video Games/Multiplayer
    • - e.preventDefault()} className={styles.placeholder}> + Video Games/Mobile
    • - e.preventDefault()} className={styles.placeholder}> + Pokémon
    • - e.preventDefault()} className={styles.placeholder}> + Retro Games
    • - e.preventDefault()} className={styles.placeholder}> + Video Games/RPG
    • - e.preventDefault()} className={styles.placeholder}> + Video Games/Strategy
    • @@ -226,77 +234,77 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {

      Interests

      • - e.preventDefault()} className={styles.placeholder}> + Comics & Cartoons
      • - e.preventDefault()} className={styles.placeholder}> + Technology
      • - e.preventDefault()} className={styles.placeholder}> + Television & Film
      • - e.preventDefault()} className={styles.placeholder}> + Weapons
      • - e.preventDefault()} className={styles.placeholder}> + Auto
      • - e.preventDefault()} className={styles.placeholder}> + Animals & Nature
      • - e.preventDefault()} className={styles.placeholder}> + Traditional Games
      • - e.preventDefault()} className={styles.placeholder}> + Sports
      • - e.preventDefault()} className={styles.placeholder}> + Extreme Sports
      • - e.preventDefault()} className={styles.placeholder}> + Professional Wrestling
      • - e.preventDefault()} className={styles.placeholder}> + Science & Math
      • - e.preventDefault()} className={styles.placeholder}> + History & Humanities
      • - e.preventDefault()} className={styles.placeholder}> + International
      • - e.preventDefault()} className={styles.placeholder}> + Outdoors
      • - e.preventDefault()} className={styles.placeholder}> + Toys
      • @@ -311,7 +319,7 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {
          {(showAll || showNsfwOnly) && (
        • - e.preventDefault()} className={styles.placeholder}> + Oekaki
        • @@ -319,17 +327,17 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { {(showAll || showWorksafeOnly) && ( <>
        • - e.preventDefault()} className={styles.placeholder}> + Papercraft & Origami
        • - e.preventDefault()} className={styles.placeholder}> + Photography
        • - e.preventDefault()} className={styles.placeholder}> + Food & Cooking
        • @@ -337,14 +345,14 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { )} {(showAll || showNsfwOnly) && (
        • - e.preventDefault()} className={styles.placeholder}> + Artwork/Critique
        • )} {(showAll || showNsfwOnly) && (
        • - e.preventDefault()} className={styles.placeholder}> + Wallpapers/General
        • @@ -352,42 +360,42 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { {(showAll || showWorksafeOnly) && ( <>
        • - e.preventDefault()} className={styles.placeholder}> + Literature
        • - e.preventDefault()} className={styles.placeholder}> + Music
        • - e.preventDefault()} className={styles.placeholder}> + Fashion
        • - e.preventDefault()} className={styles.placeholder}> + 3DCG
        • - e.preventDefault()} className={styles.placeholder}> + Graphic Design
        • - e.preventDefault()} className={styles.placeholder}> + Do-It-Yourself
        • - e.preventDefault()} className={styles.placeholder}> + Worksafe GIF
        • - e.preventDefault()} className={styles.placeholder}> + Quests
        • @@ -413,53 +421,53 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { ) : (
        • - e.preventDefault()} className={styles.placeholder}> + Business & Finance
        • )}
        • - e.preventDefault()} className={styles.placeholder}> + Travel
        • - e.preventDefault()} className={styles.placeholder}> + Fitness
        • - e.preventDefault()} className={styles.placeholder}> + Paranormal
        • - e.preventDefault()} className={styles.placeholder}> + Advice
        • - e.preventDefault()} className={styles.placeholder}> + LGBT
        • - e.preventDefault()} className={styles.placeholder}> + Pony
        • - e.preventDefault()} className={styles.placeholder}> + Current News
        • - e.preventDefault()} className={styles.placeholder}> + Worksafe Requests
        • - e.preventDefault()} className={styles.placeholder}> + Very Important Posts
        • @@ -474,12 +482,12 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {
          • - e.preventDefault()} className={styles.placeholder}> + Random
          • - e.preventDefault()} className={styles.placeholder}> + ROBOT9001
          • @@ -491,23 +499,23 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => { ) : (
          • - e.preventDefault()} className={styles.placeholder}> + Politically Incorrect
          • )}
          • - e.preventDefault()} className={styles.placeholder}> + International/Random
          • - e.preventDefault()} className={styles.placeholder}> + Cams & Meetups
          • - e.preventDefault()} className={styles.placeholder}> + Shit 4chan Says
          • @@ -524,67 +532,67 @@ const BoardsList = ({ multisub }: { multisub: MultisubSubplebbit[] }) => {
            • - e.preventDefault()} className={styles.placeholder}> + Sexy Beautiful Women
            • - e.preventDefault()} className={styles.placeholder}> + Hardcore
            • - e.preventDefault()} className={styles.placeholder}> + Handsome Men
            • - e.preventDefault()} className={styles.placeholder}> + Hentai
            • - e.preventDefault()} className={styles.placeholder}> + Ecchi
            • - e.preventDefault()} className={styles.placeholder}> + Yuri
            • - e.preventDefault()} className={styles.placeholder}> + Hentai/Alternative
            • - e.preventDefault()} className={styles.placeholder}> + Yaoi
            • - e.preventDefault()} className={styles.placeholder}> + Torrents
            • - e.preventDefault()} className={styles.placeholder}> + High Resolution
            • - e.preventDefault()} className={styles.placeholder}> + Adult GIF
            • - e.preventDefault()} className={styles.placeholder}> + Adult Cartoons
            • - e.preventDefault()} className={styles.placeholder}> + Adult Requests
            • diff --git a/src/views/home/home.tsx b/src/views/home/home.tsx index 093233f3..2e72b823 100644 --- a/src/views/home/home.tsx +++ b/src/views/home/home.tsx @@ -10,6 +10,7 @@ import BoardsList from './boards-list'; import Version from '../../components/version'; import useDisclaimerModalStore from '../../stores/use-disclaimer-modal-store'; import DisclaimerModal from '../../components/disclaimer-modal'; +import DirectoryModal from '../../components/directory-modal'; import _ from 'lodash'; // https://github.com/plebbit/lists/blob/master/5chan-multisub.json @@ -186,6 +187,7 @@ const Home = () => { return ( <> +