diff --git a/packages/pl-fe/src/features/circle/index.tsx b/packages/pl-fe/src/features/circle/index.tsx index 18365a0a8..db534a7be 100644 --- a/packages/pl-fe/src/features/circle/index.tsx +++ b/packages/pl-fe/src/features/circle/index.tsx @@ -115,25 +115,29 @@ const Circle: React.FC = () => { const avatarUrl = users[i].avatar || avatarMissing; - await new Promise(resolve => { - const img = new Image(); + try { + await new Promise(resolve => { + const img = new Image(); - img.onload = () => { - ctx.save(); - ctx.beginPath(); - ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); - ctx.closePath(); - ctx.clip(); + img.onload = () => { + ctx.save(); + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); + ctx.closePath(); + ctx.clip(); - ctx.drawImage(img, centerX - radius, centerY - radius, radius * 2, radius * 2); - ctx.restore(); + ctx.drawImage(img, centerX - radius, centerY - radius, radius * 2, radius * 2); + ctx.restore(); - resolve(null); - }; + resolve(null); + }; - img.setAttribute('crossorigin', 'anonymous'); - img.src = avatarUrl; - }); + img.setAttribute('crossorigin', 'anonymous'); + img.src = avatarUrl; + }); + } catch (_) { + // + } } } diff --git a/packages/pl-fe/src/features/events/components/event-carousel.tsx b/packages/pl-fe/src/features/events/components/event-carousel.tsx deleted file mode 100644 index 1ba8a4527..000000000 --- a/packages/pl-fe/src/features/events/components/event-carousel.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import { Link } from 'react-router-dom'; -import ReactSwipeableViews from 'react-swipeable-views'; - -import EventPreview from 'pl-fe/components/event-preview'; -import Card from 'pl-fe/components/ui/card'; -import Icon from 'pl-fe/components/ui/icon'; -import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; -import { makeGetStatus } from 'pl-fe/selectors'; - -import PlaceholderEventPreview from '../../placeholder/components/placeholder-event-preview'; - -const Event = ({ id }: { id: string }) => { - const getStatus = useCallback(makeGetStatus(), []); - const status = useAppSelector(state => getStatus(state, { id })); - - if (!status) return null; - - return ( - - - - ); -}; - -interface IEventCarousel { - statusIds: Array; - isLoading?: boolean | null; - emptyMessage: React.ReactNode; -} - -const EventCarousel: React.FC = ({ statusIds, isLoading, emptyMessage }) => { - const [index, setIndex] = useState(0); - - const handleChangeIndex = (index: number) => { - setIndex(index % statusIds.length); - }; - - if (statusIds.length === 0) { - if (isLoading) { - return ; - } - - return ( - - {emptyMessage} - - ); - } - return ( -
- {index !== 0 && ( -
- -
- )} - - {statusIds.map(statusId => )} - - {index !== statusIds.length - 1 && ( -
- -
- )} -
- ); -}; - -export { EventCarousel as default }; diff --git a/packages/pl-fe/src/features/events/index.tsx b/packages/pl-fe/src/features/events/index.tsx deleted file mode 100644 index 8e01a115b..000000000 --- a/packages/pl-fe/src/features/events/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { useEffect } from 'react'; -import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; - -import { fetchJoinedEvents, fetchRecentEvents } from 'pl-fe/actions/events'; -import Button from 'pl-fe/components/ui/button'; -import { CardBody, CardHeader, CardTitle } from 'pl-fe/components/ui/card'; -import Column from 'pl-fe/components/ui/column'; -import HStack from 'pl-fe/components/ui/hstack'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; -import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; - -import EventCarousel from './components/event-carousel'; - -const messages = defineMessages({ - title: { id: 'column.events', defaultMessage: 'Events' }, -}); - -const Events = () => { - const intl = useIntl(); - - const dispatch = useAppDispatch(); - - const recentEvents = useAppSelector((state) => state.status_lists.recent_events!.items); - const recentEventsLoading = useAppSelector((state) => state.status_lists.recent_events!.isLoading); - const joinedEvents = useAppSelector((state) => state.status_lists.joined_events!.items); - const joinedEventsLoading = useAppSelector((state) => state.status_lists.joined_events!.isLoading); - - useEffect(() => { - dispatch(fetchRecentEvents()); - dispatch(fetchJoinedEvents()); - }, []); - - return ( - - - } /> - - - - } - /> - - - } /> - - - } - /> - - - ); -}; - -export { Events as default }; diff --git a/packages/pl-fe/src/features/ui/util/async-components.ts b/packages/pl-fe/src/features/ui/util/async-components.ts index 3f37e7b80..b817203a6 100644 --- a/packages/pl-fe/src/features/ui/util/async-components.ts +++ b/packages/pl-fe/src/features/ui/util/async-components.ts @@ -10,6 +10,7 @@ export const Blocks = lazy(() => import('pl-fe/pages/settings/blocks')); export const Bookmarks = lazy(() => import('pl-fe/pages/status-lists/bookmarks')); export const BubbleTimeline = lazy(() => import('pl-fe/pages/timelines/bubble-timeline')); export const ChatIndex = lazy(() => import('pl-fe/pages/chats/chats')); +export const Circles = lazy(() => import('pl-fe/pages/account-lists/circles')); export const CommunityTimeline = lazy(() => import('pl-fe/pages/timelines/community-timeline')); export const Conversations = lazy(() => import('pl-fe/pages/status-lists/conversations')); export const CreateApp = lazy(() => import('pl-fe/pages/developers/create-app')); @@ -17,6 +18,7 @@ export const CryptoDonate = lazy(() => import('pl-fe/pages/utils/crypto-donate') export const Dashboard = lazy(() => import('pl-fe/pages/dashboard/dashboard')); export const DeleteAccount = lazy(() => import('pl-fe/pages/settings/delete-account')); export const Developers = lazy(() => import('pl-fe/pages/developers/developers')); +export const Directory = lazy(() => import('pl-fe/pages/account-lists/directory')); export const DomainBlocks = lazy(() => import('pl-fe/pages/settings/domain-blocks')); export const Domains = lazy(() => import('pl-fe/pages/dashboard/domains')); export const EditEmail = lazy(() => import('pl-fe/pages/settings/edit-email')); @@ -29,6 +31,10 @@ export const ExternalLogin = lazy(() => import('pl-fe/pages/auth/external-login' export const FavouritedStatuses = lazy(() => import('pl-fe/pages/status-lists/favourited-statuses')); export const FederationRestrictions = lazy(() => import('pl-fe/pages/utils/federation-restrictions')); export const Filters = lazy(() => import('pl-fe/pages/settings')); +export const Followers = lazy(() => import('pl-fe/pages/account-lists/followers')); +export const Following = lazy(() => import('pl-fe/pages/account-lists/following')); +export const FollowRecommendations = lazy(() => import('pl-fe/pages/account-lists/follow-recommendations')); +export const FollowRequests = lazy(() => import('pl-fe/pages/account-lists/follow-requests')); export const GenericNotFound = lazy(() => import('pl-fe/pages/utils/generic-not-found')); export const GroupBlockedMembers = lazy(() => import('pl-fe/pages/groups/group-blocked-members')); export const GroupGallery = lazy(() => import('pl-fe/pages/groups/group-gallery')); @@ -44,6 +50,7 @@ export const InteractionPolicies = lazy(() => import('pl-fe/pages/settings/inter export const LandingPage = lazy(() => import('pl-fe/pages/utils/landing')); export const LandingTimeline = lazy(() => import('pl-fe/pages/timelines/landing-timeline')); export const LinkTimeline = lazy(() => import('pl-fe/pages/timelines/link-timeline')); +export const Lists = lazy(() => import('pl-fe/pages/account-lists/lists')); export const ListTimeline = lazy(() => import('pl-fe/pages/timelines/list-timeline')); export const LoginPage = lazy(() => import('pl-fe/pages/auth/login')); export const LogoutPage = lazy(() => import('pl-fe/pages/auth/logout')); @@ -53,6 +60,7 @@ export const Migration = lazy(() => import('pl-fe/pages/settings/migration')); export const ModerationLog = lazy(() => import('pl-fe/pages/dashboard/moderation-log')); export const Mutes = lazy(() => import('pl-fe/pages/settings/mutes')); export const NewStatus = lazy(() => import('pl-fe/pages/utils/new-status')); +export const OutgoingFollowRequests = lazy(() => import('pl-fe/pages/account-lists/outgoing-follow-requests')); export const PasswordReset = lazy(() => import('pl-fe/pages/auth/password-reset')); export const PinnedStatuses = lazy(() => import('pl-fe/pages/status-lists/pinned-statuses')); export const PlFeConfig = lazy(() => import('pl-fe/pages/dashboard/pl-fe-config')); @@ -73,30 +81,23 @@ export const ThemeEditor = lazy(() => import('pl-fe/pages/dashboard/theme-editor export const UrlPrivacy = lazy(() => import('pl-fe/pages/settings/url-privacy')); export const UserIndex = lazy(() => import('pl-fe/pages/dashboard/user-index')); +export const DraftStatuses = lazy(() => import('pl-fe/pages/status-lists/draft-statuses')); +export const EventDiscussion = lazy(() => import('pl-fe/pages/statuses/event-discussion')); +export const EventInformation = lazy(() => import('pl-fe/pages/statuses/event-information')); +export const Events = lazy(() => import('pl-fe/pages/status-lists/events')); +export const InteractionRequests = lazy(() => import('pl-fe/pages/status-lists/interaction-requests')); +export const ScheduledStatuses = lazy(() => import('pl-fe/pages/status-lists/scheduled-statuses')); +export const Status = lazy(() => import('pl-fe/pages/statuses/status')); + export const AccountGallery = lazy(() => import('pl-fe/features/account-gallery')); export const AccountTimeline = lazy(() => import('pl-fe/features/account-timeline')); export const BookmarkFolders = lazy(() => import('pl-fe/features/bookmark-folders')); export const Circle = lazy(() => import('pl-fe/features/circle')); -export const Circles = lazy(() => import('pl-fe/pages/account-lists/circles')); export const ComposeEditor = lazy(() => import('pl-fe/features/compose/editor')); export const ComposeEvent = lazy(() => import('pl-fe/features/compose-event')); -export const Directory = lazy(() => import('pl-fe/pages/account-lists/directory')); -export const DraftStatuses = lazy(() => import('pl-fe/features/draft-statuses')); -export const EventDiscussion = lazy(() => import('pl-fe/features/event/event-discussion')); -export const EventInformation = lazy(() => import('pl-fe/features/event/event-information')); -export const Events = lazy(() => import('pl-fe/features/events')); export const FollowedTags = lazy(() => import('pl-fe/features/followed-tags')); -export const Followers = lazy(() => import('pl-fe/pages/account-lists/followers')); -export const Following = lazy(() => import('pl-fe/pages/account-lists/following')); -export const FollowRecommendations = lazy(() => import('pl-fe/pages/account-lists/follow-recommendations')); -export const FollowRequests = lazy(() => import('pl-fe/pages/account-lists/follow-requests')); -export const InteractionRequests = lazy(() => import('pl-fe/features/interaction-requests')); -export const Lists = lazy(() => import('pl-fe/pages/account-lists/lists')); export const Notifications = lazy(() => import('pl-fe/features/notifications')); -export const OutgoingFollowRequests = lazy(() => import('pl-fe/pages/account-lists/outgoing-follow-requests')); -export const ScheduledStatuses = lazy(() => import('pl-fe/features/scheduled-statuses')); export const Search = lazy(() => import('pl-fe/features/search')); -export const Status = lazy(() => import('pl-fe/features/status')); // Panels export const AccountNotePanel = lazy(() => import('pl-fe/features/ui/components/panels/account-note-panel')); diff --git a/packages/pl-fe/src/features/draft-statuses/index.tsx b/packages/pl-fe/src/pages/status-lists/draft-statuses.tsx similarity index 89% rename from packages/pl-fe/src/features/draft-statuses/index.tsx rename to packages/pl-fe/src/pages/status-lists/draft-statuses.tsx index f9384175c..a49b06931 100644 --- a/packages/pl-fe/src/features/draft-statuses/index.tsx +++ b/packages/pl-fe/src/pages/status-lists/draft-statuses.tsx @@ -7,13 +7,13 @@ import Column from 'pl-fe/components/ui/column'; import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; -import DraftStatus from './components/draft-status'; +import DraftStatus from '../../features/draft-statuses/components/draft-status'; const messages = defineMessages({ heading: { id: 'column.draft_statuses', defaultMessage: 'Drafts' }, }); -const DraftStatuses = () => { +const DraftStatusesPage = () => { const intl = useIntl(); const dispatch = useAppDispatch(); @@ -38,4 +38,4 @@ const DraftStatuses = () => { ); }; -export { DraftStatuses as default }; +export { DraftStatusesPage as default }; diff --git a/packages/pl-fe/src/pages/status-lists/events.tsx b/packages/pl-fe/src/pages/status-lists/events.tsx new file mode 100644 index 000000000..cedc930b1 --- /dev/null +++ b/packages/pl-fe/src/pages/status-lists/events.tsx @@ -0,0 +1,136 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { Link } from 'react-router-dom'; +import ReactSwipeableViews from 'react-swipeable-views'; + +import { fetchJoinedEvents, fetchRecentEvents } from 'pl-fe/actions/events'; +import EventPreview from 'pl-fe/components/event-preview'; +import Button from 'pl-fe/components/ui/button'; +import Card, { CardBody, CardHeader, CardTitle } from 'pl-fe/components/ui/card'; +import Column from 'pl-fe/components/ui/column'; +import HStack from 'pl-fe/components/ui/hstack'; +import Icon from 'pl-fe/components/ui/icon'; +import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; +import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; +import { makeGetStatus } from 'pl-fe/selectors'; + +import PlaceholderEventPreview from '../../features/placeholder/components/placeholder-event-preview'; + +const messages = defineMessages({ + title: { id: 'column.events', defaultMessage: 'Events' }, +}); + +const Event = ({ id }: { id: string }) => { + const getStatus = useCallback(makeGetStatus(), []); + const status = useAppSelector(state => getStatus(state, { id })); + + if (!status) return null; + + return ( + + + + ); +}; + +interface IEventCarousel { + statusIds: Array; + isLoading?: boolean | null; + emptyMessage: React.ReactNode; +} + +const EventCarousel: React.FC = ({ statusIds, isLoading, emptyMessage }) => { + const [index, setIndex] = useState(0); + + const handleChangeIndex = (index: number) => { + setIndex(index % statusIds.length); + }; + + if (statusIds.length === 0) { + if (isLoading) { + return ; + } + + return ( + + {emptyMessage} + + ); + } + return ( +
+ {index !== 0 && ( +
+ +
+ )} + + {statusIds.map(statusId => )} + + {index !== statusIds.length - 1 && ( +
+ +
+ )} +
+ ); +}; + +const EventsPage = () => { + const intl = useIntl(); + + const dispatch = useAppDispatch(); + + const recentEvents = useAppSelector((state) => state.status_lists.recent_events!.items); + const recentEventsLoading = useAppSelector((state) => state.status_lists.recent_events!.isLoading); + const joinedEvents = useAppSelector((state) => state.status_lists.joined_events!.items); + const joinedEventsLoading = useAppSelector((state) => state.status_lists.joined_events!.isLoading); + + useEffect(() => { + dispatch(fetchRecentEvents()); + dispatch(fetchJoinedEvents()); + }, []); + + return ( + + + } /> + + + + } + /> + + + } /> + + + } + /> + + + ); +}; + +export { EventsPage as default }; diff --git a/packages/pl-fe/src/features/interaction-requests/index.tsx b/packages/pl-fe/src/pages/status-lists/interaction-requests.tsx similarity index 99% rename from packages/pl-fe/src/features/interaction-requests/index.tsx rename to packages/pl-fe/src/pages/status-lists/interaction-requests.tsx index 0c1891e0f..fd6b33fec 100644 --- a/packages/pl-fe/src/features/interaction-requests/index.tsx +++ b/packages/pl-fe/src/pages/status-lists/interaction-requests.tsx @@ -216,7 +216,7 @@ const InteractionRequest: React.FC = ({ ); }; -const InteractionRequests = () => { +const InteractionRequestsPage = () => { const intl = useIntl(); const { data = [], fetchNextPage, hasNextPage, isFetching, isLoading, refetch } = useFlatInteractionRequests(); @@ -268,4 +268,4 @@ const InteractionRequests = () => { ); }; -export { InteractionRequests as default }; +export { InteractionRequestsPage as default }; diff --git a/packages/pl-fe/src/features/scheduled-statuses/index.tsx b/packages/pl-fe/src/pages/status-lists/scheduled-statuses.tsx similarity index 88% rename from packages/pl-fe/src/features/scheduled-statuses/index.tsx rename to packages/pl-fe/src/pages/status-lists/scheduled-statuses.tsx index bdfa01076..d092fe403 100644 --- a/packages/pl-fe/src/features/scheduled-statuses/index.tsx +++ b/packages/pl-fe/src/pages/status-lists/scheduled-statuses.tsx @@ -6,13 +6,13 @@ import ScrollableList from 'pl-fe/components/scrollable-list'; import Column from 'pl-fe/components/ui/column'; import { scheduledStatusesQueryOptions } from 'pl-fe/queries/statuses/scheduled-statuses'; -import ScheduledStatus from './components/scheduled-status'; +import ScheduledStatus from '../../features/scheduled-statuses/components/scheduled-status'; const messages = defineMessages({ heading: { id: 'column.scheduled_statuses', defaultMessage: 'Scheduled posts' }, }); -const ScheduledStatuses = () => { +const ScheduledStatusesPage = () => { const intl = useIntl(); const { data: scheduledStatuses = [], isLoading, hasNextPage, fetchNextPage } = useInfiniteQuery(scheduledStatusesQueryOptions); @@ -34,4 +34,4 @@ const ScheduledStatuses = () => { ); }; -export { ScheduledStatuses as default }; +export { ScheduledStatusesPage as default }; diff --git a/packages/pl-fe/src/features/event/event-discussion.tsx b/packages/pl-fe/src/pages/statuses/event-discussion.tsx similarity index 92% rename from packages/pl-fe/src/features/event/event-discussion.tsx rename to packages/pl-fe/src/pages/statuses/event-discussion.tsx index 810148c41..74093f4f9 100644 --- a/packages/pl-fe/src/features/event/event-discussion.tsx +++ b/packages/pl-fe/src/pages/statuses/event-discussion.tsx @@ -13,9 +13,9 @@ import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; import { makeGetStatus } from 'pl-fe/selectors'; -import { makeGetDescendantsIds } from '../status/components/thread'; -import ThreadStatus from '../status/components/thread-status'; -import { ComposeForm } from '../ui/util/async-components'; +import { makeGetDescendantsIds } from '../../features/status/components/thread'; +import ThreadStatus from '../../features/status/components/thread-status'; +import { ComposeForm } from '../../features/ui/util/async-components'; import type { MediaAttachment } from 'pl-api'; import type { VirtuosoHandle } from 'react-virtuoso'; @@ -28,7 +28,7 @@ interface IEventDiscussion { onOpenVideo: (video: MediaAttachment, time: number) => void; } -const EventDiscussion: React.FC = ({ params: { statusId: statusId } }) => { +const EventDiscussionPage: React.FC = ({ params: { statusId: statusId } }) => { const intl = useIntl(); const dispatch = useAppDispatch(); @@ -165,4 +165,4 @@ const EventDiscussion: React.FC = ({ params: { statusId: statu ); }; -export { EventDiscussion as default }; +export { EventDiscussionPage as default }; diff --git a/packages/pl-fe/src/features/event/event-information.tsx b/packages/pl-fe/src/pages/statuses/event-information.tsx similarity index 97% rename from packages/pl-fe/src/features/event/event-information.tsx rename to packages/pl-fe/src/pages/statuses/event-information.tsx index 41bf8d4c2..05999f155 100644 --- a/packages/pl-fe/src/features/event/event-information.tsx +++ b/packages/pl-fe/src/pages/statuses/event-information.tsx @@ -20,7 +20,7 @@ interface IEventInformation { params: RouteParams; } -const EventInformation: React.FC = ({ params }) => { +const EventInformationPage: React.FC = ({ params }) => { const dispatch = useAppDispatch(); const getStatus = useCallback(makeGetStatus(), []); const intl = useIntl(); @@ -195,4 +195,4 @@ const EventInformation: React.FC = ({ params }) => { ); }; -export { EventInformation as default }; +export { EventInformationPage as default }; diff --git a/packages/pl-fe/src/features/status/index.tsx b/packages/pl-fe/src/pages/statuses/status.tsx similarity index 94% rename from packages/pl-fe/src/features/status/index.tsx rename to packages/pl-fe/src/pages/statuses/status.tsx index 33911d7eb..ed64a1b8b 100644 --- a/packages/pl-fe/src/features/status/index.tsx +++ b/packages/pl-fe/src/pages/statuses/status.tsx @@ -13,8 +13,8 @@ import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; import { useLoggedIn } from 'pl-fe/hooks/use-logged-in'; import { makeGetStatus } from 'pl-fe/selectors'; -import Thread from './components/thread'; -import ThreadLoginCta from './components/thread-login-cta'; +import Thread from '../../features/status/components/thread'; +import ThreadLoginCta from '../../features/status/components/thread-login-cta'; const messages = defineMessages({ title: { id: 'status.title', defaultMessage: 'Post details' }, @@ -43,7 +43,7 @@ interface IStatusDetails { params: RouteParams; } -const StatusDetails: React.FC = (props) => { +const StatusPage: React.FC = (props) => { const dispatch = useAppDispatch(); const intl = useIntl(); const { isLoggedIn } = useLoggedIn(); @@ -113,4 +113,4 @@ const StatusDetails: React.FC = (props) => { ); }; -export { StatusDetails as default }; +export { StatusPage as default };