2022-04-26 11:36:08 -07:00
|
|
|
'use strict';
|
|
|
|
|
2023-04-21 14:31:10 -07:00
|
|
|
import clsx from 'clsx';
|
|
|
|
import React, { useEffect, useRef } from 'react';
|
2022-06-28 12:28:20 -07:00
|
|
|
import { Switch, useHistory, useLocation, Redirect } from 'react-router-dom';
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2022-05-12 08:45:40 -07:00
|
|
|
import { fetchFollowRequests } from 'soapbox/actions/accounts';
|
|
|
|
import { fetchReports, fetchUsers, fetchConfig } from 'soapbox/actions/admin';
|
2022-07-06 14:25:19 -07:00
|
|
|
import { fetchAnnouncements } from 'soapbox/actions/announcements';
|
2022-11-16 05:32:32 -08:00
|
|
|
import { fetchCustomEmojis } from 'soapbox/actions/custom-emojis';
|
2022-05-12 08:45:40 -07:00
|
|
|
import { fetchFilters } from 'soapbox/actions/filters';
|
2022-04-26 11:36:08 -07:00
|
|
|
import { fetchMarker } from 'soapbox/actions/markers';
|
2022-05-12 08:45:40 -07:00
|
|
|
import { openModal } from 'soapbox/actions/modals';
|
|
|
|
import { expandNotifications } from 'soapbox/actions/notifications';
|
2022-11-15 12:50:11 -08:00
|
|
|
import { register as registerPushNotifications } from 'soapbox/actions/push-notifications';
|
2022-11-16 05:32:32 -08:00
|
|
|
import { fetchScheduledStatuses } from 'soapbox/actions/scheduled-statuses';
|
2022-07-01 13:09:07 -07:00
|
|
|
import { fetchSuggestionsForTimeline } from 'soapbox/actions/suggestions';
|
2022-05-12 08:45:40 -07:00
|
|
|
import { expandHomeTimeline } from 'soapbox/actions/timelines';
|
2023-07-22 10:49:02 -07:00
|
|
|
import { useNostrStream, useUserStream } from 'soapbox/api/hooks';
|
2023-04-17 11:56:31 -07:00
|
|
|
import GroupLookupHoc from 'soapbox/components/hoc/group-lookup-hoc';
|
|
|
|
import withHoc from 'soapbox/components/hoc/with-hoc';
|
2022-04-28 16:26:30 -07:00
|
|
|
import SidebarNavigation from 'soapbox/components/sidebar-navigation';
|
2022-11-15 08:00:49 -08:00
|
|
|
import ThumbNavigation from 'soapbox/components/thumb-navigation';
|
2022-04-28 16:26:30 -07:00
|
|
|
import { Layout } from 'soapbox/components/ui';
|
2023-07-22 10:49:02 -07:00
|
|
|
import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig, useFeatures, useDraggedFiles } from 'soapbox/hooks';
|
2022-11-15 11:36:52 -08:00
|
|
|
import AdminPage from 'soapbox/pages/admin-page';
|
2022-08-30 11:16:00 -07:00
|
|
|
import ChatsPage from 'soapbox/pages/chats-page';
|
2022-11-15 11:36:52 -08:00
|
|
|
import DefaultPage from 'soapbox/pages/default-page';
|
2022-11-26 11:25:48 -08:00
|
|
|
import EventPage from 'soapbox/pages/event-page';
|
2023-02-05 14:14:21 -08:00
|
|
|
import EventsPage from 'soapbox/pages/events-page';
|
2022-12-12 14:36:56 -08:00
|
|
|
import GroupPage from 'soapbox/pages/group-page';
|
2022-12-15 14:51:30 -08:00
|
|
|
import GroupsPage from 'soapbox/pages/groups-page';
|
2023-03-08 10:22:10 -08:00
|
|
|
import GroupsPendingPage from 'soapbox/pages/groups-pending-page';
|
2022-11-15 11:36:52 -08:00
|
|
|
import HomePage from 'soapbox/pages/home-page';
|
2023-04-05 07:29:57 -07:00
|
|
|
import ManageGroupsPage from 'soapbox/pages/manage-groups-page';
|
2022-11-15 11:36:52 -08:00
|
|
|
import ProfilePage from 'soapbox/pages/profile-page';
|
|
|
|
import RemoteInstancePage from 'soapbox/pages/remote-instance-page';
|
2023-06-14 05:11:39 -07:00
|
|
|
import SearchPage from 'soapbox/pages/search-page';
|
2022-11-15 11:36:52 -08:00
|
|
|
import StatusPage from 'soapbox/pages/status-page';
|
2022-11-01 10:22:29 -07:00
|
|
|
import { usePendingPolicy } from 'soapbox/queries/policies';
|
2023-07-22 10:49:02 -07:00
|
|
|
import { getVapidKey } from 'soapbox/utils/auth';
|
2022-04-28 16:57:50 -07:00
|
|
|
import { isStandalone } from 'soapbox/utils/state';
|
2022-09-28 11:37:56 -07:00
|
|
|
|
2022-11-16 05:32:32 -08:00
|
|
|
import BackgroundShapes from './components/background-shapes';
|
2022-12-23 12:51:57 -08:00
|
|
|
import FloatingActionButton from './components/floating-action-button';
|
2022-11-01 10:22:29 -07:00
|
|
|
import { supportedPolicyIds } from './components/modals/policy-modal';
|
2022-04-26 11:36:08 -07:00
|
|
|
import Navbar from './components/navbar';
|
2022-11-16 05:32:32 -08:00
|
|
|
import BundleContainer from './containers/bundle-container';
|
2022-04-26 11:36:08 -07:00
|
|
|
import {
|
|
|
|
Status,
|
|
|
|
CommunityTimeline,
|
|
|
|
PublicTimeline,
|
|
|
|
RemoteTimeline,
|
|
|
|
AccountTimeline,
|
|
|
|
AccountGallery,
|
|
|
|
HomeTimeline,
|
|
|
|
Followers,
|
|
|
|
Following,
|
|
|
|
DirectTimeline,
|
|
|
|
Conversations,
|
|
|
|
HashtagTimeline,
|
|
|
|
Notifications,
|
|
|
|
FollowRequests,
|
|
|
|
GenericNotFound,
|
|
|
|
FavouritedStatuses,
|
|
|
|
Blocks,
|
|
|
|
DomainBlocks,
|
|
|
|
Mutes,
|
|
|
|
Filters,
|
2023-03-04 12:22:59 -08:00
|
|
|
EditFilter,
|
2022-04-26 11:36:08 -07:00
|
|
|
PinnedStatuses,
|
|
|
|
Search,
|
|
|
|
ListTimeline,
|
|
|
|
Lists,
|
|
|
|
Bookmarks,
|
|
|
|
Settings,
|
|
|
|
EditProfile,
|
|
|
|
EditEmail,
|
|
|
|
EditPassword,
|
|
|
|
EmailConfirmation,
|
|
|
|
DeleteAccount,
|
|
|
|
SoapboxConfig,
|
2023-01-11 15:59:50 -08:00
|
|
|
ExportData,
|
2022-04-26 11:36:08 -07:00
|
|
|
ImportData,
|
2023-01-11 15:25:25 -08:00
|
|
|
Backups,
|
2022-04-26 11:36:08 -07:00
|
|
|
MfaForm,
|
|
|
|
ChatIndex,
|
2022-08-16 10:38:17 -07:00
|
|
|
ChatWidget,
|
2022-04-26 11:36:08 -07:00
|
|
|
ServerInfo,
|
|
|
|
Dashboard,
|
|
|
|
ModerationLog,
|
|
|
|
CryptoDonate,
|
|
|
|
ScheduledStatuses,
|
|
|
|
UserIndex,
|
|
|
|
FederationRestrictions,
|
|
|
|
Aliases,
|
|
|
|
Migration,
|
|
|
|
FollowRecommendations,
|
|
|
|
Directory,
|
|
|
|
SidebarMenu,
|
|
|
|
ProfileHoverCard,
|
2022-06-16 21:19:53 -07:00
|
|
|
StatusHoverCard,
|
2022-04-26 11:36:08 -07:00
|
|
|
Share,
|
|
|
|
NewStatus,
|
|
|
|
IntentionalError,
|
|
|
|
Developers,
|
|
|
|
CreateApp,
|
|
|
|
SettingsStore,
|
|
|
|
TestTimeline,
|
|
|
|
LogoutPage,
|
2022-05-12 08:45:40 -07:00
|
|
|
AuthTokenList,
|
2022-10-25 14:56:25 -07:00
|
|
|
ThemeEditor,
|
2022-11-29 15:32:21 -08:00
|
|
|
Quotes,
|
2022-11-03 16:48:10 -07:00
|
|
|
ServiceWorkerInfo,
|
2022-09-08 14:25:02 -07:00
|
|
|
EventInformation,
|
|
|
|
EventDiscussion,
|
2022-11-26 11:13:14 -08:00
|
|
|
Events,
|
2023-04-10 13:22:08 -07:00
|
|
|
GroupGallery,
|
2022-12-14 08:41:16 -08:00
|
|
|
Groups,
|
2023-02-27 05:25:59 -08:00
|
|
|
GroupsDiscover,
|
2023-03-14 09:46:16 -07:00
|
|
|
GroupsPopular,
|
|
|
|
GroupsSuggested,
|
2023-04-13 06:28:40 -07:00
|
|
|
GroupsTag,
|
2023-03-29 10:21:28 -07:00
|
|
|
GroupsTags,
|
2023-03-08 10:22:10 -08:00
|
|
|
PendingGroupRequests,
|
2022-12-16 15:07:35 -08:00
|
|
|
GroupMembers,
|
2023-03-23 12:20:19 -07:00
|
|
|
GroupTags,
|
|
|
|
GroupTagTimeline,
|
2022-12-12 14:36:56 -08:00
|
|
|
GroupTimeline,
|
2022-12-18 09:03:41 -08:00
|
|
|
ManageGroup,
|
|
|
|
GroupBlockedMembers,
|
|
|
|
GroupMembershipRequests,
|
2023-02-07 13:22:23 -08:00
|
|
|
Announcements,
|
2023-03-29 12:51:29 -07:00
|
|
|
EditGroup,
|
2023-07-02 04:19:27 -07:00
|
|
|
FollowedTags,
|
2022-04-26 11:36:08 -07:00
|
|
|
} from './util/async-components';
|
2023-07-03 04:53:41 -07:00
|
|
|
import GlobalHotkeys from './util/global-hotkeys';
|
2022-11-16 05:32:32 -08:00
|
|
|
import { WrappedRoute } from './util/react-router-helpers';
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
|
|
|
// Without this it ends up in ~8 very commonly used bundles.
|
2022-05-12 08:45:40 -07:00
|
|
|
import 'soapbox/components/status';
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2023-04-17 12:52:43 -07:00
|
|
|
const GroupTagsSlug = withHoc(GroupTags as any, GroupLookupHoc);
|
|
|
|
const GroupTagTimelineSlug = withHoc(GroupTagTimeline as any, GroupLookupHoc);
|
2023-04-17 11:56:31 -07:00
|
|
|
const GroupTimelineSlug = withHoc(GroupTimeline as any, GroupLookupHoc);
|
2023-04-17 12:28:20 -07:00
|
|
|
const GroupMembersSlug = withHoc(GroupMembers as any, GroupLookupHoc);
|
|
|
|
const GroupGallerySlug = withHoc(GroupGallery as any, GroupLookupHoc);
|
|
|
|
const ManageGroupSlug = withHoc(ManageGroup as any, GroupLookupHoc);
|
|
|
|
const EditGroupSlug = withHoc(EditGroup as any, GroupLookupHoc);
|
|
|
|
const GroupBlockedMembersSlug = withHoc(GroupBlockedMembers as any, GroupLookupHoc);
|
|
|
|
const GroupMembershipRequestsSlug = withHoc(GroupMembershipRequests as any, GroupLookupHoc);
|
2023-04-17 11:56:31 -07:00
|
|
|
|
2022-06-07 13:21:18 -07:00
|
|
|
const EmptyPage = HomePage;
|
|
|
|
|
2023-01-10 15:03:15 -08:00
|
|
|
interface ISwitchingColumnsArea {
|
|
|
|
children: React.ReactNode
|
|
|
|
}
|
|
|
|
|
|
|
|
const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = ({ children }) => {
|
2022-04-26 11:36:08 -07:00
|
|
|
const features = useFeatures();
|
2022-06-07 14:56:45 -07:00
|
|
|
const { search } = useLocation();
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
const { authenticatedProfile, cryptoAddresses } = useSoapboxConfig();
|
|
|
|
const hasCrypto = cryptoAddresses.size > 0;
|
|
|
|
|
|
|
|
// NOTE: Mastodon and Pleroma route some basenames to the backend.
|
|
|
|
// When adding new routes, use a basename that does NOT conflict
|
|
|
|
// with a known backend route, but DO redirect the backend route
|
|
|
|
// to the corresponding component as a fallback.
|
|
|
|
// Ex: use /login instead of /auth, but redirect /auth to /login
|
|
|
|
return (
|
|
|
|
<Switch>
|
|
|
|
<WrappedRoute path='/email-confirmation' page={EmptyPage} component={EmailConfirmation} publicRoute exact />
|
|
|
|
<WrappedRoute path='/logout' page={EmptyPage} component={LogoutPage} publicRoute exact />
|
|
|
|
|
|
|
|
<WrappedRoute path='/' exact page={HomePage} component={HomeTimeline} content={children} />
|
|
|
|
|
|
|
|
{/*
|
|
|
|
NOTE: we cannot nest routes in a fragment
|
|
|
|
https://stackoverflow.com/a/68637108
|
|
|
|
*/}
|
|
|
|
{features.federating && <WrappedRoute path='/timeline/local' exact page={HomePage} component={CommunityTimeline} content={children} publicRoute />}
|
|
|
|
{features.federating && <WrappedRoute path='/timeline/fediverse' exact page={HomePage} component={PublicTimeline} content={children} publicRoute />}
|
|
|
|
{features.federating && <WrappedRoute path='/timeline/:instance' exact page={RemoteInstancePage} component={RemoteTimeline} content={children} />}
|
|
|
|
|
2022-04-30 09:45:58 -07:00
|
|
|
{features.conversations && <WrappedRoute path='/conversations' page={DefaultPage} component={Conversations} content={children} />}
|
2022-05-24 08:24:47 -07:00
|
|
|
{features.directTimeline && <WrappedRoute path='/messages' page={DefaultPage} component={DirectTimeline} content={children} />}
|
|
|
|
{(features.conversations && !features.directTimeline) && (
|
2022-04-30 09:45:58 -07:00
|
|
|
<WrappedRoute path='/messages' page={DefaultPage} component={Conversations} content={children} />
|
|
|
|
)}
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
{/* Mastodon web routes */}
|
|
|
|
<Redirect from='/web/:path1/:path2/:path3' to='/:path1/:path2/:path3' />
|
|
|
|
<Redirect from='/web/:path1/:path2' to='/:path1/:path2' />
|
|
|
|
<Redirect from='/web/:path' to='/:path' />
|
|
|
|
<Redirect from='/timelines/home' to='/' />
|
|
|
|
<Redirect from='/timelines/public/local' to='/timeline/local' />
|
|
|
|
<Redirect from='/timelines/public' to='/timeline/fediverse' />
|
|
|
|
<Redirect from='/timelines/direct' to='/messages' />
|
|
|
|
|
|
|
|
{/* Pleroma FE web routes */}
|
|
|
|
<Redirect from='/main/all' to='/timeline/fediverse' />
|
|
|
|
<Redirect from='/main/public' to='/timeline/local' />
|
|
|
|
<Redirect from='/main/friends' to='/' />
|
|
|
|
<Redirect from='/tag/:id' to='/tags/:id' />
|
|
|
|
<Redirect from='/user-settings' to='/settings/profile' />
|
|
|
|
<WrappedRoute path='/notice/:statusId' publicRoute exact page={DefaultPage} component={Status} content={children} />
|
|
|
|
<Redirect from='/users/:username/statuses/:statusId' to='/@:username/posts/:statusId' />
|
|
|
|
<Redirect from='/users/:username/chats' to='/chats' />
|
|
|
|
<Redirect from='/users/:username' to='/@:username' />
|
|
|
|
<Redirect from='/registration' to='/' exact />
|
|
|
|
|
|
|
|
{/* Gab */}
|
|
|
|
<Redirect from='/home' to='/' />
|
|
|
|
|
|
|
|
{/* Mastodon rendered pages */}
|
2022-04-30 09:31:04 -07:00
|
|
|
<Redirect from='/admin' to='/soapbox/admin' />
|
2022-04-26 11:36:08 -07:00
|
|
|
<Redirect from='/terms' to='/about' />
|
|
|
|
<Redirect from='/settings/preferences' to='/settings' />
|
|
|
|
<Redirect from='/settings/two_factor_authentication_methods' to='/settings/mfa' />
|
|
|
|
<Redirect from='/settings/otp_authentication' to='/settings/mfa' />
|
|
|
|
<Redirect from='/settings/applications' to='/developers' />
|
|
|
|
<Redirect from='/auth/edit' to='/settings' />
|
2022-06-07 14:56:45 -07:00
|
|
|
<Redirect from='/auth/confirmation' to={`/email-confirmation${search}`} />
|
2022-04-26 11:36:08 -07:00
|
|
|
<Redirect from='/auth/reset_password' to='/reset-password' />
|
|
|
|
<Redirect from='/auth/edit_password' to='/edit-password' />
|
|
|
|
<Redirect from='/auth/sign_in' to='/login' />
|
|
|
|
<Redirect from='/auth/sign_out' to='/logout' />
|
|
|
|
|
|
|
|
{/* Pleroma hard-coded email URLs */}
|
|
|
|
<Redirect from='/registration/:token' to='/invite/:token' />
|
|
|
|
|
|
|
|
{/* Soapbox Legacy redirects */}
|
|
|
|
<Redirect from='/canary' to='/about/canary' />
|
|
|
|
<Redirect from='/canary.txt' to='/about/canary' />
|
|
|
|
<Redirect from='/auth/external' to='/login/external' />
|
|
|
|
<Redirect from='/auth/mfa' to='/settings/mfa' />
|
|
|
|
<Redirect from='/auth/password/new' to='/reset-password' />
|
2022-06-07 14:56:45 -07:00
|
|
|
<Redirect from='/auth/password/edit' to={`/edit-password${search}`} />
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
<WrappedRoute path='/tags/:id' publicRoute page={DefaultPage} component={HashtagTimeline} content={children} />
|
|
|
|
|
|
|
|
{features.lists && <WrappedRoute path='/lists' page={DefaultPage} component={Lists} content={children} />}
|
2022-11-30 09:19:16 -08:00
|
|
|
{features.lists && <WrappedRoute path='/list/:id' page={DefaultPage} component={ListTimeline} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
{features.bookmarks && <WrappedRoute path='/bookmarks' page={DefaultPage} component={Bookmarks} content={children} />}
|
|
|
|
|
|
|
|
<WrappedRoute path='/notifications' page={DefaultPage} component={Notifications} content={children} />
|
|
|
|
|
2023-06-14 05:11:39 -07:00
|
|
|
<WrappedRoute path='/search' page={SearchPage} component={Search} content={children} />
|
2022-04-26 11:36:08 -07:00
|
|
|
{features.suggestions && <WrappedRoute path='/suggestions' publicRoute page={DefaultPage} component={FollowRecommendations} content={children} />}
|
|
|
|
{features.profileDirectory && <WrappedRoute path='/directory' publicRoute page={DefaultPage} component={Directory} content={children} />}
|
2023-02-05 14:14:21 -08:00
|
|
|
{features.events && <WrappedRoute path='/events' page={EventsPage} component={Events} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2022-08-30 11:16:00 -07:00
|
|
|
{features.chats && <WrappedRoute path='/chats' exact page={ChatsPage} component={ChatIndex} content={children} />}
|
2022-09-28 17:16:20 -07:00
|
|
|
{features.chats && <WrappedRoute path='/chats/new' page={ChatsPage} component={ChatIndex} content={children} />}
|
2022-09-28 17:39:22 -07:00
|
|
|
{features.chats && <WrappedRoute path='/chats/settings' page={ChatsPage} component={ChatIndex} content={children} />}
|
2022-09-28 11:37:56 -07:00
|
|
|
{features.chats && <WrappedRoute path='/chats/:chatId' page={ChatsPage} component={ChatIndex} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
<WrappedRoute path='/follow_requests' page={DefaultPage} component={FollowRequests} content={children} />
|
|
|
|
<WrappedRoute path='/blocks' page={DefaultPage} component={Blocks} content={children} />
|
|
|
|
{features.federating && <WrappedRoute path='/domain_blocks' page={DefaultPage} component={DomainBlocks} content={children} />}
|
|
|
|
<WrappedRoute path='/mutes' page={DefaultPage} component={Mutes} content={children} />
|
2023-03-04 12:22:59 -08:00
|
|
|
{(features.filters || features.filtersV2) && <WrappedRoute path='/filters/new' page={DefaultPage} component={EditFilter} content={children} />}
|
|
|
|
{(features.filters || features.filtersV2) && <WrappedRoute path='/filters/:id' page={DefaultPage} component={EditFilter} content={children} />}
|
2023-03-04 03:43:27 -08:00
|
|
|
{(features.filters || features.filtersV2) && <WrappedRoute path='/filters' page={DefaultPage} component={Filters} content={children} />}
|
2023-07-02 04:19:27 -07:00
|
|
|
{(features.followedHashtagsList) && <WrappedRoute path='/followed_tags' page={DefaultPage} component={FollowedTags} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/@:username' publicRoute exact component={AccountTimeline} page={ProfilePage} content={children} />
|
|
|
|
<WrappedRoute path='/@:username/with_replies' publicRoute={!authenticatedProfile} component={AccountTimeline} page={ProfilePage} content={children} componentParams={{ withReplies: true }} />
|
|
|
|
<WrappedRoute path='/@:username/followers' publicRoute={!authenticatedProfile} component={Followers} page={ProfilePage} content={children} />
|
|
|
|
<WrappedRoute path='/@:username/following' publicRoute={!authenticatedProfile} component={Following} page={ProfilePage} content={children} />
|
|
|
|
<WrappedRoute path='/@:username/media' publicRoute={!authenticatedProfile} component={AccountGallery} page={ProfilePage} content={children} />
|
|
|
|
<WrappedRoute path='/@:username/tagged/:tag' exact component={AccountTimeline} page={ProfilePage} content={children} />
|
2022-05-16 14:33:45 -07:00
|
|
|
<WrappedRoute path='/@:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} />
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/@:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
|
|
|
|
<WrappedRoute path='/@:username/posts/:statusId' publicRoute exact page={StatusPage} component={Status} content={children} />
|
2022-11-29 15:32:21 -08:00
|
|
|
<WrappedRoute path='/@:username/posts/:statusId/quotes' publicRoute page={StatusPage} component={Quotes} content={children} />
|
2022-12-14 15:38:57 -08:00
|
|
|
{features.events && <WrappedRoute path='/@:username/events/:statusId' publicRoute exact page={EventPage} component={EventInformation} content={children} />}
|
|
|
|
{features.events && <WrappedRoute path='/@:username/events/:statusId/discussion' publicRoute exact page={EventPage} component={EventDiscussion} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
<Redirect from='/@:username/:statusId' to='/@:username/posts/:statusId' />
|
|
|
|
|
2022-12-17 05:37:08 -08:00
|
|
|
{features.groups && <WrappedRoute path='/groups' exact page={GroupsPage} component={Groups} content={children} />}
|
2023-02-27 05:25:59 -08:00
|
|
|
{features.groupsDiscovery && <WrappedRoute path='/groups/discover' exact page={GroupsPage} component={GroupsDiscover} content={children} />}
|
2023-03-14 09:46:16 -07:00
|
|
|
{features.groupsDiscovery && <WrappedRoute path='/groups/popular' exact page={GroupsPendingPage} component={GroupsPopular} content={children} />}
|
|
|
|
{features.groupsDiscovery && <WrappedRoute path='/groups/suggested' exact page={GroupsPendingPage} component={GroupsSuggested} content={children} />}
|
2023-04-13 06:28:40 -07:00
|
|
|
{features.groupsDiscovery && <WrappedRoute path='/groups/tags' exact page={GroupsPendingPage} component={GroupsTags} content={children} />}
|
|
|
|
{features.groupsDiscovery && <WrappedRoute path='/groups/discover/tags/:id' exact page={GroupsPendingPage} component={GroupsTag} content={children} />}
|
2023-03-08 10:22:10 -08:00
|
|
|
{features.groupsPending && <WrappedRoute path='/groups/pending-requests' exact page={GroupsPendingPage} component={PendingGroupRequests} content={children} />}
|
2023-04-17 12:52:43 -07:00
|
|
|
{features.groupsTags && <WrappedRoute path='/groups/:groupId/tags' exact page={GroupPage} component={GroupTags} content={children} />}
|
2023-03-23 12:20:19 -07:00
|
|
|
{features.groupsTags && <WrappedRoute path='/groups/:groupId/tag/:id' exact page={GroupsPendingPage} component={GroupTagTimeline} content={children} />}
|
2023-04-17 12:28:20 -07:00
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId' exact page={GroupPage} component={GroupTimeline} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/members' exact page={GroupPage} component={GroupMembers} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/media' publicRoute={!authenticatedProfile} component={GroupGallery} page={GroupPage} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/manage' exact page={ManageGroupsPage} component={ManageGroup} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/manage/edit' exact page={ManageGroupsPage} component={EditGroup} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/manage/blocks' exact page={ManageGroupsPage} component={GroupBlockedMembers} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/manage/requests' exact page={ManageGroupsPage} component={GroupMembershipRequests} content={children} />}
|
2023-03-20 18:57:49 -07:00
|
|
|
{features.groups && <WrappedRoute path='/groups/:groupId/posts/:statusId' exact page={StatusPage} component={Status} content={children} />}
|
2023-04-17 12:28:20 -07:00
|
|
|
|
2023-04-17 12:52:43 -07:00
|
|
|
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tags' exact page={GroupPage} component={GroupTagsSlug} content={children} />}
|
2023-04-21 06:36:37 -07:00
|
|
|
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tag/:tagId' exact page={GroupsPendingPage} component={GroupTagTimelineSlug} content={children} />}
|
2023-06-29 13:10:45 -07:00
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug' publicRoute exact page={GroupPage} component={GroupTimelineSlug} content={children} />}
|
2023-04-17 12:28:20 -07:00
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/members' exact page={GroupPage} component={GroupMembersSlug} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/media' publicRoute={!authenticatedProfile} component={GroupGallerySlug} page={GroupPage} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/manage' exact page={ManageGroupsPage} component={ManageGroupSlug} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/manage/edit' exact page={ManageGroupsPage} component={EditGroupSlug} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/manage/blocks' exact page={ManageGroupsPage} component={GroupBlockedMembersSlug} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/manage/requests' exact page={ManageGroupsPage} component={GroupMembershipRequestsSlug} content={children} />}
|
|
|
|
{features.groups && <WrappedRoute path='/group/:groupSlug/posts/:statusId' exact page={StatusPage} component={Status} content={children} />}
|
2023-06-05 07:41:21 -07:00
|
|
|
{features.groups && <Redirect from='/group/:groupSlug/statuses/:statusId' to='/group/:groupSlug/posts/:statusId' />}
|
2022-12-12 14:36:56 -08:00
|
|
|
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/statuses/new' page={DefaultPage} component={NewStatus} content={children} exact />
|
2022-05-30 09:18:31 -07:00
|
|
|
<WrappedRoute path='/statuses/:statusId' exact page={StatusPage} component={Status} content={children} />
|
2022-04-26 11:36:08 -07:00
|
|
|
{features.scheduledStatuses && <WrappedRoute path='/scheduled_statuses' page={DefaultPage} component={ScheduledStatuses} content={children} />}
|
|
|
|
|
|
|
|
<WrappedRoute path='/settings/profile' page={DefaultPage} component={EditProfile} content={children} />
|
2023-01-11 15:59:50 -08:00
|
|
|
{features.exportData && <WrappedRoute path='/settings/export' page={DefaultPage} component={ExportData} content={children} />}
|
2022-05-24 11:06:59 -07:00
|
|
|
{features.importData && <WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />}
|
2022-06-04 23:45:51 -07:00
|
|
|
{features.accountAliases && <WrappedRoute path='/settings/aliases' page={DefaultPage} component={Aliases} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
{features.accountMoving && <WrappedRoute path='/settings/migration' page={DefaultPage} component={Migration} content={children} />}
|
2023-01-11 15:25:25 -08:00
|
|
|
{features.backups && <WrappedRoute path='/settings/backups' page={DefaultPage} component={Backups} content={children} />}
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/settings/email' page={DefaultPage} component={EditEmail} content={children} />
|
|
|
|
<WrappedRoute path='/settings/password' page={DefaultPage} component={EditPassword} content={children} />
|
|
|
|
<WrappedRoute path='/settings/account' page={DefaultPage} component={DeleteAccount} content={children} />
|
|
|
|
<WrappedRoute path='/settings/mfa' page={DefaultPage} component={MfaForm} exact />
|
2022-05-12 08:45:40 -07:00
|
|
|
<WrappedRoute path='/settings/tokens' page={DefaultPage} component={AuthTokenList} content={children} />
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/settings' page={DefaultPage} component={Settings} content={children} />
|
|
|
|
<WrappedRoute path='/soapbox/config' adminOnly page={DefaultPage} component={SoapboxConfig} content={children} />
|
|
|
|
|
2022-04-30 09:31:04 -07:00
|
|
|
<WrappedRoute path='/soapbox/admin' staffOnly page={AdminPage} component={Dashboard} content={children} exact />
|
|
|
|
<WrappedRoute path='/soapbox/admin/approval' staffOnly page={AdminPage} component={Dashboard} content={children} exact />
|
|
|
|
<WrappedRoute path='/soapbox/admin/reports' staffOnly page={AdminPage} component={Dashboard} content={children} exact />
|
|
|
|
<WrappedRoute path='/soapbox/admin/log' staffOnly page={AdminPage} component={ModerationLog} content={children} exact />
|
|
|
|
<WrappedRoute path='/soapbox/admin/users' staffOnly page={AdminPage} component={UserIndex} content={children} exact />
|
2022-10-25 14:56:25 -07:00
|
|
|
<WrappedRoute path='/soapbox/admin/theme' staffOnly page={AdminPage} component={ThemeEditor} content={children} exact />
|
2023-02-07 13:22:23 -08:00
|
|
|
<WrappedRoute path='/soapbox/admin/announcements' staffOnly page={AdminPage} component={Announcements} content={children} exact />
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/info' page={EmptyPage} component={ServerInfo} content={children} />
|
|
|
|
|
|
|
|
<WrappedRoute path='/developers/apps/create' developerOnly page={DefaultPage} component={CreateApp} content={children} />
|
|
|
|
<WrappedRoute path='/developers/settings_store' developerOnly page={DefaultPage} component={SettingsStore} content={children} />
|
|
|
|
<WrappedRoute path='/developers/timeline' developerOnly page={DefaultPage} component={TestTimeline} content={children} />
|
2022-11-03 16:48:10 -07:00
|
|
|
<WrappedRoute path='/developers/sw' developerOnly page={DefaultPage} component={ServiceWorkerInfo} content={children} />
|
2022-04-26 11:36:08 -07:00
|
|
|
<WrappedRoute path='/developers' page={DefaultPage} component={Developers} content={children} />
|
|
|
|
<WrappedRoute path='/error/network' developerOnly page={EmptyPage} component={() => new Promise((_resolve, reject) => reject())} content={children} />
|
|
|
|
<WrappedRoute path='/error' developerOnly page={EmptyPage} component={IntentionalError} content={children} />
|
|
|
|
|
|
|
|
{hasCrypto && <WrappedRoute path='/donate/crypto' publicRoute page={DefaultPage} component={CryptoDonate} content={children} />}
|
|
|
|
{features.federating && <WrappedRoute path='/federation_restrictions' publicRoute page={DefaultPage} component={FederationRestrictions} content={children} />}
|
|
|
|
|
|
|
|
<WrappedRoute path='/share' page={DefaultPage} component={Share} content={children} exact />
|
|
|
|
|
|
|
|
<WrappedRoute page={EmptyPage} component={GenericNotFound} content={children} />
|
|
|
|
</Switch>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-01-10 15:03:15 -08:00
|
|
|
interface IUI {
|
|
|
|
children?: React.ReactNode
|
|
|
|
}
|
|
|
|
|
|
|
|
const UI: React.FC<IUI> = ({ children }) => {
|
2022-04-26 11:36:08 -07:00
|
|
|
const history = useHistory();
|
2022-09-17 00:29:36 -07:00
|
|
|
const dispatch = useAppDispatch();
|
2022-11-01 10:22:29 -07:00
|
|
|
const { data: pendingPolicy } = usePendingPolicy();
|
2022-04-26 11:36:08 -07:00
|
|
|
const node = useRef<HTMLDivElement | null>(null);
|
|
|
|
const me = useAppSelector(state => state.me);
|
2023-06-25 10:35:09 -07:00
|
|
|
const { account } = useOwnAccount();
|
2022-04-26 11:36:08 -07:00
|
|
|
const features = useFeatures();
|
|
|
|
const vapidKey = useAppSelector(state => getVapidKey(state));
|
|
|
|
|
2023-02-09 09:42:46 -08:00
|
|
|
const dropdownMenuIsOpen = useAppSelector(state => state.dropdown_menu.isOpen);
|
2022-04-28 16:57:50 -07:00
|
|
|
const standalone = useAppSelector(isStandalone);
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2023-04-21 14:31:10 -07:00
|
|
|
const { isDragging } = useDraggedFiles(node);
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
const handleServiceWorkerPostMessage = ({ data }: MessageEvent) => {
|
|
|
|
if (data.type === 'navigate') {
|
|
|
|
history.push(data.path);
|
|
|
|
} else {
|
|
|
|
console.warn('Unknown message type:', data.type);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-04-21 14:31:10 -07:00
|
|
|
const handleDragEnter = (e: DragEvent) => e.preventDefault();
|
|
|
|
const handleDragLeave = (e: DragEvent) => e.preventDefault();
|
|
|
|
const handleDragOver = (e: DragEvent) => e.preventDefault();
|
|
|
|
const handleDrop = (e: DragEvent) => e.preventDefault();
|
|
|
|
|
2022-04-26 11:36:08 -07:00
|
|
|
/** Load initial data when a user is logged in */
|
|
|
|
const loadAccountData = () => {
|
|
|
|
if (!account) return;
|
|
|
|
|
2022-07-01 13:09:07 -07:00
|
|
|
dispatch(expandHomeTimeline({}, () => {
|
|
|
|
dispatch(fetchSuggestionsForTimeline());
|
|
|
|
}));
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
dispatch(expandNotifications())
|
|
|
|
// @ts-ignore
|
|
|
|
.then(() => dispatch(fetchMarker(['notifications'])))
|
|
|
|
.catch(console.error);
|
|
|
|
|
2022-07-06 14:25:19 -07:00
|
|
|
dispatch(fetchAnnouncements());
|
|
|
|
|
2022-04-26 11:36:08 -07:00
|
|
|
if (account.staff) {
|
2022-05-15 06:11:59 -07:00
|
|
|
dispatch(fetchReports({ resolved: false }));
|
2022-04-26 11:36:08 -07:00
|
|
|
dispatch(fetchUsers(['local', 'need_approval']));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (account.admin) {
|
|
|
|
dispatch(fetchConfig());
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(() => dispatch(fetchFilters()), 500);
|
|
|
|
|
|
|
|
if (account.locked) {
|
|
|
|
setTimeout(() => dispatch(fetchFollowRequests()), 700);
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(() => dispatch(fetchScheduledStatuses()), 900);
|
|
|
|
};
|
|
|
|
|
|
|
|
useEffect(() => {
|
2022-05-16 14:33:45 -07:00
|
|
|
if ('serviceWorker' in navigator) {
|
2022-04-26 11:36:08 -07:00
|
|
|
navigator.serviceWorker.addEventListener('message', handleServiceWorkerPostMessage);
|
|
|
|
}
|
|
|
|
|
2023-01-11 11:55:52 -08:00
|
|
|
if (window.Notification?.permission === 'default') {
|
2022-04-26 11:36:08 -07:00
|
|
|
window.setTimeout(() => Notification.requestPermission(), 120 * 1000);
|
|
|
|
}
|
2023-04-21 14:31:10 -07:00
|
|
|
}, []);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
document.addEventListener('dragenter', handleDragEnter);
|
|
|
|
document.addEventListener('dragleave', handleDragLeave);
|
|
|
|
document.addEventListener('dragover', handleDragOver);
|
|
|
|
document.addEventListener('drop', handleDrop);
|
2022-04-26 11:36:08 -07:00
|
|
|
return () => {
|
|
|
|
document.removeEventListener('dragenter', handleDragEnter);
|
2023-04-21 14:31:10 -07:00
|
|
|
document.removeEventListener('dragleave', handleDragLeave);
|
2022-04-26 11:36:08 -07:00
|
|
|
document.removeEventListener('dragover', handleDragOver);
|
|
|
|
document.removeEventListener('drop', handleDrop);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
2023-07-22 10:49:02 -07:00
|
|
|
useUserStream();
|
|
|
|
useNostrStream();
|
2022-04-26 11:36:08 -07:00
|
|
|
|
|
|
|
// The user has logged in
|
|
|
|
useEffect(() => {
|
|
|
|
loadAccountData();
|
|
|
|
dispatch(fetchCustomEmojis());
|
|
|
|
}, [!!account]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
dispatch(registerPushNotifications());
|
|
|
|
}, [vapidKey]);
|
|
|
|
|
2022-11-01 10:22:29 -07:00
|
|
|
useEffect(() => {
|
2022-11-04 04:36:48 -07:00
|
|
|
if (account && pendingPolicy && supportedPolicyIds.includes(pendingPolicy.pending_policy_id)) {
|
|
|
|
setTimeout(() => {
|
|
|
|
dispatch(openModal('POLICY'));
|
|
|
|
}, 500);
|
2022-11-01 10:22:29 -07:00
|
|
|
}
|
2022-11-04 04:36:48 -07:00
|
|
|
}, [pendingPolicy, !!account]);
|
2022-11-01 10:22:29 -07:00
|
|
|
|
2022-04-26 11:36:08 -07:00
|
|
|
const shouldHideFAB = (): boolean => {
|
|
|
|
const path = location.pathname;
|
|
|
|
return Boolean(path.match(/^\/posts\/|^\/search|^\/getting-started|^\/chats/));
|
|
|
|
};
|
|
|
|
|
|
|
|
// Wait for login to succeed or fail
|
|
|
|
if (me === null) return null;
|
|
|
|
|
|
|
|
const style: React.CSSProperties = {
|
|
|
|
pointerEvents: dropdownMenuIsOpen ? 'none' : undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2023-07-03 04:53:41 -07:00
|
|
|
<GlobalHotkeys node={node}>
|
2022-12-06 22:45:10 -08:00
|
|
|
<div ref={node} style={style}>
|
2023-04-21 14:31:10 -07:00
|
|
|
<div
|
2023-04-21 15:13:40 -07:00
|
|
|
className={clsx('pointer-events-none fixed z-[90] h-screen w-screen transition', {
|
2023-04-21 14:31:10 -07:00
|
|
|
'backdrop-blur': isDragging,
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
|
2022-12-06 22:45:10 -08:00
|
|
|
<BackgroundShapes />
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2022-12-06 22:45:10 -08:00
|
|
|
<div className='z-10 flex flex-col'>
|
|
|
|
<Navbar />
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2022-12-06 22:45:10 -08:00
|
|
|
<Layout>
|
|
|
|
<Layout.Sidebar>
|
|
|
|
{!standalone && <SidebarNavigation />}
|
|
|
|
</Layout.Sidebar>
|
2022-04-28 16:26:30 -07:00
|
|
|
|
2022-12-06 22:45:10 -08:00
|
|
|
<SwitchingColumnsArea>
|
|
|
|
{children}
|
|
|
|
</SwitchingColumnsArea>
|
|
|
|
</Layout>
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2022-12-23 12:51:57 -08:00
|
|
|
{(me && !shouldHideFAB()) && (
|
2023-02-01 14:13:42 -08:00
|
|
|
<div className='fixed bottom-24 right-4 z-40 transition-all rtl:left-4 rtl:right-auto lg:hidden'>
|
2022-12-23 13:22:41 -08:00
|
|
|
<FloatingActionButton />
|
|
|
|
</div>
|
2022-12-23 12:51:57 -08:00
|
|
|
)}
|
2022-04-26 11:36:08 -07:00
|
|
|
|
2022-12-06 22:45:10 -08:00
|
|
|
{me && (
|
|
|
|
<BundleContainer fetchComponent={SidebarMenu}>
|
2022-04-26 11:36:08 -07:00
|
|
|
{Component => <Component />}
|
|
|
|
</BundleContainer>
|
2022-12-06 22:45:10 -08:00
|
|
|
)}
|
|
|
|
|
|
|
|
{me && features.chats && (
|
|
|
|
<BundleContainer fetchComponent={ChatWidget}>
|
|
|
|
{Component => (
|
|
|
|
<div className='hidden xl:block'>
|
|
|
|
<Component />
|
|
|
|
</div>
|
|
|
|
)}
|
2022-04-26 11:36:08 -07:00
|
|
|
</BundleContainer>
|
2022-12-06 22:45:10 -08:00
|
|
|
)}
|
|
|
|
<ThumbNavigation />
|
|
|
|
|
|
|
|
<BundleContainer fetchComponent={ProfileHoverCard}>
|
|
|
|
{Component => <Component />}
|
|
|
|
</BundleContainer>
|
|
|
|
|
|
|
|
<BundleContainer fetchComponent={StatusHoverCard}>
|
|
|
|
{Component => <Component />}
|
|
|
|
</BundleContainer>
|
2022-04-26 11:36:08 -07:00
|
|
|
</div>
|
2022-12-06 22:45:10 -08:00
|
|
|
</div>
|
2023-07-03 04:53:41 -07:00
|
|
|
</GlobalHotkeys>
|
2022-04-26 11:36:08 -07:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default UI;
|