mirror of
https://github.com/plebbit/seedit.git
synced 2026-04-20 07:08:43 -04:00
@@ -10,7 +10,7 @@
|
||||
"@capacitor/app": "6.0.1",
|
||||
"@capacitor/local-notifications": "7.0.1",
|
||||
"@floating-ui/react": "0.26.1",
|
||||
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#41f0cdf14617f5e843311986d66f14f2f8fcbce0",
|
||||
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#d6347601b40a237c26518ab9cc9de7d29bb69b62",
|
||||
"@testing-library/jest-dom": "5.14.1",
|
||||
"@testing-library/react": "13.0.0",
|
||||
"@testing-library/user-event": "13.2.1",
|
||||
|
||||
9
src/components/error-display/error-display.module.css
Normal file
9
src/components/error-display/error-display.module.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.errorMessage {
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
.showFullErrorButton {
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
padding: 5px 0;
|
||||
}
|
||||
49
src/components/error-display/error-display.tsx
Normal file
49
src/components/error-display/error-display.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './error-display.module.css';
|
||||
|
||||
const ErrorDisplay = ({ error }: { error: any }) => {
|
||||
const { t } = useTranslation();
|
||||
const [showFullError, setShowFullError] = useState(false);
|
||||
|
||||
return (
|
||||
(error?.message || error?.stack || error?.details) && (
|
||||
<div className={styles.error}>
|
||||
<br />
|
||||
<span>
|
||||
{error?.message && (
|
||||
<span className={styles.errorMessage}>
|
||||
{t('error')}: {error.message}
|
||||
</span>
|
||||
)}
|
||||
{(error?.stack || error?.details) && (
|
||||
<>
|
||||
{' — '}
|
||||
<span className={styles.showFullErrorButton} onClick={() => setShowFullError(!showFullError)}>
|
||||
{showFullError ? 'hide' : 'show'} full error
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
{showFullError && (
|
||||
<>
|
||||
{error?.stack && (
|
||||
<>
|
||||
<br />
|
||||
<div className={styles.errorStack}>Stack: {error.stack}</div>
|
||||
</>
|
||||
)}
|
||||
{error?.details && (
|
||||
<>
|
||||
<br />
|
||||
<div className={styles.errorStack}>Details: {JSON.stringify(error?.details, null, 2)}</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorDisplay;
|
||||
1
src/components/error-display/index.ts
Normal file
1
src/components/error-display/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './error-display';
|
||||
@@ -20,6 +20,20 @@
|
||||
border-left: 2px solid var(--markdown-blockquote-border);
|
||||
color: var(--markdown-blockquote);
|
||||
white-space: normal;
|
||||
display: flow-root;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.markdown blockquote > p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown blockquote blockquote > p:last-child {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.markdown blockquote > blockquote:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown li {
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-size: 11px;
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
.tagline a {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
width: 70px;
|
||||
height: var(--height, 70px);
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.thumbnailHidden {
|
||||
|
||||
@@ -105,4 +105,34 @@
|
||||
position: relative;
|
||||
will-change: transform;
|
||||
transition: transform 0.3s linear;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
width: calc(100% - 8px);
|
||||
margin: 0;
|
||||
border: 1px solid var(--border-text);
|
||||
background: var(--background);
|
||||
left: 0;
|
||||
list-style: none;
|
||||
z-index: 999999999 !important;
|
||||
}
|
||||
|
||||
.dropdownItem {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
color: var(--text);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dropdownItem:hover, .activeDropdownItem {
|
||||
background-color: var(--text-primary);
|
||||
color: var(--background);
|
||||
}
|
||||
|
||||
.dropdownItem:hover {
|
||||
color: var(--background);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState, useMemo } from 'react';
|
||||
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './search-bar.module.css';
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
isSubplebbitAboutView,
|
||||
} from '../../lib/utils/view-utils';
|
||||
import useFeedFiltersStore from '../../stores/use-feed-filters-store';
|
||||
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import _ from 'lodash';
|
||||
|
||||
interface SearchBarProps {
|
||||
@@ -50,6 +51,15 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
const [inputValue, setInputValue] = useState(currentQuery);
|
||||
const { setIsSearching } = useFeedFiltersStore();
|
||||
|
||||
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
|
||||
const [isInputFocused, setIsInputFocused] = useState(false);
|
||||
const [activeDropdownIndex, setActiveDropdownIndex] = useState<number>(-1);
|
||||
|
||||
const filteredCommunitySuggestions = useMemo(() => {
|
||||
if (!inputValue || isInCommunitySearch) return [];
|
||||
return defaultSubplebbitAddresses.filter((address) => address?.toLowerCase()?.includes(inputValue.toLowerCase())).slice(0, 10);
|
||||
}, [inputValue, defaultSubplebbitAddresses, isInCommunitySearch]);
|
||||
|
||||
useEffect(() => {
|
||||
setInputValue(searchParams.get('q') || '');
|
||||
}, [searchParams]);
|
||||
@@ -118,6 +128,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setInputValue(value);
|
||||
setActiveDropdownIndex(-1);
|
||||
if (isInCommunitySearch) {
|
||||
if (value.trim()) {
|
||||
setIsSearching(true);
|
||||
@@ -141,6 +152,46 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleCommunitySelect = useCallback(
|
||||
(address: string) => {
|
||||
setInputValue('');
|
||||
setIsInputFocused(false);
|
||||
setActiveDropdownIndex(-1);
|
||||
navigate(`/p/${address}`);
|
||||
},
|
||||
[navigate, setInputValue, setIsInputFocused, setActiveDropdownIndex],
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (!isInputFocused || isInCommunitySearch || filteredCommunitySuggestions.length === 0) {
|
||||
if (e.key === 'Enter' && !isInCommunitySearch) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
setActiveDropdownIndex((prevIndex) => (prevIndex < filteredCommunitySuggestions.length - 1 ? prevIndex + 1 : prevIndex));
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
setActiveDropdownIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : 0));
|
||||
} else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if (activeDropdownIndex !== -1 && filteredCommunitySuggestions[activeDropdownIndex]) {
|
||||
handleCommunitySelect(filteredCommunitySuggestions[activeDropdownIndex]);
|
||||
} else if (inputValue.trim() && !isInCommunitySearch) {
|
||||
searchBarRef.current?.requestSubmit();
|
||||
}
|
||||
} else if (e.key === 'Escape') {
|
||||
setIsInputFocused(false);
|
||||
setActiveDropdownIndex(-1);
|
||||
}
|
||||
},
|
||||
[isInputFocused, isInCommunitySearch, filteredCommunitySuggestions, activeDropdownIndex, handleCommunitySelect, inputValue, navigate],
|
||||
);
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef} className={`${styles.searchBarWrapper} ${isInHomeAboutView || isInSubplebbitAboutView || isInPostPageAboutView ? styles.mobileInfobar : ''}`}>
|
||||
<form className={styles.searchBar} ref={searchBarRef} onSubmit={handleSearchSubmit}>
|
||||
@@ -152,13 +203,38 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
autoCapitalize='off'
|
||||
placeholder={placeholder}
|
||||
ref={searchInputRef}
|
||||
onFocus={() => setShowExpando(true)}
|
||||
onFocus={() => {
|
||||
setShowExpando(true);
|
||||
setIsInputFocused(true);
|
||||
}}
|
||||
onChange={handleSearchChange}
|
||||
value={inputValue}
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={() => setTimeout(() => setIsInputFocused(false), 150)}
|
||||
/>
|
||||
<input type='submit' value='' />
|
||||
</form>
|
||||
{!isInCommunitySearch && isInputFocused && filteredCommunitySuggestions.length > 0 && (
|
||||
<ul className={styles.dropdown}>
|
||||
{filteredCommunitySuggestions.map((address, index) => (
|
||||
<li
|
||||
key={address}
|
||||
className={`${styles.dropdownItem} ${index === activeDropdownIndex ? styles.activeDropdownItem : ''}`}
|
||||
onClick={() => handleCommunitySelect(address)}
|
||||
onMouseEnter={() => setActiveDropdownIndex(index)}
|
||||
>
|
||||
{address}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
<div className={`${styles.infobar} ${showExpando ? styles.slideDown : styles.slideUp} ${!isInFeedView ? styles.lessHeight : ''}`}>
|
||||
{isInFeedView && (
|
||||
<label>
|
||||
<input type='checkbox' checked={isInCommunitySearch} onChange={() => handleCommunitySearchToggle(true)} />
|
||||
{t('search_feed_post')}
|
||||
</label>
|
||||
)}
|
||||
<label>
|
||||
<input
|
||||
type='checkbox'
|
||||
@@ -168,12 +244,6 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
/>
|
||||
{t('go_to_a_community')}
|
||||
</label>
|
||||
{isInFeedView && (
|
||||
<label>
|
||||
<input type='checkbox' checked={isInCommunitySearch} onChange={() => handleCommunitySearchToggle(true)} />
|
||||
{t('search_feed_post')}
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
}
|
||||
|
||||
.searchBarWrapper {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
@@ -390,7 +392,7 @@ a {
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.createCommunitySubtitles {
|
||||
.communitySubtitles {
|
||||
position: relative;
|
||||
margin-top: 10px;
|
||||
padding: 5px 0 0 44px;
|
||||
|
||||
@@ -29,7 +29,7 @@ import SubscribeButton from '../subscribe-button';
|
||||
import LoadingEllipsis from '../loading-ellipsis';
|
||||
import Version from '../version';
|
||||
import { FAQ } from '../../views/about/about';
|
||||
import { createCommunitySubtitles } from '../../constants/create-community-subtitles';
|
||||
import { communitySubtitles } from '../../constants/community-subtitles';
|
||||
|
||||
const isElectron = window.electronApi?.isElectron === true;
|
||||
|
||||
@@ -236,18 +236,18 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
const [subtitle2, setSubtitle2] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (createCommunitySubtitles.length >= 2) {
|
||||
if (communitySubtitles.length >= 2) {
|
||||
const indices = new Set<number>();
|
||||
while (indices.size < 2) {
|
||||
const randomIndex = Math.floor(Math.random() * createCommunitySubtitles.length);
|
||||
const randomIndex = Math.floor(Math.random() * communitySubtitles.length);
|
||||
indices.add(randomIndex);
|
||||
}
|
||||
const [index1, index2] = Array.from(indices);
|
||||
setSubtitle1(createCommunitySubtitles[index1]);
|
||||
setSubtitle2(createCommunitySubtitles[index2]);
|
||||
} else if (createCommunitySubtitles.length === 1) {
|
||||
setSubtitle1(communitySubtitles[index1]);
|
||||
setSubtitle2(communitySubtitles[index2]);
|
||||
} else if (communitySubtitles.length === 1) {
|
||||
// Handle case with only one subtitle
|
||||
setSubtitle1(createCommunitySubtitles[0]);
|
||||
setSubtitle1(communitySubtitles[0]);
|
||||
setSubtitle2(''); // Or handle as needed
|
||||
}
|
||||
}, []); // Empty dependency array ensures this runs only once on mount
|
||||
@@ -375,7 +375,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
{t('create_your_community')}
|
||||
<div className={styles.nub} />
|
||||
</div>
|
||||
<div className={styles.createCommunitySubtitles}>
|
||||
<div className={styles.communitySubtitles}>
|
||||
<span className={styles.createCommunityImage}>
|
||||
<img src='assets/sprout/sprout-2.png' alt='' />
|
||||
</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const createCommunitySubtitles = [
|
||||
export const communitySubtitles = [
|
||||
'...unstoppable by design.',
|
||||
'...servers are overrated.',
|
||||
'...cryptographic playground.',
|
||||
@@ -23,4 +23,9 @@ export const createCommunitySubtitles = [
|
||||
'...because you love freedom.',
|
||||
'...decentralized, but for real.',
|
||||
'...for your peace of mind.',
|
||||
'...no corporation to answer to.',
|
||||
'...for your peace of mind.',
|
||||
'...your tokenized sovereignty.',
|
||||
'...for text-only wonders.',
|
||||
'...because open source rulez.',
|
||||
];
|
||||
24
src/stores/use-error-store.ts
Normal file
24
src/stores/use-error-store.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface ErrorStoreState {
|
||||
errors: Record<string, Error | null>;
|
||||
setError: (source: string, error: Error | null | undefined) => void;
|
||||
clearAllErrors: () => void;
|
||||
}
|
||||
|
||||
const useErrorStore = create<ErrorStoreState>((set) => ({
|
||||
errors: {},
|
||||
setError: (source, error) =>
|
||||
set((state) => {
|
||||
const newErrors = { ...state.errors };
|
||||
if (error) {
|
||||
newErrors[source] = error;
|
||||
} else {
|
||||
delete newErrors[source];
|
||||
}
|
||||
return { errors: newErrors };
|
||||
}),
|
||||
clearAllErrors: () => set({ errors: {} }),
|
||||
}));
|
||||
|
||||
export default useErrorStore;
|
||||
@@ -49,11 +49,11 @@ export const FAQ = () => {
|
||||
New Users:
|
||||
</h3>
|
||||
<p>
|
||||
Welcome! Your account <Link to='/profile'>u/{account?.author?.shortAddress}</Link> was created automatically and it's stored locally (
|
||||
{window.electronApi?.isElectron ? 'on this desktop app' : isAndroid ? 'on this mobile app' : `on ${window.location.hostname}`}, not on a server). You can back
|
||||
up your account in the <Link to='/settings#exportAccount'>preferences</Link>. There are no global rules or admins on Seedit, each community has its own rules
|
||||
and moderators, so please be sure to read the rules of the community you are joining. You can connect peer-to-peer to any community by using the search bar, or
|
||||
you can check out the <Link to='/communities/vote'>default community list</Link>.
|
||||
Welcome! Your account was created automatically and it's stored locally on your device (
|
||||
{window.electronApi?.isElectron ? 'on this desktop app' : isAndroid ? 'on this mobile app' : `on this web app, ${window.location.hostname}`}, not on a server).
|
||||
You can back up your account in the <Link to='/settings#exportAccount'>preferences</Link>. There are no global rules or admins on Seedit, each community has its
|
||||
own rules and moderators, so please be sure to read the rules of the community you are joining. You can connect peer-to-peer to any community by using the
|
||||
search bar, or you can check out the <Link to='/communities/vote'>default community list</Link>.
|
||||
</p>
|
||||
<hr />
|
||||
<h3 id='whatIsSeedit'>What is Seedit and how does it work?</h3>
|
||||
@@ -130,7 +130,7 @@ export const FAQ = () => {
|
||||
is generated randomly from a cryptographic hash of your public key, similarly to how a bitcoin address is generated. You can{' '}
|
||||
<HashLink to='/settings#cryptoAddress'>change your account address</HashLink> to a unique readable name you own, by resolving it with a decentralized domain
|
||||
name service such as{' '}
|
||||
<a href='https://sns.id' target='_blank' rel='noopener noreferrer'>
|
||||
<a href='https://ens.domains/' target='_blank' rel='noopener noreferrer'>
|
||||
ENS
|
||||
</a>{' '}
|
||||
or{' '}
|
||||
|
||||
@@ -58,11 +58,13 @@ const All = () => {
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
options.filter = (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
options.filter = {
|
||||
filter: (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
},
|
||||
key: `search-filter-${searchQuery}`,
|
||||
};
|
||||
options.filterKey = `search-filter-${searchQuery}`;
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
@@ -30,4 +30,11 @@ div[data-viewport-type="window"] {
|
||||
display: inline-block;
|
||||
padding: 10px 0 0px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
padding-left: 10px;
|
||||
font-size: 12px;
|
||||
margin-top: -10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import Post from '../../components/post';
|
||||
import Reply from '../../components/reply/';
|
||||
import AuthorSidebar from '../../components/author-sidebar';
|
||||
import styles from './author.module.css';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
@@ -24,7 +25,13 @@ const Author = () => {
|
||||
const isInAuthorSubmittedView = isAuthorSubmittedView(location.pathname, params);
|
||||
const isMobile = useWindowWidth() < 640;
|
||||
|
||||
const { authorComments, lastCommentCid, hasMore, loadMore } = useAuthorComments({ commentCid, authorAddress });
|
||||
const { authorComments, error, lastCommentCid, hasMore, loadMore } = useAuthorComments({ commentCid, authorAddress });
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
const replyComments = useMemo(() => authorComments?.filter((comment) => comment && comment.parentCid) || [], [authorComments]);
|
||||
const postComments = useMemo(() => authorComments?.filter((comment) => comment && !comment.parentCid) || [], [authorComments]);
|
||||
@@ -82,6 +89,11 @@ const Author = () => {
|
||||
<div className={isMobile ? styles.sidebarMobile : styles.sidebarDesktop}>
|
||||
<AuthorSidebar />
|
||||
</div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<Virtuoso
|
||||
increaseViewportBy={{ bottom: 1200, top: 600 }}
|
||||
totalCount={authorComments?.length || 0}
|
||||
|
||||
@@ -165,3 +165,10 @@
|
||||
background-color: var(--button-background-color-hover);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 12px;
|
||||
margin-top: -10px;
|
||||
padding-left: 5px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
@@ -69,11 +69,13 @@ const Home = () => {
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
options.filter = (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
options.filter = {
|
||||
filter: (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
},
|
||||
key: `search-filter-${searchQuery}`,
|
||||
};
|
||||
options.filterKey = `search-filter-${searchQuery}`;
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
@@ -7,6 +7,7 @@ import Reply from '../../components/reply/reply';
|
||||
import { isInboxCommentRepliesView, isInboxPostRepliesView, isInboxUnreadView } from '../../lib/utils/view-utils';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import _ from 'lodash';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
@@ -43,7 +44,7 @@ const Inbox = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const { unreadNotificationCount } = account || {};
|
||||
const { notifications, markAsRead } = useNotifications();
|
||||
const { error, notifications, markAsRead } = useNotifications();
|
||||
|
||||
const location = useLocation();
|
||||
const isInInboxCommentRepliesView = isInboxCommentRepliesView(location.pathname);
|
||||
@@ -97,6 +98,12 @@ const Inbox = () => {
|
||||
document.title = documentTitle;
|
||||
}, [documentTitle]);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<InboxTabs />
|
||||
@@ -109,6 +116,11 @@ const Inbox = () => {
|
||||
<div className={styles.noNotifications}>{t('nothing_found')}</div>
|
||||
)}
|
||||
</div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<Virtuoso
|
||||
increaseViewportBy={{ bottom: 1200, top: 600 }}
|
||||
totalCount={notifications?.length || 0}
|
||||
|
||||
@@ -49,11 +49,13 @@ const Mod = () => {
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
options.filter = (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
options.filter = {
|
||||
filter: (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
},
|
||||
key: `search-filter-${searchQuery}`,
|
||||
};
|
||||
options.filterKey = `search-filter-${searchQuery}`;
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
@@ -184,10 +184,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
.noReplies, .error {
|
||||
.noReplies {
|
||||
color: var(--red);
|
||||
font-size: 13px;
|
||||
text-transform: lowercase;
|
||||
padding-top: 19px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.error {
|
||||
padding-left: 3px;
|
||||
font-size: 13px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
@@ -1,23 +1,24 @@
|
||||
import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { Comment, useAccount, useAccountComment, useAccountComments, useComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Comment, useAccount, useAccountComment, useAccountComments, useComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import findTopParentCidOfReply from '../../lib/utils/cid-utils';
|
||||
import { sortRepliesByBest } from '../../lib/utils/post-utils';
|
||||
import { isPendingPostView, isPostContextView } from '../../lib/utils/view-utils';
|
||||
import useContentOptionsStore from '../../stores/use-content-options-store';
|
||||
import useFeedResetStore from '../../stores/use-feed-reset-store';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
import useReplies from '../../hooks/use-replies';
|
||||
import useStateString from '../../hooks/use-state-string';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Over18Warning from '../../components/over-18-warning';
|
||||
import PostComponent from '../../components/post';
|
||||
import Reply from '../../components/reply';
|
||||
import ReplyForm from '../../components/reply-form';
|
||||
import PostComponent from '../../components/post';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
import styles from './post-page.module.css';
|
||||
import _ from 'lodash';
|
||||
import Over18Warning from '../../components/over-18-warning';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
import useContentOptionsStore from '../../stores/use-content-options-store';
|
||||
import useFeedResetStore from '../../stores/use-feed-reset-store';
|
||||
|
||||
type SortDropdownProps = {
|
||||
sortBy: string;
|
||||
@@ -80,7 +81,7 @@ const Post = ({ post }: { post: Comment }) => {
|
||||
const params = useParams();
|
||||
const isInPostContextView = isPostContextView(location.pathname, params, location.search);
|
||||
|
||||
const { cid, deleted, depth, error, locked, removed, postCid, replyCount, state, subplebbitAddress, timestamp } = post || {};
|
||||
const { cid, deleted, depth, locked, removed, postCid, replyCount, state, subplebbitAddress, timestamp } = post || {};
|
||||
|
||||
const [sortBy, setSortBy] = useState('best');
|
||||
const unsortedReplies = useReplies(post);
|
||||
@@ -170,11 +171,6 @@ const Post = ({ post }: { post: Comment }) => {
|
||||
{replies.length === 0 && replyCount !== undefined && !(isInPostContextView || isSingleComment) && (
|
||||
<div className={styles.noReplies}>{t('nothing_found')}</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
{t('error')}: {error.message}
|
||||
</div>
|
||||
)}
|
||||
{isSingleComment ? (
|
||||
<Reply key={`singleComment-${cid}`} reply={post} depth={0} isSingleComment={true} />
|
||||
) : (
|
||||
@@ -285,6 +281,12 @@ const PostPage = () => {
|
||||
const { hasAcceptedWarning } = useContentOptionsStore();
|
||||
const isBroadlyNsfwSubplebbit = useIsBroadlyNsfwSubplebbit(subplebbitAddress || '');
|
||||
|
||||
useEffect(() => {
|
||||
if (post?.error) {
|
||||
console.log(post.error);
|
||||
}
|
||||
}, [post?.error]);
|
||||
|
||||
const postTitle = post.title?.slice(0, 40) || post?.content?.slice(0, 40);
|
||||
const subplebbitTitle = subplebbit?.title || subplebbit?.shortAddress;
|
||||
useEffect(() => {
|
||||
@@ -303,6 +305,11 @@ const PostPage = () => {
|
||||
<Sidebar subplebbit={subplebbit} comment={post} settings={subplebbit?.settings} />
|
||||
</div>
|
||||
{isInPendingPostView && params?.accountCommentIndex ? <Post post={pendingPost} /> : isInPostContextView ? <PostWithContext post={post} /> : <Post post={post} />}
|
||||
{post?.error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={post.error} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -147,3 +147,10 @@ div[data-viewport-type="window"] {
|
||||
margin-right: -3px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.error {
|
||||
padding-left: 10px;
|
||||
font-size: 12px;
|
||||
margin-top: -10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import AuthorSidebar from '../../components/author-sidebar';
|
||||
import Post from '../../components/post';
|
||||
import Reply from '../../components/reply';
|
||||
import styles from './profile.module.css';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
|
||||
const pageSize = 10;
|
||||
const sortTypes: string[] = ['new', 'old'];
|
||||
@@ -135,15 +136,26 @@ const VirtualizedCommentList = ({ comments }: { comments: any[] }) => {
|
||||
|
||||
const Overview = () => {
|
||||
const { t } = useTranslation();
|
||||
const { accountComments } = useAccountComments();
|
||||
const { error, accountComments } = useAccountComments();
|
||||
const [sortType, setSortType] = useState('new');
|
||||
|
||||
const sortedComments = useMemo(() => {
|
||||
return [...accountComments].sort((a, b) => (sortType === 'new' ? b.timestamp - a.timestamp : a.timestamp - b.timestamp));
|
||||
}, [accountComments, sortType]);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<SortDropdown onSortChange={setSortType} />
|
||||
{sortedComments.length === 0 ? <div className={styles.nothingFound}>{t('nothing_found')}</div> : <VirtualizedCommentList comments={sortedComments} />}
|
||||
</div>
|
||||
@@ -152,7 +164,7 @@ const Overview = () => {
|
||||
|
||||
const Comments = () => {
|
||||
const { t } = useTranslation();
|
||||
const { accountComments } = useAccountComments();
|
||||
const { error, accountComments } = useAccountComments();
|
||||
const [sortType, setSortType] = useState('new');
|
||||
|
||||
const replyComments = useMemo(() => accountComments?.filter((comment) => comment.parentCid) || [], [accountComments]);
|
||||
@@ -161,8 +173,19 @@ const Comments = () => {
|
||||
return [...replyComments].sort((a, b) => (sortType === 'new' ? b.timestamp - a.timestamp : a.timestamp - b.timestamp));
|
||||
}, [replyComments, sortType]);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<SortDropdown onSortChange={setSortType} />
|
||||
{sortedComments.length === 0 ? <div className={styles.nothingFound}>{t('nothing_found')}</div> : <VirtualizedCommentList comments={sortedComments} />}
|
||||
</div>
|
||||
@@ -171,7 +194,7 @@ const Comments = () => {
|
||||
|
||||
const Submitted = () => {
|
||||
const { t } = useTranslation();
|
||||
const { accountComments } = useAccountComments();
|
||||
const { error, accountComments } = useAccountComments();
|
||||
const [sortType, setSortType] = useState('new');
|
||||
|
||||
const postComments = useMemo(() => accountComments?.filter((comment) => !comment.parentCid) || [], [accountComments]);
|
||||
@@ -180,8 +203,19 @@ const Submitted = () => {
|
||||
return [...postComments].sort((a, b) => (sortType === 'new' ? b.timestamp - a.timestamp : a.timestamp - b.timestamp));
|
||||
}, [postComments, sortType]);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<SortDropdown onSortChange={setSortType} />
|
||||
{sortedComments.length === 0 ? <div className={styles.nothingFound}>{t('nothing_found')}</div> : <VirtualizedCommentList comments={sortedComments} />}
|
||||
</div>
|
||||
@@ -190,7 +224,7 @@ const Submitted = () => {
|
||||
|
||||
const VotedComments = ({ voteType }: { voteType: 1 | -1 }) => {
|
||||
const { t } = useTranslation();
|
||||
const { accountVotes } = useAccountVotes();
|
||||
const { error, accountVotes } = useAccountVotes();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sortType, setSortType] = useState('new');
|
||||
|
||||
@@ -203,8 +237,19 @@ const VotedComments = ({ voteType }: { voteType: 1 | -1 }) => {
|
||||
const paginatedCids = votedCommentCids.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
||||
const hasMore = currentPage * pageSize < votedCommentCids.length;
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<SortDropdown onSortChange={setSortType} />
|
||||
{paginatedCids.length === 0 ? <div className={styles.nothingFound}>{t('nothing_found')}</div> : paginatedCids.map((cid) => <CommentItem key={cid} cid={cid} />)}
|
||||
<PaginationControls currentPage={currentPage} hasMore={hasMore} onPageChange={setCurrentPage} />
|
||||
|
||||
@@ -166,7 +166,10 @@ const AccountSettings = () => {
|
||||
const [text, setText] = useState('');
|
||||
|
||||
const accountJson = useMemo(
|
||||
() => stringify({ account: { ...account, plebbit: undefined, karma: undefined, plebbitReactOptions: undefined, unreadNotificationCount: undefined } }),
|
||||
() =>
|
||||
stringify({
|
||||
account: { ...account, plebbit: undefined, karma: undefined, plebbitReactOptions: undefined, unreadNotificationCount: undefined, signer: undefined },
|
||||
}),
|
||||
[account],
|
||||
);
|
||||
|
||||
@@ -192,10 +195,19 @@ const AccountSettings = () => {
|
||||
|
||||
const saveAccount = async () => {
|
||||
try {
|
||||
const newAccount = JSON.parse(text).account;
|
||||
// force keeping the same id, makes it easier to copy paste
|
||||
await setAccount({ ...newAccount, id: account?.id });
|
||||
alert(`Saved ${newAccount.name}`);
|
||||
const newAccountFromTextarea = JSON.parse(text).account;
|
||||
// re-attach all original fields that were not meant to be editable in the textarea
|
||||
const finalAccount = {
|
||||
...newAccountFromTextarea,
|
||||
id: account?.id, // force keeping the same id, makes it easier to copy paste
|
||||
signer: account?.signer,
|
||||
plebbit: account?.plebbit,
|
||||
karma: account?.karma,
|
||||
plebbitReactOptions: account?.plebbitReactOptions,
|
||||
unreadNotificationCount: account?.unreadNotificationCount,
|
||||
};
|
||||
await setAccount(finalAccount);
|
||||
alert(`Saved ${finalAccount.name}`);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
alert(error.message);
|
||||
|
||||
@@ -12,6 +12,7 @@ import useFeedResetStore from '../../stores/use-feed-reset-store';
|
||||
import { usePinnedPostsStore } from '../../stores/use-pinned-posts-store';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Over18Warning from '../../components/over-18-warning';
|
||||
import Post from '../../components/post';
|
||||
@@ -27,7 +28,6 @@ interface FooterProps {
|
||||
isOnline: boolean;
|
||||
started: boolean;
|
||||
isSubCreatedButNotYetPublished: boolean;
|
||||
error: Error | null;
|
||||
hasMore: boolean;
|
||||
timeFilterName: string;
|
||||
reset: () => void;
|
||||
@@ -43,7 +43,6 @@ const Footer = ({
|
||||
isOnline,
|
||||
started,
|
||||
isSubCreatedButNotYetPublished,
|
||||
error,
|
||||
hasMore,
|
||||
timeFilterName,
|
||||
reset,
|
||||
@@ -85,12 +84,6 @@ const Footer = ({
|
||||
const loadingString = (
|
||||
<>
|
||||
<div className={styles.stateString}>{loadingStateString === 'Failed' ? 'failed' : <LoadingEllipsis string={loadingStateString} />}</div>
|
||||
{error && (
|
||||
<div style={{ color: 'red' }}>
|
||||
<br />
|
||||
{t('error')}: {error.message}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -258,11 +251,13 @@ const Subplebbit = () => {
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
options.filter = (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
options.filter = {
|
||||
filter: (comment: Comment) => {
|
||||
if (!searchQuery.trim()) return true;
|
||||
return commentMatchesPattern(comment, searchQuery);
|
||||
},
|
||||
key: `search-filter-${searchQuery}`,
|
||||
};
|
||||
options.filterKey = `search-filter-${searchQuery}`;
|
||||
}
|
||||
|
||||
return options;
|
||||
@@ -330,7 +325,6 @@ const Subplebbit = () => {
|
||||
isOnline,
|
||||
started,
|
||||
isSubCreatedButNotYetPublished,
|
||||
error: error || null,
|
||||
hasMore,
|
||||
timeFilterName: searchQuery ? 'all' : timeFilterName || '',
|
||||
reset,
|
||||
@@ -359,6 +353,12 @@ const Subplebbit = () => {
|
||||
const hasUnhiddenAnyNsfwCommunity = !hideAdultCommunities || !hideGoreCommunities || !hideAntiCommunities || !hideVulgarCommunities;
|
||||
const isBroadlyNsfwSubplebbit = useIsBroadlyNsfwSubplebbit(subplebbitAddress || '');
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
// page title
|
||||
useEffect(() => {
|
||||
document.title = title ? title : shortAddress || subplebbitAddress;
|
||||
@@ -371,6 +371,11 @@ const Subplebbit = () => {
|
||||
<div className={styles.sidebar}>
|
||||
<Sidebar subplebbit={subplebbit} isSubCreatedButNotYetPublished={started && isSubCreatedButNotYetPublished} settings={settings} reset={reset} />
|
||||
</div>
|
||||
{error && (
|
||||
<div className={styles.error}>
|
||||
<ErrorDisplay error={error} />
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.feed}>
|
||||
<Virtuoso
|
||||
increaseViewportBy={{ bottom: 1200, top: 600 }}
|
||||
|
||||
@@ -340,3 +340,10 @@
|
||||
vertical-align: top;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 12px;
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
@@ -14,10 +14,12 @@ import {
|
||||
isSubplebbitsVotePassingView,
|
||||
isSubplebbitsVoteRejectingView,
|
||||
} from '../../lib/utils/view-utils';
|
||||
import useErrorStore from '../../stores/use-error-store';
|
||||
import { useDefaultSubplebbitAddresses, useDefaultSubplebbitTags } from '../../hooks/use-default-subplebbits';
|
||||
import { useDefaultSubplebbits } from '../../hooks/use-default-subplebbits';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
import Markdown from '../../components/markdown';
|
||||
import Label from '../../components/post/label';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
@@ -108,7 +110,13 @@ const VoteTabs = () => {
|
||||
|
||||
const Infobar = () => {
|
||||
const account = useAccount();
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const { accountSubplebbits, error: accountSubplebbitsError } = useAccountSubplebbits();
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
setError('Infobar_useAccountSubplebbits', accountSubplebbitsError);
|
||||
}, [accountSubplebbitsError, setError]);
|
||||
|
||||
const subscriptions = account?.subscriptions || [];
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
@@ -285,7 +293,12 @@ const Subplebbit = ({ subplebbit, tags, index }: SubplebbitProps) => {
|
||||
|
||||
const AccountSubplebbits = ({ viewRole }: { viewRole: string }) => {
|
||||
const account = useAccount();
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const { accountSubplebbits, error: accountSubplebbitsError } = useAccountSubplebbits();
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
setError('AccountSubplebbits_useAccountSubplebbits', accountSubplebbitsError);
|
||||
}, [accountSubplebbitsError, setError, viewRole]);
|
||||
|
||||
const filteredSubplebbitsArray = useMemo(() => {
|
||||
return Object.values(accountSubplebbits).filter((subplebbit: any) => {
|
||||
@@ -300,7 +313,13 @@ const AccountSubplebbits = ({ viewRole }: { viewRole: string }) => {
|
||||
|
||||
const SubscriberSubplebbits = () => {
|
||||
const account = useAccount();
|
||||
const { subplebbits } = useSubplebbits({ subplebbitAddresses: account?.subscriptions });
|
||||
const { subplebbits, error: subplebbitsError } = useSubplebbits({ subplebbitAddresses: account?.subscriptions });
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
setError('SubscriberSubplebbits_useSubplebbits', subplebbitsError);
|
||||
}, [subplebbitsError, setError]);
|
||||
|
||||
const subplebbitsArray = useMemo(() => Object.values(subplebbits), [subplebbits]);
|
||||
return subplebbitsArray?.map((subplebbit, index) => subplebbit && <Subplebbit key={index} subplebbit={subplebbit} index={index} />).filter(Boolean);
|
||||
};
|
||||
@@ -314,7 +333,13 @@ const AllDefaultSubplebbits = () => {
|
||||
const urlTag = pathname.includes('/tag/') ? pathname.split('/').pop() : undefined;
|
||||
const currentTag = urlTag && validTags.includes(urlTag) ? urlTag : undefined;
|
||||
|
||||
const { subplebbits } = useSubplebbits({ subplebbitAddresses });
|
||||
const { subplebbits, error: subplebbitsError } = useSubplebbits({ subplebbitAddresses });
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
setError('AllDefaultSubplebbits_useSubplebbits', subplebbitsError);
|
||||
}, [subplebbitsError, setError]);
|
||||
|
||||
const subplebbitsArray = useMemo(() => Object.values(subplebbits), [subplebbits]);
|
||||
|
||||
return subplebbitsArray
|
||||
@@ -329,11 +354,21 @@ const AllDefaultSubplebbits = () => {
|
||||
|
||||
const AllAccountSubplebbits = () => {
|
||||
const account = useAccount();
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const { accountSubplebbits, error: accountSubplebbitsError } = useAccountSubplebbits();
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
setError('AllAccountSubplebbits_useAccountSubplebbits', accountSubplebbitsError);
|
||||
}, [accountSubplebbitsError, setError]);
|
||||
|
||||
const accountSubplebbitAddresses = Object.keys(accountSubplebbits);
|
||||
const subscriptionsArray = account?.subscriptions ?? [];
|
||||
const uniqueAddresses = Array.from(new Set([...accountSubplebbitAddresses, ...subscriptionsArray]));
|
||||
const { subplebbits } = useSubplebbits({ subplebbitAddresses: uniqueAddresses });
|
||||
const { subplebbits, error: subplebbitsError } = useSubplebbits({ subplebbitAddresses: uniqueAddresses });
|
||||
|
||||
useEffect(() => {
|
||||
setError('AllAccountSubplebbits_useSubplebbits', subplebbitsError);
|
||||
}, [subplebbitsError, setError]);
|
||||
const subplebbitsArray = useMemo(() => Object.values(subplebbits ?? {}), [subplebbits]);
|
||||
return subplebbitsArray?.map((subplebbit, index) => subplebbit && <Subplebbit key={index} subplebbit={subplebbit} index={index} />).filter(Boolean);
|
||||
};
|
||||
@@ -341,6 +376,24 @@ const AllAccountSubplebbits = () => {
|
||||
const Subplebbits = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const { errors, clearAllErrors } = useErrorStore();
|
||||
|
||||
// Clear errors on component unmount or location change
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearAllErrors();
|
||||
};
|
||||
}, [location, clearAllErrors]);
|
||||
|
||||
// Console log errors
|
||||
useEffect(() => {
|
||||
Object.entries(errors).forEach(([source, errorObj]) => {
|
||||
if (errorObj) {
|
||||
console.error(`Error from ${source}:`, errorObj.message, errorObj.stack);
|
||||
}
|
||||
});
|
||||
}, [errors]);
|
||||
|
||||
const isInSubplebbitsSubscriberView = isSubplebbitsSubscriberView(location.pathname);
|
||||
const isInSubplebbitsModeratorView = isSubplebbitsModeratorView(location.pathname);
|
||||
const isInSubplebbitsAdminView = isSubplebbitsAdminView(location.pathname);
|
||||
@@ -385,6 +438,32 @@ const Subplebbits = () => {
|
||||
document.title = documentTitle;
|
||||
}, [documentTitle]);
|
||||
|
||||
const renderErrors = () => {
|
||||
const errorsToDisplay: JSX.Element[] = [];
|
||||
Object.entries(errors).forEach(([source, errorObj]) => {
|
||||
if (!errorObj) return;
|
||||
|
||||
if (
|
||||
source === 'Infobar_useAccountSubplebbits' &&
|
||||
(isInSubplebbitsView || isInSubplebbitsSubscriberView || isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView)
|
||||
) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AccountSubplebbits_useAccountSubplebbits' && (isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView)) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'SubscriberSubplebbits_useSubplebbits' && isInSubplebbitsSubscriberView) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AllDefaultSubplebbits_useSubplebbits' && isInSubplebbitsVoteView) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AllAccountSubplebbits_useAccountSubplebbits' && isInSubplebbitsView) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AllAccountSubplebbits_useSubplebbits' && isInSubplebbitsView) {
|
||||
// Avoid duplicate key if both errors from AllAccountSubplebbits are present
|
||||
errorsToDisplay.push(<ErrorDisplay key={`${source}_subplebbits`} error={errorObj} />);
|
||||
}
|
||||
});
|
||||
return errorsToDisplay;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<div className={styles.sidebar}>
|
||||
@@ -396,6 +475,7 @@ const Subplebbits = () => {
|
||||
<VoteTabs />
|
||||
)}
|
||||
<Infobar />
|
||||
<div className={styles.error}>{renderErrors()}</div>
|
||||
{isInSubplebbitsVoteView && <AllDefaultSubplebbits />}
|
||||
{(isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView) && <AccountSubplebbits viewRole={viewRole} />}
|
||||
{isInSubplebbitsSubscriberView && <SubscriberSubplebbits />}
|
||||
|
||||
171
yarn.lock
171
yarn.lock
@@ -3373,12 +3373,12 @@
|
||||
dependencies:
|
||||
"@noble/hashes" "1.3.2"
|
||||
|
||||
"@noble/curves@1.8.1":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.1.tgz#19bc3970e205c99e4bdb1c64a4785706bce497ff"
|
||||
integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==
|
||||
"@noble/curves@1.8.2", "@noble/curves@~1.8.1":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7"
|
||||
integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==
|
||||
dependencies:
|
||||
"@noble/hashes" "1.7.1"
|
||||
"@noble/hashes" "1.7.2"
|
||||
|
||||
"@noble/curves@^1.1.0", "@noble/curves@^1.4.0", "@noble/curves@^1.4.2", "@noble/curves@^1.6.0", "@noble/curves@^1.7.0", "@noble/curves@~1.9.0":
|
||||
version "1.9.0"
|
||||
@@ -3387,13 +3387,6 @@
|
||||
dependencies:
|
||||
"@noble/hashes" "1.8.0"
|
||||
|
||||
"@noble/curves@~1.8.1":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7"
|
||||
integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==
|
||||
dependencies:
|
||||
"@noble/hashes" "1.7.2"
|
||||
|
||||
"@noble/ed25519@^1.5.1":
|
||||
version "1.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.5.tgz#94df8bdb9fec9c4644a56007eecb57b0e9fbd0d7"
|
||||
@@ -3404,11 +3397,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
|
||||
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
|
||||
|
||||
"@noble/hashes@1.7.1":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f"
|
||||
integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==
|
||||
|
||||
"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1":
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4"
|
||||
@@ -3623,9 +3611,9 @@
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#26c097afa62a87c9650dcdfad52babbc77744cbc":
|
||||
version "0.0.6"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#26c097afa62a87c9650dcdfad52babbc77744cbc"
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#a2cb6ca6462b2e2e3b66f71204375a81ed05cf80":
|
||||
version "0.0.7"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#a2cb6ca6462b2e2e3b66f71204375a81ed05cf80"
|
||||
dependencies:
|
||||
"@bonfida/spl-name-service" "3.0.10"
|
||||
"@chainsafe/libp2p-gossipsub" "14.1.0"
|
||||
@@ -3652,9 +3640,9 @@
|
||||
cbor "9.0.1"
|
||||
debounce "1.2.1"
|
||||
err-code "3.0.1"
|
||||
ethers "6.13.5"
|
||||
ethers "6.14.0"
|
||||
ext-name "5.0.0"
|
||||
file-type "16.5.4"
|
||||
file-type "20.5.0"
|
||||
helia "5.2.0"
|
||||
hpagent "1.2.0"
|
||||
it-all "3.0.6"
|
||||
@@ -3686,8 +3674,8 @@
|
||||
ts-custom-error "3.3.1"
|
||||
typestub-ipfs-only-hash "4.0.0"
|
||||
uuid "11.1.0"
|
||||
viem "2.23.5"
|
||||
zod "3.24.3"
|
||||
viem "2.29.0"
|
||||
zod "3.24.4"
|
||||
|
||||
"@plebbit/plebbit-logger@github:plebbit/plebbit-logger#355a96d7659ed820047980049dfa627d30d83a69":
|
||||
version "0.0.1"
|
||||
@@ -3702,11 +3690,11 @@
|
||||
dependencies:
|
||||
debug "4.3.4"
|
||||
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#047a4e01377fba0b5cf1531814446715d7130aa4":
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#9d0e851a4a571e15053343c66186418958d53550":
|
||||
version "0.0.1"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#047a4e01377fba0b5cf1531814446715d7130aa4"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#9d0e851a4a571e15053343c66186418958d53550"
|
||||
dependencies:
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#26c097afa62a87c9650dcdfad52babbc77744cbc"
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#a2cb6ca6462b2e2e3b66f71204375a81ed05cf80"
|
||||
"@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git"
|
||||
assert "2.0.0"
|
||||
ethers "5.6.9"
|
||||
@@ -3718,11 +3706,11 @@
|
||||
uuid "8.3.2"
|
||||
zustand "4.0.0"
|
||||
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#41f0cdf14617f5e843311986d66f14f2f8fcbce0":
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#d6347601b40a237c26518ab9cc9de7d29bb69b62":
|
||||
version "0.0.1"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#41f0cdf14617f5e843311986d66f14f2f8fcbce0"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#d6347601b40a237c26518ab9cc9de7d29bb69b62"
|
||||
dependencies:
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#26c097afa62a87c9650dcdfad52babbc77744cbc"
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#a2cb6ca6462b2e2e3b66f71204375a81ed05cf80"
|
||||
"@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git"
|
||||
assert "2.0.0"
|
||||
ethers "5.6.9"
|
||||
@@ -4338,6 +4326,15 @@
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
"@tokenizer/inflate@^0.2.6":
|
||||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@tokenizer/inflate/-/inflate-0.2.7.tgz#32dd9dfc9abe457c89b3d9b760fc0690c85a103b"
|
||||
integrity sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==
|
||||
dependencies:
|
||||
debug "^4.4.0"
|
||||
fflate "^0.8.2"
|
||||
token-types "^6.0.0"
|
||||
|
||||
"@tokenizer/token@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
|
||||
@@ -6900,7 +6897,7 @@ debug@2:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6:
|
||||
debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6, debug@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
|
||||
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
||||
@@ -8109,10 +8106,10 @@ ethers@5.6.9:
|
||||
"@ethersproject/web" "5.6.1"
|
||||
"@ethersproject/wordlists" "5.6.1"
|
||||
|
||||
ethers@6.13.5:
|
||||
version "6.13.5"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.5.tgz#8c1d6ac988ac08abc3c1d8fabbd4b8b602851ac4"
|
||||
integrity sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==
|
||||
ethers@6.14.0:
|
||||
version "6.14.0"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.14.0.tgz#b80eca3b60fc97da53f73b77629ce7392568eae0"
|
||||
integrity sha512-KgHwltNSMdbrGWEyKkM0Rt2s+u1nDH/5BVDQakLinzGEJi4bWindBzZSCC4gKsbZjwDTI6ex/8suR9Ihbmz4IQ==
|
||||
dependencies:
|
||||
"@adraffy/ens-normalize" "1.10.1"
|
||||
"@noble/curves" "1.2.0"
|
||||
@@ -8328,6 +8325,11 @@ fdir@^6.4.4:
|
||||
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9"
|
||||
integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==
|
||||
|
||||
fflate@^0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea"
|
||||
integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
|
||||
|
||||
figures@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
||||
@@ -8349,14 +8351,15 @@ file-selector@^2.1.0:
|
||||
dependencies:
|
||||
tslib "^2.7.0"
|
||||
|
||||
file-type@16.5.4:
|
||||
version "16.5.4"
|
||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd"
|
||||
integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==
|
||||
file-type@20.5.0:
|
||||
version "20.5.0"
|
||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-20.5.0.tgz#616e90564e6ffabab22ad9763e28efcc5c95aee0"
|
||||
integrity sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==
|
||||
dependencies:
|
||||
readable-web-to-node-stream "^3.0.0"
|
||||
strtok3 "^6.2.4"
|
||||
token-types "^4.1.1"
|
||||
"@tokenizer/inflate" "^0.2.6"
|
||||
strtok3 "^10.2.0"
|
||||
token-types "^6.0.0"
|
||||
uint8array-extras "^1.4.0"
|
||||
|
||||
file-type@^3.8.0:
|
||||
version "3.9.0"
|
||||
@@ -12385,10 +12388,10 @@ own-keys@^1.0.1:
|
||||
object-keys "^1.1.1"
|
||||
safe-push-apply "^1.0.0"
|
||||
|
||||
ox@0.6.7:
|
||||
version "0.6.7"
|
||||
resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832"
|
||||
integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==
|
||||
ox@0.6.9:
|
||||
version "0.6.9"
|
||||
resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.9.tgz#da1ee04fa10de30c8d04c15bfb80fe58b1f554bd"
|
||||
integrity sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==
|
||||
dependencies:
|
||||
"@adraffy/ens-normalize" "^1.10.1"
|
||||
"@noble/curves" "^1.6.0"
|
||||
@@ -12662,10 +12665,10 @@ pbkdf2@^3.1.2:
|
||||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
peek-readable@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72"
|
||||
integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==
|
||||
peek-readable@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-7.0.0.tgz#c6e4e78ec76f7005e5f6b51ffc93fdb91ede6512"
|
||||
integrity sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==
|
||||
|
||||
peer-id@0.16.0:
|
||||
version "0.16.0"
|
||||
@@ -13232,7 +13235,7 @@ readable-stream@3, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stre
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@4.7.0, readable-stream@^4.7.0:
|
||||
readable-stream@4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91"
|
||||
integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==
|
||||
@@ -13256,13 +13259,6 @@ readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.8:
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-web-to-node-stream@^3.0.0:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz#392ba37707af5bf62d725c36c1b5d6ef4119eefc"
|
||||
integrity sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==
|
||||
dependencies:
|
||||
readable-stream "^4.7.0"
|
||||
|
||||
rechoir@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
|
||||
@@ -14399,13 +14395,13 @@ strip-json-comments@~2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
|
||||
|
||||
strtok3@^6.2.4:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.3.0.tgz#358b80ffe6d5d5620e19a073aa78ce947a90f9a0"
|
||||
integrity sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==
|
||||
strtok3@^10.2.0:
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-10.2.2.tgz#a4c6d78d15db02c5eb20d92af3eedf81edaf09d2"
|
||||
integrity sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg==
|
||||
dependencies:
|
||||
"@tokenizer/token" "^0.3.0"
|
||||
peek-readable "^4.1.0"
|
||||
peek-readable "^7.0.0"
|
||||
|
||||
style-to-object@^0.4.0:
|
||||
version "0.4.4"
|
||||
@@ -14707,10 +14703,10 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
token-types@^4.1.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753"
|
||||
integrity sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==
|
||||
token-types@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/token-types/-/token-types-6.0.0.tgz#1ab26be1ef9c434853500c071acfe5c8dd6544a3"
|
||||
integrity sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==
|
||||
dependencies:
|
||||
"@tokenizer/token" "^0.3.0"
|
||||
ieee754 "^1.2.1"
|
||||
@@ -14954,6 +14950,11 @@ uint8-varint@^2.0.1, uint8-varint@^2.0.2, uint8-varint@^2.0.4:
|
||||
uint8arraylist "^2.0.0"
|
||||
uint8arrays "^5.0.0"
|
||||
|
||||
uint8array-extras@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uint8array-extras/-/uint8array-extras-1.4.0.tgz#e42a678a6dd335ec2d21661333ed42f44ae7cc74"
|
||||
integrity sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==
|
||||
|
||||
uint8arraylist@^2.0.0, uint8arraylist@^2.4.3, uint8arraylist@^2.4.8:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/uint8arraylist/-/uint8arraylist-2.4.8.tgz#5a4d17f4defd77799cb38e93fd5db0f0dceddc12"
|
||||
@@ -15348,19 +15349,19 @@ vfile@^6.0.0:
|
||||
"@types/unist" "^3.0.0"
|
||||
vfile-message "^4.0.0"
|
||||
|
||||
viem@2.23.5:
|
||||
version "2.23.5"
|
||||
resolved "https://registry.yarnpkg.com/viem/-/viem-2.23.5.tgz#50fb9ea0701d58e6a7a1714ecaa5edfa100bb391"
|
||||
integrity sha512-cUfBHdFQHmBlPW0loFXda0uZcoU+uJw3NRYQRwYgkrpH6PgovH8iuVqDn6t1jZk82zny4wQL54c9dCX2W9kLMg==
|
||||
viem@2.29.0:
|
||||
version "2.29.0"
|
||||
resolved "https://registry.yarnpkg.com/viem/-/viem-2.29.0.tgz#acaf936e534f61a2dfccd8128acce92bc724aba7"
|
||||
integrity sha512-N6GeIuuay/spDyw+5FbSuNIkVN0da+jGOjdlC0bdatIN+N0jtOf9Zfj0pbXgpIJGwnM9ocxzTRt0HZVbHBdL2Q==
|
||||
dependencies:
|
||||
"@noble/curves" "1.8.1"
|
||||
"@noble/hashes" "1.7.1"
|
||||
"@noble/curves" "1.8.2"
|
||||
"@noble/hashes" "1.7.2"
|
||||
"@scure/bip32" "1.6.2"
|
||||
"@scure/bip39" "1.5.4"
|
||||
abitype "1.0.8"
|
||||
isows "1.0.6"
|
||||
ox "0.6.7"
|
||||
ws "8.18.0"
|
||||
ox "0.6.9"
|
||||
ws "8.18.1"
|
||||
|
||||
vite-plugin-eslint@1.8.1:
|
||||
version "1.8.1"
|
||||
@@ -15802,21 +15803,16 @@ ws@8.17.1:
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b"
|
||||
integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==
|
||||
|
||||
ws@8.18.0:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
|
||||
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
|
||||
ws@8.18.1, ws@^8.18.0, ws@^8.4.0, ws@^8.5.0:
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb"
|
||||
integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==
|
||||
|
||||
ws@^7.5.10:
|
||||
version "7.5.10"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
|
||||
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
|
||||
|
||||
ws@^8.18.0, ws@^8.4.0, ws@^8.5.0:
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb"
|
||||
integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==
|
||||
|
||||
xml2js@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"
|
||||
@@ -15914,7 +15910,12 @@ zod-validation-error@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.4.0.tgz#3a8a1f55c65579822d7faa190b51336c61bee2a6"
|
||||
integrity sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==
|
||||
|
||||
zod@3.24.3, zod@^3.22.4:
|
||||
zod@3.24.4:
|
||||
version "3.24.4"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f"
|
||||
integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==
|
||||
|
||||
zod@^3.22.4:
|
||||
version "3.24.3"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.3.tgz#1f40f750a05e477396da64438e0e1c0995dafd87"
|
||||
integrity sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==
|
||||
|
||||
Reference in New Issue
Block a user