[CH] Replace Favorite Tab in a profilePage by custom links (#127)

This commit is contained in:
Clovis 2022-12-30 11:51:38 +01:00 committed by GitHub
parent 4a1515472b
commit 0b8acdc6d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 41 deletions

View file

@ -0,0 +1,53 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { useParams } from 'react-router-dom';
import { fetchAccountByUsername } from 'soapbox/actions/accounts';
import MissingIndicator from 'soapbox/components/missing_indicator';
import { Card } from 'soapbox/components/ui';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import {
ProfileFieldsPanel,
} from 'soapbox/features/ui/util/async-components';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { findAccountByUsername } from 'soapbox/selectors';
const ProfileFields = () => {
const { username } = useParams<{ username: string }>();
const dispatch = useAppDispatch();
const account = useAppSelector(state => {
const account = findAccountByUsername(state, username);
if (!account) {
dispatch(fetchAccountByUsername(username));
}
return account;
});
const isAccount = useAppSelector(state => !!state.getIn(['accounts', account?.id]));
if (!isAccount) {
return (
<MissingIndicator />
);
}
return (
account.fields.isEmpty() ? (
<div className='mt-2'>
<Card variant='rounded' size='lg'>
<FormattedMessage id='account.no_fields' defaultMessage='This section is empty for now.' />
</Card>
</div>
) : (
<BundleContainer fetchComponent={ProfileFieldsPanel}>
{Component => <Component account={account} />}
</BundleContainer>
)
);
};
export default ProfileFields;

View file

@ -1,8 +1,8 @@
import classNames from 'classnames';
import React from 'react';
import { defineMessages, useIntl, FormattedMessage, FormatDateOptions } from 'react-intl';
import { defineMessages, useIntl, FormatDateOptions } from 'react-intl';
import { Widget, Stack, HStack, Icon, Text } from 'soapbox/components/ui';
import { Stack, HStack, Icon, Text } from 'soapbox/components/ui';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import { CryptoAddress } from 'soapbox/features/ui/util/async-components';
@ -79,13 +79,11 @@ interface IProfileFieldsPanel {
/** Custom profile fields for sidebar. */
const ProfileFieldsPanel: React.FC<IProfileFieldsPanel> = ({ account }) => {
return (
<Widget title={<FormattedMessage id='profile_fields_panel.title' defaultMessage='Profile fields' />}>
<Stack space={4}>
{account.fields.map((field, i) => (
<ProfileField field={field} key={i} />
))}
</Stack>
</Widget>
<Stack space={4}>
{account.fields.map((field, i) => (
<ProfileField field={field} key={i} />
))}
</Stack>
);
};

View file

@ -113,6 +113,7 @@ import {
TestTimeline,
LogoutPage,
AuthTokenList,
ProfileFields,
} from './util/async-components';
import { WrappedRoute } from './util/react_router_helpers';
@ -190,18 +191,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
<WrappedRoute path='/messages' page={DefaultPage} component={Conversations} content={children} />
)}
{/* Gab groups */}
{/*
<WrappedRoute path='/groups' exact page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'featured' }} />
<WrappedRoute path='/groups/create' page={GroupsPage} component={Groups} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} />
<WrappedRoute path='/groups/browse/member' page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'member' }} />
<WrappedRoute path='/groups/browse/admin' page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'admin' }} />
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
<WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
<WrappedRoute path='/groups/:id/edit' page={GroupPage} component={GroupEdit} content={children} />
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
*/}
{/* Mastodon web routes */}
<Redirect from='/web/:path1/:path2/:path3' to='/:path1/:path2/:path3' />
<Redirect from='/web/:path1/:path2' to='/:path1/:path2' />
@ -278,6 +267,7 @@ const SwitchingColumnsArea: React.FC = ({ 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} />
<WrappedRoute path='/@:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/about' component={ProfileFields} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/posts/:statusId' publicRoute exact page={StatusPage} component={Status} content={children} />
<Redirect from='/@:username/:statusId' to='/@:username/posts/:statusId' />

View file

@ -366,6 +366,10 @@ export function ProfileMediaPanel() {
return import(/* webpackChunkName: "features/account_gallery" */'../components/profile_media_panel');
}
export function ProfileFields() {
return import(/* webpackChunkName: "features/favourited_statuses" */'../../profile_fields');
}
export function ProfileFieldsPanel() {
return import(/* webpackChunkName: "features/account_timeline" */'../components/profile_fields_panel');
}

View file

@ -12,6 +12,7 @@
"account.chat": "Chat with @{name}",
"account.deactivated": "Deactivated",
"account.direct": "Envoyer un message direct à @{name}",
"account.no_fields": "Cette section est vide pour le moment.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Modifier le profil",
"account.endorse": "Recommander sur le profil",
@ -34,6 +35,7 @@
"account.locked_info": "Ce compte est verrouillé. Son propriétaire approuve manuellement qui peut le ou la suivre.",
"account.login": "Connexion",
"account.media": "Média",
"account.about": "À propos",
"account.member_since": "Joined {date}",
"account.mention": "Mentionner",
"account.moved_to": "{name} a déménagé vers:",
@ -432,7 +434,7 @@
"edit_profile.fields.locked_label": "Verrouiller le compte",
"edit_profile.fields.meta_fields.content_placeholder": "Contenu",
"edit_profile.fields.meta_fields.label_placeholder": "Label",
"edit_profile.fields.meta_fields_label": "Champs du profil",
"edit_profile.fields.meta_fields_label": "Champs \"À propos\"",
"edit_profile.fields.stranger_notifications_label": "Bloquer les notifications d'inconnus",
"edit_profile.fields.website_label": "Website",
"edit_profile.fields.website_placeholder": "Display a Link",
@ -879,7 +881,7 @@
"profile_dropdown.logout": "Log out @{acct}",
"profile_dropdown.switch_account": "Switch accounts",
"profile_dropdown.theme": "Thème",
"profile_fields_panel.title": "Champs du profil",
"profile_fields_panel.title": "À propos",
"public.column_settings.title": "Fediverse timeline settings",
"reactions.all": "All",
"regeneration_indicator.label": "Chargement…",

View file

@ -2,7 +2,7 @@ import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Redirect, useHistory } from 'react-router-dom';
import { Column, Layout, Tabs } from 'soapbox/components/ui';
import { Column, Layout, Tabs, Widget } from 'soapbox/components/ui';
import Header from 'soapbox/features/account/components/header';
import LinkFooter from 'soapbox/features/ui/components/link_footer';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
@ -12,7 +12,6 @@ import {
ProfileMediaPanel,
ProfileFieldsPanel,
SignUpPanel,
CtaBanner,
PinnedAccountsPanel,
} from 'soapbox/features/ui/util/async-components';
import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
@ -66,27 +65,21 @@ const ProfilePage: React.FC<IProfilePage> = ({ params, children }) => {
to: `/@${username}/media`,
name: 'media',
},
{
text: <FormattedMessage id='account.about' defaultMessage='About' />,
to: `/@${username}/about`,
name: 'about',
},
];
if (account) {
const ownAccount = account.id === me;
if (ownAccount || !account.pleroma.get('hide_favorites', true)) {
tabItems.push({
text: <FormattedMessage id='navigation_bar.favourites' defaultMessage='Likes' />,
to: `/@${account.acct}/favorites`,
name: 'likes',
});
}
}
let activeItem;
const pathname = history.location.pathname.replace(`@${username}/`, '');
if (pathname.endsWith('/with_replies')) {
activeItem = 'replies';
} else if (pathname.endsWith('/media')) {
activeItem = 'media';
} else if (pathname.endsWith('/favorites')) {
activeItem = 'likes';
} else if (pathname.endsWith('/about')) {
activeItem = 'about';
} else {
activeItem = 'profile';
}
@ -123,9 +116,11 @@ const ProfilePage: React.FC<IProfilePage> = ({ params, children }) => {
{Component => <Component account={account} />}
</BundleContainer>
{account && !account.fields.isEmpty() && (
<BundleContainer fetchComponent={ProfileFieldsPanel}>
{Component => <Component account={account} />}
</BundleContainer>
<Widget title={<FormattedMessage id='profile_fields_panel.title' defaultMessage='Profile fields' />}>
<BundleContainer fetchComponent={ProfileFieldsPanel}>
{Component => <Component account={account} />}
</BundleContainer>
</Widget>
)}
{(features.accountEndorsements && account && isLocal(account)) ? (
<BundleContainer fetchComponent={PinnedAccountsPanel}>