mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
+127
@@ -0,0 +1,127 @@
|
||||
## [0.1.13](https://github.com/plebbit/plebchan/compare/v0.1.12...v0.1.13) (2023-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **App.js:** remove automatic dark mode, because it's not part of 4chan UX and it's not old school, and the selected style is saved anyway ([e3b577b](https://github.com/plebbit/plebchan/commit/e3b577b6900ba87be0aab85745038dfe40fb6c6a))
|
||||
* **app:** new version info toast should only appear once ([bdb661b](https://github.com/plebbit/plebchan/commit/bdb661b0dc7317a37232c5a1869610b3efc1cbc0))
|
||||
* **CaptchaModal:** improve captcha visibility by fixing margin ([a312c64](https://github.com/plebbit/plebchan/commit/a312c64bb047f155bdcfe77f5c1832fb75512479))
|
||||
* **Catalog:** added missing post menu button to rules and description ([a7a845e](https://github.com/plebbit/plebchan/commit/a7a845eada43174bdf6df8846d7eb96011415474))
|
||||
* **EditLabel:** don't show the edit label if comment.original.content is identical to comment.content ([bcbf311](https://github.com/plebbit/plebchan/commit/bcbf311b952cc5b153b75a92f9840595ddd52c3e))
|
||||
* **home:** ensure removed threads don't appear in popular threads box ([fee9e6f](https://github.com/plebbit/plebchan/commit/fee9e6fa08ccc944f386a31a403a95637e8f119c))
|
||||
* **home:** fix displacement of threads while rendered in popular threads box ([06decd9](https://github.com/plebbit/plebchan/commit/06decd99e2f96c2c6e07e8fb8d5fafe5a8862707))
|
||||
* **home:** fix rerender with useEffect dep ([c63ade8](https://github.com/plebbit/plebchan/commit/c63ade854b3eec55b4e267a9da8af8f19d15d314))
|
||||
* **home:** remove fallback image warning ([eec7e5c](https://github.com/plebbit/plebchan/commit/eec7e5cd640ba554f8672ab3718f54b0444abba2))
|
||||
* **Home:** remove preload of boards because it's resource-intensive and doesn't have concurrency maximum ([8758996](https://github.com/plebbit/plebchan/commit/8758996c970244783f02b9342564209bec146150))
|
||||
* **hooks:** more accurate state strings ([2230049](https://github.com/plebbit/plebchan/commit/22300490ffb602201f5cccfccee0b0ea3aae9ba1))
|
||||
* **mobile reply:** remove unnecessary width calculation for reply images ([8e4ca88](https://github.com/plebbit/plebchan/commit/8e4ca881ad1ed90b8d9cf3084c01df7a570c6986))
|
||||
* **offline indicator:** check for online status every 30 minutes instead of 20 ([4eba8e7](https://github.com/plebbit/plebchan/commit/4eba8e7530516a798396696418e013251740481d))
|
||||
* **post form:** make subject field optional, not mandatory ([548d491](https://github.com/plebbit/plebchan/commit/548d4914bf1924e4312f5baa2773c98d027d011a))
|
||||
* **Post Form:** use defaultValue for Name when displayName is defined ([c779c34](https://github.com/plebbit/plebchan/commit/c779c34243dea4c08c527929f4796b7bfe5f199c))
|
||||
* **post:** fix misplaced pin and lock icons ([3a02990](https://github.com/plebbit/plebchan/commit/3a029906744c6f42d501567389ffa34ccf650b12))
|
||||
* **post:** fix misplaced user address ([1a4f7ac](https://github.com/plebbit/plebchan/commit/1a4f7ac281d39dc99f0b4759e76611460d7442d8))
|
||||
* **PostOnHover:** add embed thumbnail ([946606a](https://github.com/plebbit/plebchan/commit/946606ac1f4dbd73aad40a1af19a4b226545dd0b))
|
||||
* **Post:** remove markdown links showing them as text ([a5a01a8](https://github.com/plebbit/plebchan/commit/a5a01a8732f9ddcfc46932db23c812c039e9b3fb))
|
||||
* **Post:** remove unnecessary key property causing warning ([2d8ecaa](https://github.com/plebbit/plebchan/commit/2d8ecaa9a07a0cb0dda7cc30639228d2ee1d570c))
|
||||
* **scroll:** resolve race condition in onClick scroll-to-top behavior ([d5715e2](https://github.com/plebbit/plebchan/commit/d5715e29eb796b11d5fb98827cc8f44097d63afe))
|
||||
* **SettingsModal:** add page reload for automatic anon mode change for ENS name ([7f7c9ff](https://github.com/plebbit/plebchan/commit/7f7c9ffaf913d21ef78b8de44e6b1b662d2fc919))
|
||||
* **Thread:** fix undefined ([fdebe14](https://github.com/plebbit/plebchan/commit/fdebe14cdb8134ece9d5161ce5c572862c4aec89))
|
||||
* **Thread:** remove useless wrapper for webpage comment.link with no thumbnail ([e4b1fc6](https://github.com/plebbit/plebchan/commit/e4b1fc6d35c34c5c4108f20a0bd211ddb4031497))
|
||||
* **usestatestring:** don't show updating state if comment/subplebbit is succeeded ([7169366](https://github.com/plebbit/plebchan/commit/7169366d11d433f6e30c4c213a8f9bcf0a02685c))
|
||||
* **views:** add CSS effect for useAuthorAddress jank ([40a2ff9](https://github.com/plebbit/plebchan/commit/40a2ff94ea1fa80deb9f2384fc05f5e90d14590c))
|
||||
* **views:** add missing parser for quote links in thread op content ([be8bed7](https://github.com/plebbit/plebchan/commit/be8bed74ef04162fe5824a1c6e9be2e39f356098))
|
||||
* **views:** fix scrolling jank removing margin between desktop reply cards ([288ae4d](https://github.com/plebbit/plebchan/commit/288ae4d066d310f1e5df8d433124015b1c63c63e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **AdminListModal:** inform the user when a board doesn't have moderators yet ([8a81177](https://github.com/plebbit/plebchan/commit/8a81177dd23a750e70669b8176f00d2969e47069))
|
||||
* **home:** boards box shows list of boards being moderated by the user ([fabec54](https://github.com/plebbit/plebchan/commit/fabec543bf0be636a63cdcbe693583cd5da215a2))
|
||||
* **home:** improve popular threads box with much more accurate conditions ([053ec57](https://github.com/plebbit/plebchan/commit/053ec57bc45413d00b196f8b42d59d90178d21bb))
|
||||
* **home:** recent threads box only shows posts with media ([de2ac49](https://github.com/plebbit/plebchan/commit/de2ac49c1f7ee4d7d2115a8bd438f0f04a9b5ff3))
|
||||
* **home:** redesigned home to be more similar to 4chan, with boards box listing all boards and thread box showing recent threads ([685cbb3](https://github.com/plebbit/plebchan/commit/685cbb3c170dc343794c316e42693e937b1bbdfd))
|
||||
* **SettingsModal:** add button to create an account and automatically switching to it, update setting description and modal width ([57c3f71](https://github.com/plebbit/plebchan/commit/57c3f71a22b151ea2aa04d4427249d2695d487be))
|
||||
* **SettingsModal:** automatically disable anon mode and tell the user, detecting ENS name when importing account, saving account or saving ENS ([c59bbb6](https://github.com/plebbit/plebchan/commit/c59bbb6f50e8b89e516255b947e23b8bfa6022f9))
|
||||
* **SettingsModal:** force keep the same account id when saving to allow faster account import ([eab5469](https://github.com/plebbit/plebchan/commit/eab546939d8be5abe599a25e5cad6538bf4d1b0f))
|
||||
* **Share button:** add success toast for copying share link to clipboard ([f0c0e64](https://github.com/plebbit/plebchan/commit/f0c0e64d750c98e6d2cad80bc721ddff228aa523))
|
||||
* **views:** show board admin role next to usernames, if any, with capcode colors and admin modal function ([e9cfdac](https://github.com/plebbit/plebchan/commit/e9cfdac18f7111a0fe42900c6f56133ce1819d14))
|
||||
|
||||
|
||||
|
||||
## [0.1.12](https://github.com/plebbit/plebchan/compare/v0.1.11...v0.1.12) (2023-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* show new version info toast only once ([3f33dcb](https://github.com/plebbit/plebchan/commit/3f33dcb37a900ec5d0710842d7f0c9b0e4f0cf2e))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "add support for non-direct imgur links" ([be89323](https://github.com/plebbit/plebchan/commit/be8932343184a96d719cf5fd4a5032ce5162d12a))
|
||||
* Revert "Update SettingsModal.jsx" ([5c72bc6](https://github.com/plebbit/plebchan/commit/5c72bc69e1c5e125c8c9348b3e2c5a0c877f5bdb))
|
||||
* Revert "fix conditional useMemo" ([572ce08](https://github.com/plebbit/plebchan/commit/572ce0869adbc51fa5d5855152350fe041bad96f))
|
||||
|
||||
|
||||
|
||||
## [0.1.10](https://github.com/plebbit/plebchan/compare/v0.1.9...v0.1.10) (2023-08-10)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "add refresh button" ([f7ae7e7](https://github.com/plebbit/plebchan/commit/f7ae7e78dfb36391f39a28f444b86f90ddc1996e))
|
||||
|
||||
|
||||
|
||||
## [0.1.8](https://github.com/plebbit/plebchan/compare/v0.1.7...v0.1.8) (2023-06-09)
|
||||
|
||||
|
||||
|
||||
## [0.1.7](https://github.com/plebbit/plebchan/compare/v0.1.6...v0.1.7) (2023-06-08)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "refactor toasts" ([37d4966](https://github.com/plebbit/plebchan/commit/37d49668e4f4ae80bc9129a1061a00932bb63abd))
|
||||
|
||||
|
||||
|
||||
## [0.1.5](https://github.com/plebbit/plebchan/compare/v0.1.4...v0.1.5) (2023-05-12)
|
||||
|
||||
|
||||
|
||||
## [0.1.4](https://github.com/plebbit/plebchan/compare/v0.1.3...v0.1.4) (2023-05-11)
|
||||
|
||||
|
||||
|
||||
## [0.1.3](https://github.com/plebbit/plebchan/compare/v0.1.2...v0.1.3) (2023-05-06)
|
||||
|
||||
|
||||
|
||||
## [0.1.2](https://github.com/plebbit/plebchan/compare/v0.1.1...v0.1.2) (2023-04-29)
|
||||
|
||||
|
||||
|
||||
## [0.1.1](https://github.com/plebbit/plebchan/compare/v0.1.0...v0.1.1) (2023-04-27)
|
||||
|
||||
|
||||
|
||||
# [0.1.0](https://github.com/plebbit/plebchan/compare/0acd472a9fce50a66964d11750ee9e1275a49617...v0.1.0) (2023-04-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* added png lowercase ([908dcd7](https://github.com/plebbit/plebchan/commit/908dcd77faa313e05d74c1e6865c29ae53ebceac))
|
||||
* delete uppercase png ([0acd472](https://github.com/plebbit/plebchan/commit/0acd472a9fce50a66964d11750ee9e1275a49617))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "fix subplebbitAddress in ReplyModal" ([24b2177](https://github.com/plebbit/plebchan/commit/24b2177e8743785591a0947cbdb85bd87a9cdc56))
|
||||
* Revert "removed markdown" ([33eec76](https://github.com/plebbit/plebchan/commit/33eec7644a564bc8825f48927b3a054858991744))
|
||||
* Revert "fix touch bug" ([777935e](https://github.com/plebbit/plebchan/commit/777935ecbe1e3d781bc4bbadf8f824323acc8c8d))
|
||||
* Revert "test InfiniteScroll" ([212a0c1](https://github.com/plebbit/plebchan/commit/212a0c10e8a563b75eb35f8d20ba8b93d0adec45))
|
||||
* Revert "better lint, added InfiniteScroll, debugUtils" ([af0a4c6](https://github.com/plebbit/plebchan/commit/af0a4c67de33c544f997ec7bd64d94e5a5a41df3))
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "plebchan",
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.13",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "7.21.3",
|
||||
|
||||
+16
-37
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Route, Routes, useLocation } from 'react-router-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import 'react-tooltip/dist/react-tooltip.css';
|
||||
@@ -21,6 +21,7 @@ import Thread from './components/views/Thread';
|
||||
import CaptchaModal from './components/modals/CaptchaModal';
|
||||
import { importAll } from './components/ImageBanner';
|
||||
import preloadImages from './utils/preloadImages';
|
||||
import showNewVersionToast from './utils/showNewVersionToast';
|
||||
import useError from './hooks/useError';
|
||||
import useInfo from './hooks/useInfo';
|
||||
import useSuccess from './hooks/useSuccess';
|
||||
@@ -44,12 +45,16 @@ export default function App() {
|
||||
const location = useLocation();
|
||||
const isElectron = window.electron && window.electron.isElectron;
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
const [, setNewErrorMessage] = useError();
|
||||
const [, setNewSuccessMessage] = useSuccess();
|
||||
const [, setNewInfoMessage] = useInfo();
|
||||
|
||||
const [infoMessageShown, setInfoMessageShown] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const successToast = localStorage.getItem('successToast');
|
||||
const errorToast = localStorage.getItem('errorToast');
|
||||
@@ -64,41 +69,15 @@ export default function App() {
|
||||
}
|
||||
}, [setNewErrorMessage, setNewSuccessMessage]);
|
||||
|
||||
// check for new version
|
||||
// TODO: delete this code and toast when v1.0.0 is released
|
||||
// TODO: delete this code and toast when v1.0.0 is released (minor updates expected)
|
||||
let hasRun = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchVersionInfo = async () => {
|
||||
try {
|
||||
const packageRes = await fetch('https://raw.githubusercontent.com/plebbit/plebchan/master/package.json', { cache: 'no-cache' });
|
||||
const packageData = await packageRes.json();
|
||||
|
||||
if (packageJson.version !== packageData.version && !infoMessageShown) {
|
||||
const newVersionInfo = isElectron
|
||||
? `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Download the latest version here: https://github.com/plebbit/plebchan/releases/latest`
|
||||
: `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
setInfoMessageShown(true);
|
||||
}
|
||||
|
||||
if (commitRef.length > 0) {
|
||||
const commitRes = await fetch('https://api.github.com/repos/plebbit/plebchan/commits?per_page=1&sha=development', { cache: 'no-cache' });
|
||||
const commitData = await commitRes.json();
|
||||
|
||||
const latestCommitHash = commitData[0].sha;
|
||||
|
||||
if (latestCommitHash.trim() !== commitRef.trim() && !infoMessageShown) {
|
||||
const newVersionInfo = `New dev version available, commit ${latestCommitHash.slice(0, 7)}. You are using commit ${commitRef.slice(0, 7)}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
setInfoMessageShown(true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch latest version info:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchVersionInfo();
|
||||
}, [setNewInfoMessage, isElectron, infoMessageShown]);
|
||||
if (!hasRun.current) {
|
||||
showNewVersionToast(setNewInfoMessage, isElectron, packageJson, commitRef);
|
||||
hasRun.current = true;
|
||||
}
|
||||
}, [setNewInfoMessage, isElectron]);
|
||||
|
||||
// preload banners
|
||||
useEffect(() => {
|
||||
|
||||
@@ -72,7 +72,7 @@ const TwitterEmbed = ({ parsedUrl }) => {
|
||||
allow='accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share'
|
||||
title={parsedUrl.href}
|
||||
srcdoc={`
|
||||
<blockquote class="twitter-tweet" data-theme="dark">
|
||||
<blockquote className="twitter-tweet" data-theme="dark">
|
||||
<a href="${parsedUrl.href.replace('x.com', 'twitter.com')}"></a>
|
||||
</blockquote>
|
||||
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
@@ -101,7 +101,7 @@ const RedditEmbed = ({ parsedUrl }) => {
|
||||
margin: 0!important;
|
||||
}
|
||||
</style>
|
||||
<blockquote class="reddit-embed-bq" style="height:240px" data-embed-theme="dark">
|
||||
<blockquote className="reddit-embed-bq" style="height:240px" data-embed-theme="dark">
|
||||
<a href="${parsedUrl.href}"></a>
|
||||
</blockquote>
|
||||
<script async src="https://embed.reddit.com/widgets.js" charset="UTF-8"></script>
|
||||
@@ -152,7 +152,7 @@ const TiktokEmbed = ({ parsedUrl }) => {
|
||||
allow='accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share'
|
||||
title={parsedUrl.href}
|
||||
srcdoc={`
|
||||
<blockquote class="tiktok-embed" data-video-id="${videoId}">
|
||||
<blockquote className="tiktok-embed" data-video-id="${videoId}">
|
||||
<a></a>
|
||||
</blockquote>
|
||||
<script async src="https://www.tiktok.com/embed.js"></script>
|
||||
@@ -177,7 +177,7 @@ const InstagramEmbed = ({ parsedUrl }) => {
|
||||
allow='accelerometer; encrypted-media; gyroscope; picture-in-picture; web-share'
|
||||
title={parsedUrl.href}
|
||||
srcdoc={`
|
||||
<blockquote class="instagram-media">
|
||||
<blockquote className="instagram-media">
|
||||
<a href="https://www.instagram.com/p/${id}/"></a>
|
||||
</blockquote>
|
||||
<script async src="//www.instagram.com/embed.js"></script>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
|
||||
const OfflineIndicator = ({ address, className, tooltipPlace }) => {
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress: address });
|
||||
const isOnline = subplebbit.updatedAt > Date.now() / 1000 - 60 * 20;
|
||||
const isOnline = subplebbit.updatedAt > Date.now() / 1000 - 60 * 30;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -2147,6 +2147,12 @@ export const BoardForm = styled.div`
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.thread-icons-mobile {
|
||||
margin-top: -1px;
|
||||
margin-right: 2px;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding-top: 5px;
|
||||
display: block;
|
||||
|
||||
@@ -1336,6 +1336,12 @@ export const BoardForm = styled.div`
|
||||
object-fit: scale-down;
|
||||
}
|
||||
|
||||
.thread-icons-mobile {
|
||||
margin-top: -1px;
|
||||
margin-right: 2px;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding-top: 5px;
|
||||
display: block;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Fragment, useCallback, useEffect, useMemo, useState, useRef } fr
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
@@ -541,7 +541,12 @@ const All = () => {
|
||||
navigate(`/p/${selected}`);
|
||||
};
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
lastVirtuosoStates[`all`] = null;
|
||||
}
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
|
||||
@@ -552,7 +557,7 @@ const All = () => {
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, []);
|
||||
}, [location.state?.scrollToTop]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates['all'];
|
||||
|
||||
@@ -578,14 +583,9 @@ const All = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -652,10 +652,9 @@ const All = () => {
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to='/'
|
||||
to={{ pathname: '/', state: { scrollToTop: true } }}
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -3486,14 +3485,9 @@ const All = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
@@ -777,7 +777,12 @@ const AllCatalog = () => {
|
||||
setSelectedFeed(feed.filter((feed) => feed.title === title));
|
||||
};
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
lastVirtuosoStates[`allCatalog`] = null;
|
||||
}
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
|
||||
@@ -788,7 +793,7 @@ const AllCatalog = () => {
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [selectedAddress]);
|
||||
}, [selectedAddress, location.state?.scrollToTop]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates['allCatalog'];
|
||||
|
||||
@@ -813,14 +818,9 @@ const AllCatalog = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -894,10 +894,9 @@ const AllCatalog = () => {
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to='/'
|
||||
to={{ pathname: '/', state: { scrollToTop: true } }}
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -933,11 +932,11 @@ const AllCatalog = () => {
|
||||
</select>
|
||||
</span>
|
||||
<div className='return-button' id='return-button-desktop'>
|
||||
[<Link to={`/p/all`}>Return</Link>]
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>Return</Link>]
|
||||
</div>
|
||||
<div id='return-button-mobile'>
|
||||
<span className='btn-wrap-catalog btn-wrap'>
|
||||
<Link to={`/p/all`}>Return</Link>
|
||||
<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>Return</Link>
|
||||
</span>
|
||||
</div>
|
||||
{subplebbits.state === 'succeeded' ? null : (
|
||||
@@ -1008,14 +1007,9 @@ const AllCatalog = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
@@ -698,7 +698,12 @@ const Board = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
lastVirtuosoStates[selectedAddress] = null;
|
||||
}
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
|
||||
@@ -709,7 +714,7 @@ const Board = () => {
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [selectedAddress]);
|
||||
}, [selectedAddress, location.state?.scrollToTop]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates[selectedAddress];
|
||||
|
||||
@@ -736,14 +741,9 @@ const Board = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -813,10 +813,9 @@ const Board = () => {
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to='/'
|
||||
to={{ pathname: '/', state: { scrollToTop: true } }}
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -919,16 +918,8 @@ const Board = () => {
|
||||
</select>
|
||||
</span>
|
||||
<div id='catalog-button-desktop'>
|
||||
[
|
||||
<Link
|
||||
to={`/p/${selectedAddress}/catalog`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Catalog
|
||||
</Link>
|
||||
]{subplebbit.roles && subplebbit?.roles?.[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
|
||||
{subplebbit.roles && subplebbit?.roles?.[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
|
||||
</div>
|
||||
{subplebbit?.state === 'succeeded' ? (
|
||||
<>
|
||||
@@ -952,14 +943,7 @@ const Board = () => {
|
||||
)}
|
||||
<div id='catalog-button-mobile'>
|
||||
<span className='btn-wrap'>
|
||||
<Link
|
||||
to={`/p/${selectedAddress}/catalog`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Catalog
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
|
||||
</span>
|
||||
</div>
|
||||
</TopBar>
|
||||
@@ -1153,10 +1137,20 @@ const Board = () => {
|
||||
## Board Mods
|
||||
</span>
|
||||
|
||||
<span className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
<img src='assets/sticky.gif' alt='Sticky' title='Sticky' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<span className='thread-icons-mobile'>
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
|
||||
<img src='assets/closed.gif' alt='Closed' title='Closed' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
</span>
|
||||
<br />
|
||||
<span className='subject-mobile' style={{ marginBottom: '-15px' }}>
|
||||
@@ -1378,10 +1372,20 @@ const Board = () => {
|
||||
## Board Mods
|
||||
</span>
|
||||
|
||||
<span className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
<img src='assets/sticky.gif' alt='Sticky' title='Sticky' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<span className='thread-icons-mobile'>
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
|
||||
<img src='assets/closed.gif' alt='Closed' title='Closed' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
</span>
|
||||
<br />
|
||||
<span className='subject-mobile' style={{ marginBottom: '-15px' }}>
|
||||
@@ -1679,10 +1683,20 @@ const Board = () => {
|
||||
## Board Mods
|
||||
</span>
|
||||
|
||||
<span className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
<img src='assets/sticky.gif' alt='Sticky' title='Sticky' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<span className='thread-icons-mobile'>
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
|
||||
<img src='assets/closed.gif' alt='Closed' title='Closed' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
</span>
|
||||
<br />
|
||||
<span className='subject-mobile' style={{ marginBottom: '-15px' }}>
|
||||
@@ -3317,24 +3331,24 @@ const Board = () => {
|
||||
</VerifiedAuthor>
|
||||
</span>
|
||||
)
|
||||
</span>
|
||||
<span key={`ti-mob-${index}`} className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
{thread.pinned ? (
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
) : null}
|
||||
{thread.locked ? (
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
) : null}
|
||||
<span key={`ti-mob-${index}`} className='thread-icons-mobile'>
|
||||
{thread.pinned ? (
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
) : null}
|
||||
{thread.locked ? (
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
) : null}
|
||||
</span>
|
||||
</span>
|
||||
<br key={`mob-br1-${index}`} />
|
||||
{thread.title ? (
|
||||
@@ -3729,7 +3743,6 @@ const Board = () => {
|
||||
to={`/p/${selectedAddress}/c/${thread.cid}`}
|
||||
onClick={() => {
|
||||
setSelectedThread(thread.cid);
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
className='button-mobile'
|
||||
>
|
||||
@@ -4538,14 +4551,9 @@ const Board = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
]
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useLayoutEffect, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
@@ -1462,7 +1462,12 @@ const Catalog = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
lastVirtuosoStates[`${selectedAddress}-catalog`] = null;
|
||||
}
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
|
||||
@@ -1473,7 +1478,7 @@ const Catalog = () => {
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [selectedAddress]);
|
||||
}, [selectedAddress, location.state?.scrollToTop]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates[`${selectedAddress}-catalog`];
|
||||
|
||||
@@ -1498,14 +1503,9 @@ const Catalog = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -1580,10 +1580,9 @@ const Catalog = () => {
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to='/'
|
||||
to={{ pathname: '/', state: { scrollToTop: true } }}
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -1688,16 +1687,8 @@ const Catalog = () => {
|
||||
</select>
|
||||
</span>
|
||||
<div className='return-button' id='return-button-desktop'>
|
||||
[
|
||||
<Link
|
||||
to={`/p/${selectedAddress}`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Return
|
||||
</Link>
|
||||
]{subplebbit.roles && subplebbit?.roles[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
|
||||
{subplebbit.roles && subplebbit?.roles[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
|
||||
</div>
|
||||
{subplebbit.state === 'succeeded' ? (
|
||||
<>
|
||||
@@ -1721,14 +1712,7 @@ const Catalog = () => {
|
||||
)}
|
||||
<div id='return-button-mobile'>
|
||||
<span className='btn-wrap-catalog btn-wrap'>
|
||||
<Link
|
||||
to={`/p/${selectedAddress}`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Return
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
@@ -1793,14 +1777,9 @@ const Catalog = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
]
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
@@ -160,14 +160,9 @@ const Description = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -245,7 +240,6 @@ const Description = () => {
|
||||
to='/'
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -275,25 +269,13 @@ const Description = () => {
|
||||
<PostForm selectedStyle={selectedStyle}>
|
||||
<ReplyFormLink id='post-form-link' selectedStyle={selectedStyle} style={{ marginBottom: '10px' }}>
|
||||
<div id='return-button-mobile'>
|
||||
<span
|
||||
className='btn-wrap'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
<Link to={`/p/${selectedAddress}`}>Return</Link>
|
||||
<span className='btn-wrap'>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div id='catalog-button-mobile'>
|
||||
<span className='btn-wrap'>
|
||||
<Link
|
||||
to={`/p/${selectedAddress}/catalog`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Catalog
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div id='bottom-button-mobile'>
|
||||
@@ -323,10 +305,10 @@ const Description = () => {
|
||||
</select>
|
||||
</span>
|
||||
<span className='return-button' id='return-button-desktop'>
|
||||
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
|
||||
</span>
|
||||
<span className='return-button catalog-button' id='catalog-button-desktop'>
|
||||
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
|
||||
</span>
|
||||
<span className='return-button catalog-button' id='bottom-button-desktop'>
|
||||
[
|
||||
@@ -605,10 +587,20 @@ const Description = () => {
|
||||
## Board Mods
|
||||
</span>
|
||||
|
||||
<span className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
<img src='assets/sticky.gif' alt='Sticky' title='Sticky' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<span className='thread-icons-mobile'>
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
|
||||
<img src='assets/closed.gif' alt='Closed' title='Closed' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
</span>
|
||||
<br />
|
||||
<span className='subject-mobile' style={{ marginBottom: '-15px' }}>
|
||||
@@ -684,14 +676,9 @@ const Description = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
]
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
+107
-104
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { useAccount, useComment, useSubplebbit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import { useAccount, useAccountSubplebbits, useComment, useSubplebbit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Container, Header, Logo, Page, Search, About, AboutTitle, AboutContent, BoardsBox, BoardsContent, Footer } from '../styled/views/Home.styled';
|
||||
import BoardAvatar from '../BoardAvatar';
|
||||
@@ -13,73 +13,108 @@ import { Tooltip } from 'react-tooltip';
|
||||
const { version } = packageJson;
|
||||
const commitRef = process?.env?.REACT_APP_COMMIT_REF ? ` ${process.env.REACT_APP_COMMIT_REF.slice(0, 7)}` : '';
|
||||
|
||||
const RecentThread = ({ commentCid }) => {
|
||||
const PopularThreads = ({ commentCid }) => {
|
||||
const comment = useComment({ commentCid });
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress: comment?.subplebbitAddress });
|
||||
const { setSelectedAddress, setSelectedTitle } = useGeneralStore((state) => state);
|
||||
const commentMediaInfo = getCommentMediaInfo(comment);
|
||||
const isMediaShowed =
|
||||
comment.link &&
|
||||
commentMediaInfo &&
|
||||
(commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' && commentMediaInfo.thumbnail) ||
|
||||
(commentMediaInfo.type === 'iframe' && commentMediaInfo.thumbnail))
|
||||
? true
|
||||
: false;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isMediaShowed && comment.replyCount > 0 && !comment.removed ? (
|
||||
<div className='board'>
|
||||
<div className='board-title' key='board-title'>
|
||||
<span>{subplebbit.title || subplebbit.address}</span>
|
||||
</div>
|
||||
<div className='board-avatar-container' key='board-avatar-container'>
|
||||
<Link
|
||||
to={`/p/${comment?.subplebbitAddress}/c/${comment?.cid}`}
|
||||
key='link'
|
||||
onClick={() => {
|
||||
setSelectedTitle(subplebbit?.title);
|
||||
setSelectedAddress(comment?.subplebbitAddress);
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
{commentMediaInfo?.type === 'webpage' && comment.thumbnailUrl ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.thumbnail} alt='post' />
|
||||
) : commentMediaInfo?.type === 'image' ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.url} alt='post' />
|
||||
) : commentMediaInfo?.type === 'video' ? (
|
||||
<video className='board-avatar' src={commentMediaInfo?.url} alt='post' />
|
||||
) : commentMediaInfo?.type === 'iframe' ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.thumbnail} alt='post' />
|
||||
) : (
|
||||
<BoardAvatar address={comment.subplebbitAddress} />
|
||||
)}
|
||||
</Link>
|
||||
<OfflineIndicator address={comment?.subplebbitAddress} className='offline-indicator' tooltipPlace='top' key='oi2' />
|
||||
</div>
|
||||
<div className='board-text' key='bt'>
|
||||
{comment?.title ? <b>{comment?.title}</b> : null}
|
||||
{comment?.content ? (comment.content.length > 99 ? `: ${comment.content.substring(0, 99)}...` : `: ${comment.content}`) : null}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
<div className='board'>
|
||||
<div className='board-title' key='board-title'>
|
||||
<span>{subplebbit.title || subplebbit.address}</span>
|
||||
</div>
|
||||
<div className='board-avatar-container' key='board-avatar-container'>
|
||||
<Link
|
||||
to={`/p/${comment?.subplebbitAddress}/c/${comment?.cid}`}
|
||||
key='link'
|
||||
onClick={() => {
|
||||
setSelectedTitle(subplebbit?.title);
|
||||
setSelectedAddress(comment?.subplebbitAddress);
|
||||
}}
|
||||
>
|
||||
{commentMediaInfo?.type === 'webpage' && commentMediaInfo?.thumbnail ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.thumbnail} alt='post' />
|
||||
) : commentMediaInfo?.type === 'image' ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.url} alt='post' />
|
||||
) : commentMediaInfo?.type === 'video' ? (
|
||||
<video className='board-avatar' src={commentMediaInfo?.url} alt='post' />
|
||||
) : commentMediaInfo?.type === 'iframe' && commentMediaInfo?.thumbnail ? (
|
||||
<img className='board-avatar' src={commentMediaInfo?.thumbnail} alt='post' />
|
||||
) : (
|
||||
<BoardAvatar address={comment.subplebbitAddress} />
|
||||
)}
|
||||
</Link>
|
||||
<OfflineIndicator address={comment?.subplebbitAddress} className='offline-indicator' tooltipPlace='top' key='oi2' />
|
||||
</div>
|
||||
<div className='board-text' key='bt'>
|
||||
{comment?.title ? <b>{comment?.title}</b> : null}
|
||||
{comment?.content ? (comment.content.length > 99 ? `: ${comment.content.substring(0, 99)}...` : `: ${comment.content}`) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Home = () => {
|
||||
const { bodyStyle, setBodyStyle, defaultSubplebbits, defaultNsfwSubplebbits, setSelectedAddress, selectedStyle, setSelectedStyle } = useGeneralStore((state) => state);
|
||||
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const accountSubplebbitsAddresses = Object.values(accountSubplebbits).map((subplebbit) => subplebbit.address);
|
||||
const sfwAddresses = defaultSubplebbits.map((subplebbit) => subplebbit.address);
|
||||
const sfwSubs = useSubplebbits({ subplebbitAddresses: sfwAddresses });
|
||||
const sfwList = sfwSubs.subplebbits.map((subplebbit) => subplebbit?.address);
|
||||
const sfwListCids = sfwSubs.subplebbits.map((s) => s?.lastPostCid);
|
||||
const [sfwListCids, setSfwListCids] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
let subplebbitToCid = {};
|
||||
|
||||
sfwSubs.subplebbits.forEach((s) => {
|
||||
let maxTimestamp = -Infinity;
|
||||
let mostRecentCid = null;
|
||||
|
||||
if (s && s.posts && s.posts.pages && s.posts.pages.hot && s.posts.pages.hot.comments) {
|
||||
for (const comment of Object.values(s.posts.pages.hot.comments)) {
|
||||
const commentMediaInfo = getCommentMediaInfo(comment);
|
||||
const isMediaShowed =
|
||||
comment.link &&
|
||||
commentMediaInfo &&
|
||||
(commentMediaInfo.type === 'image' ||
|
||||
commentMediaInfo.type === 'video' ||
|
||||
(commentMediaInfo.type === 'webpage' && commentMediaInfo.thumbnail) ||
|
||||
(commentMediaInfo.type === 'iframe' && commentMediaInfo.thumbnail));
|
||||
|
||||
if (
|
||||
isMediaShowed &&
|
||||
comment.replyCount > 2 &&
|
||||
!comment.removed &&
|
||||
!comment.locked &&
|
||||
!comment.pinned &&
|
||||
comment.timestamp > Date.now() / 1000 - 60 * 60 * 24 * 30 &&
|
||||
comment.timestamp > maxTimestamp
|
||||
) {
|
||||
maxTimestamp = comment.timestamp;
|
||||
mostRecentCid = comment.cid;
|
||||
}
|
||||
}
|
||||
|
||||
if (mostRecentCid) {
|
||||
subplebbitToCid[s.address] = { cid: mostRecentCid, timestamp: maxTimestamp };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const newSfwListCids = Object.values(subplebbitToCid)
|
||||
.map((item) => item.cid)
|
||||
.slice(0, 8);
|
||||
|
||||
setSfwListCids((prevOrderedCids) => {
|
||||
const uniqueCids = Array.from(new Set([...prevOrderedCids, ...newSfwListCids]));
|
||||
return uniqueCids.slice(0, 8);
|
||||
});
|
||||
}, [sfwSubs.subplebbits, sfwListCids]);
|
||||
|
||||
const account = useAccount();
|
||||
const navigate = useNavigate();
|
||||
const isElectron = window.electron && window.electron.isElectron;
|
||||
|
||||
const inputRef = useRef(null);
|
||||
const prevStyle = useRef(selectedStyle);
|
||||
@@ -174,8 +209,8 @@ const Home = () => {
|
||||
<div className='boxbar'>
|
||||
<h2>Boards</h2>
|
||||
</div>
|
||||
<div class='boxcontent'>
|
||||
<div class='column'>
|
||||
<div className='boxcontent'>
|
||||
<div className='column'>
|
||||
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>
|
||||
<a
|
||||
href='https://github.com/plebbit/temporary-default-subplebbits'
|
||||
@@ -187,13 +222,7 @@ const Home = () => {
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<Link
|
||||
to='/p/all'
|
||||
id='button'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
<Link to={{ pathname: '/p/all', state: { scrollToTop: true } }} id='button'>
|
||||
[view all]
|
||||
</Link>
|
||||
<ul>
|
||||
@@ -203,10 +232,10 @@ const Home = () => {
|
||||
<Link
|
||||
key={`default-link-${index}`}
|
||||
className='boardlink'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
to={{
|
||||
pathname: `/p/${address}`,
|
||||
state: { scrollToTop: true },
|
||||
}}
|
||||
to={`/p/${address}`}
|
||||
>
|
||||
{address}
|
||||
</Link>
|
||||
@@ -221,7 +250,7 @@ const Home = () => {
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div class='column'>
|
||||
<div className='column'>
|
||||
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>
|
||||
<a
|
||||
href='https://github.com/plebbit/temporary-default-subplebbits'
|
||||
@@ -237,14 +266,7 @@ const Home = () => {
|
||||
{defaultNsfwSubplebbits.slice(0, showAllSFWBoards ? undefined : 18).map((subplebbit, index) => (
|
||||
<li key={`default-${index}`}>
|
||||
<OfflineIndicator address={subplebbit.address} className='disconnected' isText={true} />
|
||||
<Link
|
||||
key={`default-link-${index}`}
|
||||
className='boardlink'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
to={`/p/${subplebbit.address}`}
|
||||
>
|
||||
<Link key={`default-link-${index}`} className='boardlink' to={{ pathname: `/p/${subplebbit.address}`, state: { scrollToTop: true } }}>
|
||||
{subplebbit.address}
|
||||
</Link>
|
||||
|
||||
@@ -258,16 +280,10 @@ const Home = () => {
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div class='column'>
|
||||
<div className='column'>
|
||||
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>Subscriptions</h3>
|
||||
|
||||
<Link
|
||||
to='/p/subscriptions'
|
||||
id='button'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
<Link to={{ pathname: '/p/subscriptions', state: { scrollToTop: true } }} id='button'>
|
||||
[view all]
|
||||
</Link>
|
||||
<br />
|
||||
@@ -276,14 +292,7 @@ const Home = () => {
|
||||
{account?.subscriptions?.slice(0, showAllSubscriptions ? undefined : 18).map((subscription, index) => (
|
||||
<li key={`sub-${index}`}>
|
||||
<OfflineIndicator address={subscription} className='disconnected' isText={true} />
|
||||
<Link
|
||||
key={`sub-link-${index}`}
|
||||
className='boardlink'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
to={`/p/${subscription}`}
|
||||
>
|
||||
<Link key={`sub-link-${index}`} className='boardlink' to={{ pathname: `/p/${subscription}`, state: { scrollToTop: true } }}>
|
||||
{subscription}
|
||||
</Link>
|
||||
|
||||
@@ -297,25 +306,19 @@ const Home = () => {
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div class='column'>
|
||||
<div className='column'>
|
||||
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>Moderating</h3>
|
||||
<ul>
|
||||
{!isElectron ? (
|
||||
<li style={{ color: 'black' }}>
|
||||
Visible on{' '}
|
||||
<a
|
||||
style={{ color: 'blue', textDecoration: 'underline' }}
|
||||
href='https://github.com/plebbit/plebchan/releases/latest'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
>
|
||||
full node (desktop)
|
||||
</a>
|
||||
.
|
||||
{accountSubplebbitsAddresses?.length === 0 && <li style={{ color: 'black' }}>Not moderating any board.</li>}
|
||||
{accountSubplebbitsAddresses?.slice(0, showAllSubscriptions ? undefined : 18).map((subplebbit, index) => (
|
||||
<li key={`sub-${index}`}>
|
||||
<OfflineIndicator address={subplebbit} className='disconnected' isText={true} />
|
||||
<Link key={`sub-link-${index}`} className='boardlink' to={{ pathname: `/p/${subplebbit}`, state: { scrollToTop: true } }}>
|
||||
{subplebbit}
|
||||
</Link>
|
||||
|
||||
</li>
|
||||
) : (
|
||||
<div>WIP</div>
|
||||
)}
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -326,7 +329,7 @@ const Home = () => {
|
||||
</div>
|
||||
<BoardsContent>
|
||||
{sfwListCids.map((cid) => (
|
||||
<RecentThread commentCid={cid} />
|
||||
<PopularThreads commentCid={cid} />
|
||||
))}
|
||||
</BoardsContent>
|
||||
</BoardsBox>
|
||||
|
||||
@@ -120,14 +120,9 @@ const Pending = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
|
||||
@@ -170,14 +170,9 @@ const Rules = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -255,7 +250,6 @@ const Rules = () => {
|
||||
to='/'
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -285,25 +279,13 @@ const Rules = () => {
|
||||
<PostForm selectedStyle={selectedStyle}>
|
||||
<ReplyFormLink id='post-form-link' selectedStyle={selectedStyle} style={{ marginBottom: '10px' }}>
|
||||
<div id='return-button-mobile'>
|
||||
<span
|
||||
className='btn-wrap'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
<Link to={`/p/${selectedAddress}`}>Return</Link>
|
||||
<span className='btn-wrap'>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div id='catalog-button-mobile'>
|
||||
<span className='btn-wrap'>
|
||||
<Link
|
||||
to={`/p/${selectedAddress}/catalog`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Catalog
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div id='bottom-button-mobile'>
|
||||
@@ -333,10 +315,10 @@ const Rules = () => {
|
||||
</select>
|
||||
</span>
|
||||
<span className='return-button' id='return-button-desktop'>
|
||||
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
|
||||
</span>
|
||||
<span className='return-button catalog-button' id='catalog-button-desktop'>
|
||||
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
|
||||
</span>
|
||||
<span className='return-button catalog-button' id='bottom-button-desktop'>
|
||||
[
|
||||
@@ -539,10 +521,20 @@ const Rules = () => {
|
||||
## Board Mods
|
||||
</span>
|
||||
|
||||
<span className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
<img src='assets/sticky.gif' alt='Sticky' title='Sticky' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<span className='thread-icons-mobile'>
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
|
||||
<img src='assets/closed.gif' alt='Closed' title='Closed' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
</span>
|
||||
<br />
|
||||
<span className='subject-mobile' style={{ marginBottom: '-15px' }}>
|
||||
@@ -620,14 +612,9 @@ const Rules = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
]
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Fragment, useCallback, useEffect, useMemo, useState, useRef } fr
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
@@ -540,7 +540,12 @@ const Subscriptions = () => {
|
||||
navigate(`/p/${selected}`);
|
||||
};
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
lastVirtuosoStates[`subscriptions`] = null;
|
||||
}
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
|
||||
@@ -551,7 +556,7 @@ const Subscriptions = () => {
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, []);
|
||||
}, [location.state?.scrollToTop]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates['subscriptions'];
|
||||
|
||||
@@ -577,14 +582,9 @@ const Subscriptions = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -651,10 +651,9 @@ const Subscriptions = () => {
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to='/'
|
||||
to={{ pathname: '/', state: { scrollToTop: true } }}
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
@@ -710,7 +710,6 @@ const SubscriptionsCatalog = () => {
|
||||
isSettingsOpen,
|
||||
setIsSettingsOpen,
|
||||
originalCommentContent,
|
||||
selectedAddress,
|
||||
setSelectedAddress,
|
||||
selectedStyle,
|
||||
setSelectedTitle,
|
||||
@@ -777,18 +776,23 @@ const SubscriptionsCatalog = () => {
|
||||
navigate(`/p/${selected}`);
|
||||
};
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
if (location.state?.scrollToTop) {
|
||||
lastVirtuosoStates[`subscriptionsCatalog`] = null;
|
||||
}
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot) => {
|
||||
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
|
||||
lastVirtuosoStates[`${selectedAddress}-catalog`] = snapshot;
|
||||
lastVirtuosoStates[`subscriptionsCatalog`] = snapshot;
|
||||
}
|
||||
});
|
||||
};
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [selectedAddress]);
|
||||
}, [location.state?.scrollToTop]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates['subscriptionsCatalog'];
|
||||
|
||||
@@ -813,14 +817,9 @@ const SubscriptionsCatalog = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -894,10 +893,9 @@ const SubscriptionsCatalog = () => {
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to='/'
|
||||
to={{ pathname: '/', state: { scrollToTop: true } }}
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -941,11 +939,11 @@ const SubscriptionsCatalog = () => {
|
||||
</select>
|
||||
</span>
|
||||
<div className='return-button' id='return-button-desktop'>
|
||||
[<Link to={`/p/subscriptions`}>Return</Link>]
|
||||
[<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Return</Link>]
|
||||
</div>
|
||||
<div id='return-button-mobile'>
|
||||
<span className='btn-wrap-catalog btn-wrap'>
|
||||
<Link to={`/p/subscriptions`}>Return</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Return</Link>
|
||||
</span>
|
||||
</div>
|
||||
{subplebbits.state === 'succeeded' ? null : (
|
||||
@@ -1015,10 +1013,7 @@ const SubscriptionsCatalog = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
|
||||
@@ -664,14 +664,9 @@ const Thread = () => {
|
||||
<NavBar selectedStyle={selectedStyle}>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
] [
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
<span className='boardList' key={`span-${subplebbit.address}`}>
|
||||
@@ -749,7 +744,6 @@ const Thread = () => {
|
||||
to='/'
|
||||
onClick={() => {
|
||||
handleStyleChange({ target: { value: 'Yotsuba' } });
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Home
|
||||
@@ -779,25 +773,13 @@ const Thread = () => {
|
||||
<PostForm selectedStyle={selectedStyle} name='post' action='' method='post' enctype='multipart/form-data'>
|
||||
<ReplyFormLink id='post-form-link' showReplyFormLink={showPostFormLink} selectedStyle={selectedStyle}>
|
||||
<div id='return-button-mobile'>
|
||||
<span
|
||||
className='btn-wrap'
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
<span className='btn-wrap'>
|
||||
<Link to={`/p/${selectedAddress}`}>Return</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div id='catalog-button-mobile'>
|
||||
<span className='btn-wrap'>
|
||||
<Link
|
||||
to={`/p/${selectedAddress}/catalog`}
|
||||
onClick={() => {
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
>
|
||||
Catalog
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div id='bottom-button-mobile'>
|
||||
@@ -898,7 +880,7 @@ const Thread = () => {
|
||||
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
|
||||
</span>
|
||||
<span className='return-button catalog-button' id='catalog-button-desktop'>
|
||||
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
|
||||
</span>
|
||||
<span className='return-button catalog-button' id='bottom-button-desktop'>
|
||||
[
|
||||
@@ -2204,12 +2186,22 @@ const Thread = () => {
|
||||
</span>
|
||||
)
|
||||
</span>
|
||||
<span key={`ti-mob-${index}`} className='thread-icons-mobile' style={{ float: 'right', marginRight: '18px' }}>
|
||||
<span key={`ti-mob-${index}`} className='thread-icons-mobile'>
|
||||
{comment.pinned ? (
|
||||
<img src='assets/sticky.gif' alt='Sticky' title='Sticky' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/sticky.gif'
|
||||
alt='Sticky'
|
||||
title='Sticky'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
) : null}
|
||||
{comment.locked ? (
|
||||
<img src='assets/closed.gif' alt='Closed' title='Closed' style={{ marginTop: '-1px', marginRight: '2px', imageRendering: 'pixelated' }} />
|
||||
<img
|
||||
src='assets/closed.gif'
|
||||
alt='Closed'
|
||||
title='Closed'
|
||||
style={{ all: 'unset', marginBottom: '-2px', paddingLeft: '2px', imageRendering: 'pixelated' }}
|
||||
/>
|
||||
) : null}
|
||||
</span>
|
||||
<br key={`mob-br1-${comment.cid}`} />
|
||||
@@ -3033,10 +3025,10 @@ const Thread = () => {
|
||||
<div id='bottombar-desktop'>
|
||||
<hr />
|
||||
<span className='bottom-bar-return'>
|
||||
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
|
||||
</span>
|
||||
<span className='bottom-bar-catalog'>
|
||||
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
|
||||
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
|
||||
</span>
|
||||
<span className='bottom-bar-top'>
|
||||
[
|
||||
@@ -3141,7 +3133,7 @@ const Thread = () => {
|
||||
</div>
|
||||
<div id='catalog-button-mobile' style={{ paddingRight: '2px' }}>
|
||||
<span className='btn-wrap'>
|
||||
<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>
|
||||
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
|
||||
</span>
|
||||
</div>
|
||||
<span className='bottom-bar-top'>
|
||||
@@ -3222,14 +3214,9 @@ const Thread = () => {
|
||||
>
|
||||
<>
|
||||
<span className='boardList'>
|
||||
[
|
||||
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
|
||||
All
|
||||
</Link>
|
||||
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
|
||||
/
|
||||
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
|
||||
Subscriptions
|
||||
</Link>
|
||||
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
|
||||
]
|
||||
</span>
|
||||
{defaultSubplebbits.map((subplebbit, index) => (
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
export const showNewVersionToast = async (setNewInfoMessage, isElectron, packageJson, commitRef) => {
|
||||
try {
|
||||
const packageRes = await fetch('https://raw.githubusercontent.com/plebbit/plebchan/master/package.json', { cache: 'no-cache' });
|
||||
const packageData = await packageRes.json();
|
||||
|
||||
if (packageJson.version !== packageData.version) {
|
||||
const newVersionInfo = isElectron
|
||||
? `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Download the latest version here: https://github.com/plebbit/plebchan/releases/latest`
|
||||
: `New version available, plebchan v${packageData.version}. You are using v${packageJson.version}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
}
|
||||
|
||||
if (commitRef.length > 0) {
|
||||
const commitRes = await fetch('https://api.github.com/repos/plebbit/plebchan/commits?per_page=1&sha=development', { cache: 'no-cache' });
|
||||
const commitData = await commitRes.json();
|
||||
|
||||
const latestCommitHash = commitData[0].sha;
|
||||
|
||||
if (latestCommitHash.trim() !== commitRef.trim()) {
|
||||
const newVersionInfo = `New dev version available, commit ${latestCommitHash.slice(0, 7)}. You are using commit ${commitRef.slice(0, 7)}. Refresh to update.`;
|
||||
setNewInfoMessage(newVersionInfo);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch latest version info:', error);
|
||||
}
|
||||
};
|
||||
|
||||
export default showNewVersionToast;
|
||||
Reference in New Issue
Block a user