diff --git a/package.json b/package.json index 6d8bd2a4..31e69da9 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "private": true, "dependencies": { "@floating-ui/react": "0.26.1", - "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#57f8891697134e8aa65f286ffd8bdbda9a6bd512", + "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#80f19b488013cf386f4926fefb5790c79a3b9b96", "@testing-library/jest-dom": "5.14.1", "@testing-library/react": "13.0.0", "@testing-library/user-event": "13.2.1", diff --git a/src/app.tsx b/src/app.tsx index c7ff5e8d..3b7eb136 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -104,10 +104,13 @@ function App() { } /> } /> - } /> - } /> - } /> - } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index bfbe19e1..6398742f 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -26,9 +26,10 @@ import { isSubplebbitSettingsView, isSubplebbitSubmitView, isSubplebbitsView, - isSubplebbitsMineView, - isSubplebbitsMineSubscriberView, - isSubplebbitsMineModeratorView, + isSubplebbitsSubscriberView, + isSubplebbitsModeratorView, + isSubplebbitsAdminView, + isSubplebbitsOwnerView, isProfileUpvotedView, } from '../../lib/utils/view-utils'; import useTheme from '../../hooks/use-theme'; @@ -202,27 +203,26 @@ const InboxHeaderTabs = () => { const SubplebbitsHeaderTabs = () => { const { t } = useTranslation(); const location = useLocation(); - const isInSubplebbitsMineSubscriberView = isSubplebbitsMineSubscriberView(location.pathname); - const isInSubplebbitsMineModeratorView = isSubplebbitsMineModeratorView(location.pathname); - const isInSubplebbitsView = isSubplebbitsView(location.pathname) && !isInSubplebbitsMineSubscriberView && !isInSubplebbitsMineModeratorView; - const isInSubplebbitsMineView = isSubplebbitsMineView(location.pathname); + const isInSubplebbitsSubscriberView = isSubplebbitsSubscriberView(location.pathname); + const isInSubplebbitsModeratorView = isSubplebbitsModeratorView(location.pathname); + const isInSubplebbitsAdminView = isSubplebbitsAdminView(location.pathname); + const isInSubplebbitsOwnerView = isSubplebbitsOwnerView(location.pathname); + const isInSubplebbitsView = + isSubplebbitsView(location.pathname) && !isInSubplebbitsSubscriberView && !isInSubplebbitsModeratorView && !isInSubplebbitsAdminView && !isInSubplebbitsOwnerView; return ( <>
  • - - {t('approved')} - -
  • -
  • - e.preventDefault()}> - {t('proposed')} + + {t('vote')}
  • {t('my_communities')} diff --git a/src/components/sidebar/sidebar.tsx b/src/components/sidebar/sidebar.tsx index b60fe6e9..e0c1a03b 100644 --- a/src/components/sidebar/sidebar.tsx +++ b/src/components/sidebar/sidebar.tsx @@ -11,6 +11,7 @@ import SearchBar from '../search-bar'; import SubscribeButton from '../subscribe-button'; import packageJson from '../../../package.json'; const { version } = packageJson; +const commitRef = process.env.REACT_APP_COMMIT_REF; interface sidebarProps { address?: string | undefined; @@ -267,6 +268,14 @@ const Sidebar = ({ address, cid, createdAt, description, downvoteCount = 0, role v{version} + {commitRef && ( + <> + {' '} + + ({commitRef.slice(0, 7)}) + + + )}
  • diff --git a/src/components/topbar/topbar.tsx b/src/components/topbar/topbar.tsx index 0dbb4bc3..8a0d7232 100644 --- a/src/components/topbar/topbar.tsx +++ b/src/components/topbar/topbar.tsx @@ -118,7 +118,7 @@ const TopBar = () => { ))} {subscriptions?.length > 0 && ( - + {t('edit_subscriptions')} )} @@ -169,7 +169,7 @@ const TopBar = () => { ))} - + {t('edit')} » diff --git a/src/lib/utils/challenge-utils.ts b/src/lib/utils/challenge-utils.ts index c19be05b..6fad2311 100644 --- a/src/lib/utils/challenge-utils.ts +++ b/src/lib/utils/challenge-utils.ts @@ -73,6 +73,25 @@ export const getDefaultExclude = () => { ]; }; +export const getDefaultChallengeDescription = (challengeType: string) => { + switch (challengeType) { + case 'text-math': + return 'Ask a plain text math question, insecure, use ONLY for testing.'; + case 'captcha-canvas-v3': + return 'Make a custom image captcha'; + case 'fail': + return 'A challenge that automatically fails with a custom error message.'; + case 'blacklist': + return 'Blacklist author addresses.'; + case 'question': + return "Ask a question, like 'What is the password?'"; + case 'evm-contract-call': + return 'The response from an EVM contract call passes a condition, e.g. a token balance challenge.'; + default: + return ''; + } +}; + export const getDefaultOptionInputs = (challengeType: string) => { switch (challengeType) { case 'text-math': diff --git a/src/lib/utils/time-utils.ts b/src/lib/utils/time-utils.ts index eabc3a59..7adc85cc 100644 --- a/src/lib/utils/time-utils.ts +++ b/src/lib/utils/time-utils.ts @@ -5,7 +5,7 @@ export const getFormattedTimeAgo = (unixTimestamp: number): string => { const timeDifference = currentTime - unixTimestamp; const t = i18next.t; - if (timeDifference < 60) { + if (timeDifference < 120) { return t('time_1_minute_ago'); } if (timeDifference < 3600) { @@ -40,7 +40,7 @@ export const getFormattedTimeDuration = (unixTimestamp: number): string => { const timeDifference = currentTime - unixTimestamp; const t = i18next.t; - if (timeDifference < 60) { + if (timeDifference < 120) { return t('time_1_minute'); } if (timeDifference < 3600) { diff --git a/src/lib/utils/view-utils.ts b/src/lib/utils/view-utils.ts index d8d11b6d..1643ceea 100644 --- a/src/lib/utils/view-utils.ts +++ b/src/lib/utils/view-utils.ts @@ -52,10 +52,6 @@ export const isAuthorSubmittedView = (pathname: string, params: ParamsType): boo return pathname === `/u/${params.authorAddress}/c/${params.commentCid}/submitted`; }; -export const isProfileDownvotedView = (pathname: string): boolean => { - return pathname === '/profile/downvoted'; -}; - export const isHomeView = (pathname: string, params: ParamsType): boolean => { return pathname === '/' || sortTypes.includes(pathname) || (timeFilterNames.includes(params.timeFilterName as TimeFilterKey) && !pathname.startsWith('/p/')); }; @@ -100,6 +96,14 @@ export const isProfileSubmittedView = (pathname: string): boolean => { return pathname.startsWith('/profile/submitted'); }; +export const isProfileDownvotedView = (pathname: string): boolean => { + return pathname === '/profile/downvoted'; +}; + +export const isProfileUpvotedView = (pathname: string): boolean => { + return pathname === '/profile/upvoted'; +}; + export const isSettingsView = (pathname: string): boolean => { return pathname === '/settings'; }; @@ -124,22 +128,30 @@ export const isSubplebbitsView = (pathname: string): boolean => { return pathname.startsWith('/communities'); }; -export const isSubplebbitsMineView = (pathname: string): boolean => { - return pathname === '/communities/mine'; +export const isSubplebbitsSubscriberView = (pathname: string): boolean => { + return pathname === '/communities/subscriber'; }; -export const isSubplebbitsMineSubscriberView = (pathname: string): boolean => { - return pathname === '/communities/mine' || pathname === '/communities/mine/subscriber'; +export const isSubplebbitsModeratorView = (pathname: string): boolean => { + return pathname === '/communities/moderator'; }; -export const isSubplebbitsMineContributorView = (pathname: string): boolean => { - return pathname === '/communities/mine/contributor'; +export const isSubplebbitsAdminView = (pathname: string): boolean => { + return pathname === '/communities/admin'; }; -export const isSubplebbitsMineModeratorView = (pathname: string): boolean => { - return pathname === '/communities/mine/moderator'; +export const isSubplebbitsOwnerView = (pathname: string): boolean => { + return pathname === '/communities/owner'; }; -export const isProfileUpvotedView = (pathname: string): boolean => { - return pathname === '/profile/upvoted'; +export const isSubplebbitsVoteView = (pathname: string): boolean => { + return pathname === '/communities/vote'; +}; + +export const isSubplebbitsVotePassedView = (pathname: string): boolean => { + return pathname === '/communities/vote/passed'; +}; + +export const isSubplebbitsVoteRejectedView = (pathname: string): boolean => { + return pathname === '/communities/vote/rejected'; }; diff --git a/src/views/submit/submit.tsx b/src/views/submit/submit.tsx index b366687d..86a28dac 100644 --- a/src/views/submit/submit.tsx +++ b/src/views/submit/submit.tsx @@ -43,12 +43,7 @@ const useSubmitStore = create((set) => ({ onChallengeVerification: alertChallengeVerificationFailed, onError: (error: Error) => { console.error(error); - // TODO: remove this explanation when pubsub providers uptime is fixed: let errorMessage = error.message; - if (errorMessage === 'The challenge request has been published over the pubsub topic but no response was received') { - errorMessage += - '. This means seedit web is currently offline, download seedit desktop which is fully peer-to-peer: https://github.com/plebbit/seedit/releases/latest'; - } alert(errorMessage); }, }; diff --git a/src/views/subplebbit/subplebbit-settings/subplebbit-settings.module.css b/src/views/subplebbit/subplebbit-settings/subplebbit-settings.module.css index b242c25b..1f095954 100644 --- a/src/views/subplebbit/subplebbit-settings/subplebbit-settings.module.css +++ b/src/views/subplebbit/subplebbit-settings/subplebbit-settings.module.css @@ -250,7 +250,7 @@ } .box, .boxInput { - width: calc(100vw - 35px); + width: calc(100vw - 20px); } .boxInput input, .boxInput textarea { diff --git a/src/views/subplebbit/subplebbit-settings/subplebbit-settings.tsx b/src/views/subplebbit/subplebbit-settings/subplebbit-settings.tsx index 1bc3a3fa..dfc52e1a 100644 --- a/src/views/subplebbit/subplebbit-settings/subplebbit-settings.tsx +++ b/src/views/subplebbit/subplebbit-settings/subplebbit-settings.tsx @@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'; import { create } from 'zustand'; import styles from './subplebbit-settings.module.css'; import { isValidURL } from '../../../lib/utils/url-utils'; -import { getDefaultExclude, getDefaultOptionInputs } from '../../../lib/utils/challenge-utils'; +import { getDefaultChallengeDescription, getDefaultExclude, getDefaultOptionInputs } from '../../../lib/utils/challenge-utils'; import LoadingEllipsis from '../../../components/loading-ellipsis'; import Sidebar from '../../../components/sidebar'; @@ -292,138 +292,90 @@ const challengesNames = ['text-math', 'captcha-canvas-v3', 'fail', 'blacklist', interface ChallengeSettingsProps { challenge: any; + index: number; + setSubmitStore: (data: Partial) => void; + settings: any; showSettings: boolean; } -const ChallengeSettings = ({ challenge, showSettings }: ChallengeSettingsProps) => { - const { name } = challenge || {}; +type OptionInput = { + option: string; + value?: string; + label: string; + default?: string; + description: string; + placeholder?: string; + required?: boolean; +}; + +const ChallengeSettings = ({ challenge, index, setSubmitStore, settings, showSettings }: ChallengeSettingsProps) => { + const { exclude, name, optionInputs } = challenge || {}; + + const handleOptionChange = (optionName: string, newValue: string) => { + const updatedOptionInputs = optionInputs.map((input: any) => (input.option === optionName ? { ...input, value: newValue } : input)); + + const updatedChallenges = settings.challenges.map((ch: any, idx: number) => (idx === index ? { ...ch, optionInputs: updatedOptionInputs } : ch)); + + setSubmitStore({ settings: { ...settings, challenges: updatedChallenges } }); + }; + + const handleExcludeChange = (type: 'role' | 'post' | 'reply' | 'vote', value: string | boolean) => { + const updatedExclude = { ...exclude[0] }; // Clone the first exclude object + + if (type === 'role') { + if (typeof value === 'string') { + const roleIndex = updatedExclude.role.indexOf(value); + if (roleIndex > -1) { + updatedExclude.role.splice(roleIndex, 1); // Remove role + } else { + updatedExclude.role.push(value); // Add role + } + } + } else { + // Handle post, reply, vote + updatedExclude[type] = value; + } + + const updatedChallenges = [...settings.challenges]; + updatedChallenges[index] = { ...updatedChallenges[index], exclude: [updatedExclude] }; + setSubmitStore({ settings: { ...settings, challenges: updatedChallenges } }); + }; return (
    - {name === 'text-math' && ( - <> -
    Ask a plain text math question, insecure, use ONLY for testing.
    -
    - Difficulty -
    The math difficulty of the challenge between 1-3.
    - -
    - - )} - {name === 'captcha-canvas-v3' && ( - <> -
    Make a custom image captcha
    -
    - Characters -
    Amount of characters of the captcha.
    - -
    -
    - Width -
    Height of the captcha.
    - -
    -
    - Height -
    Width of the captcha.
    - -
    -
    - Color -
    Color of the captcha.
    - -
    - - )} - {name === 'fail' && ( - <> -
    A challenge that automatically fails with a custom error message.
    -
    - Error -
    The error to display to the author.
    - -
    - - )} - {name === 'blacklist' && ( - <> -
    Blacklist author addresses.
    -
    - Blacklist -
    Comma separated list of author addresses to be blacklisted.
    - -
    -
    - Error -
    The error to display to the author.
    - -
    - - )} - {name === 'question' && ( - <> -
    Ask a question, like 'What is the password?'
    -
    - Question -
    The question to answer.
    - -
    -
    - Answer -
    The answer to the question.
    - -
    - - )} - {name === 'evm-contract-call' && ( - <> -
    The response from an EVM contract call passes a condition, e.g. a token balance challenge.
    -
    - chainTicker -
    The chain ticker
    - -
    -
    - Address -
    The contract address.
    - -
    -
    - ABI -
    The ABI of the contract method.
    -