Big Buffet readwrite fork
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
fe08f06e5e
commit
a530d3dfb2
16 changed files with 86 additions and 149 deletions
|
@ -290,8 +290,9 @@ const Account = ({
|
|||
) : withAccountNote && (
|
||||
<Text
|
||||
size='sm'
|
||||
truncate
|
||||
dangerouslySetInnerHTML={{ __html: account.note_emojified }}
|
||||
className='mr-2 rtl:ml-2 rtl:mr-0'
|
||||
className='mr-2 line-clamp-2 rtl:ml-2 rtl:mr-0'
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
@ -139,7 +139,7 @@ export const ProfileHoverCard: React.FC<IProfileHoverCard> = ({ visible = true }
|
|||
) : null}
|
||||
|
||||
{account.note.length > 0 && (
|
||||
<Text size='sm' dangerouslySetInnerHTML={accountBio} />
|
||||
<Text className='line-clamp-2' truncate size='sm' dangerouslySetInnerHTML={accountBio} />
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
|
|
|
@ -24,15 +24,12 @@ const messages = defineMessages({
|
|||
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||
profile: { id: 'account.profile', defaultMessage: 'Profile' },
|
||||
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
||||
domainBlocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
||||
followedTags: { id: 'navigation_bar.followed_tags', defaultMessage: 'Followed hashtags' },
|
||||
soapboxConfig: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' },
|
||||
accountMigration: { id: 'navigation_bar.account_migration', defaultMessage: 'Move account' },
|
||||
accountAliases: { id: 'navigation_bar.account_aliases', defaultMessage: 'Account aliases' },
|
||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||
profileDirectory: { id: 'navigation_bar.profile_directory', defaultMessage: 'Profile directory' },
|
||||
bookmarks: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' },
|
||||
lists: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||
groups: { id: 'column.groups', defaultMessage: 'Groups' },
|
||||
|
@ -236,6 +233,15 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
|||
/>
|
||||
)}
|
||||
|
||||
{features.profileDirectory && (
|
||||
<SidebarLink
|
||||
to='/directory'
|
||||
icon={require('@tabler/icons/address-book.svg')}
|
||||
text={intl.formatMessage(messages.profileDirectory)}
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
{settings.get('isDeveloper') && (
|
||||
<SidebarLink
|
||||
to='/developers'
|
||||
|
@ -267,20 +273,6 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
|||
|
||||
<Divider />
|
||||
|
||||
<SidebarLink
|
||||
to='/blocks'
|
||||
icon={require('@tabler/icons/ban.svg')}
|
||||
text={intl.formatMessage(messages.blocks)}
|
||||
onClick={onClose}
|
||||
/>
|
||||
|
||||
<SidebarLink
|
||||
to='/mutes'
|
||||
icon={require('@tabler/icons/circle-x.svg')}
|
||||
text={intl.formatMessage(messages.mutes)}
|
||||
onClick={onClose}
|
||||
/>
|
||||
|
||||
<SidebarLink
|
||||
to='/settings/preferences'
|
||||
icon={require('@tabler/icons/settings.svg')}
|
||||
|
@ -288,24 +280,6 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
|
|||
onClick={onClose}
|
||||
/>
|
||||
|
||||
{features.federating && (
|
||||
<SidebarLink
|
||||
to='/domain_blocks'
|
||||
icon={require('@tabler/icons/ban.svg')}
|
||||
text={intl.formatMessage(messages.domainBlocks)}
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(features.filters || features.filtersV2) && (
|
||||
<SidebarLink
|
||||
to='/filters'
|
||||
icon={require('@tabler/icons/filter.svg')}
|
||||
text={intl.formatMessage(messages.filters)}
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
{features.followedHashtagsList && (
|
||||
<SidebarLink
|
||||
to='/followed_tags'
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import React from 'react';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
import Account from 'soapbox/components/account';
|
||||
import { HStack, Icon, Stack } from 'soapbox/components/ui';
|
||||
import { useStatContext } from 'soapbox/contexts/stat-context';
|
||||
import ComposeButton from 'soapbox/features/ui/components/compose-button';
|
||||
import ProfileDropdown from 'soapbox/features/ui/components/profile-dropdown';
|
||||
import { useAppSelector, useGroupsPath, useFeatures, useOwnAccount, useSettings } from 'soapbox/hooks';
|
||||
|
||||
import DropdownMenu, { Menu } from './dropdown-menu';
|
||||
|
@ -14,6 +16,7 @@ const messages = defineMessages({
|
|||
bookmarks: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' },
|
||||
lists: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||
events: { id: 'column.events', defaultMessage: 'Events' },
|
||||
profileDirectory: { id: 'navigation_bar.profile_directory', defaultMessage: 'Profile directory' },
|
||||
developers: { id: 'navigation.developers', defaultMessage: 'Developers' },
|
||||
});
|
||||
|
||||
|
@ -68,6 +71,14 @@ const SidebarNavigation = () => {
|
|||
});
|
||||
}
|
||||
|
||||
if (features.profileDirectory) {
|
||||
menu.push({
|
||||
to: '/directory',
|
||||
text: intl.formatMessage(messages.profileDirectory),
|
||||
icon: require('@tabler/icons/address-book.svg'),
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.get('isDeveloper')) {
|
||||
menu.push({
|
||||
to: '/developers',
|
||||
|
@ -110,7 +121,7 @@ const SidebarNavigation = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Stack space={4}>
|
||||
<Stack className='h-full' space={4}>
|
||||
<Stack space={2}>
|
||||
<SidebarNavigationLink
|
||||
to='/'
|
||||
|
@ -197,6 +208,22 @@ const SidebarNavigation = () => {
|
|||
{account && (
|
||||
<ComposeButton />
|
||||
)}
|
||||
|
||||
<div className='grow' />
|
||||
|
||||
{account && (
|
||||
<div className='relative items-center'>
|
||||
<ProfileDropdown account={account}>
|
||||
<HStack className='w-full' alignItems='center' justifyContent='between' space={2}>
|
||||
<Account account={account} showProfileHoverCard={false} withLinkToProfile={false} hideActions />
|
||||
<Icon
|
||||
src={require('@tabler/icons/chevron-down.svg')}
|
||||
className='h-4 w-4 text-gray-900 transition-transform dark:text-gray-100'
|
||||
/>
|
||||
</HStack>
|
||||
</ProfileDropdown>
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -102,7 +102,7 @@ const Column: React.FC<IColumn> = React.forwardRef((props, ref: React.ForwardedR
|
|||
backHref={backHref}
|
||||
className={clsx({
|
||||
'rounded-t-3xl': !isScrolled && !transparent,
|
||||
'sticky top-12 z-10 bg-white/90 dark:bg-primary-900/90 backdrop-blur lg:top-16': !transparent,
|
||||
'sticky top-0 z-10 bg-white/90 dark:bg-primary-900/90 backdrop-blur': !transparent,
|
||||
'p-4 sm:p-0 sm:pb-4': transparent,
|
||||
'-mt-4 -mx-4 p-4': size !== 'lg' && !transparent,
|
||||
'-mt-4 -mx-4 p-4 sm:-mt-6 sm:-mx-6 sm:p-6': size === 'lg' && !transparent,
|
||||
|
|
|
@ -21,7 +21,7 @@ interface LayoutComponent extends React.FC<ILayout> {
|
|||
|
||||
/** Layout container, to hold Sidebar, Main, and Aside. */
|
||||
const Layout: LayoutComponent = ({ children }) => (
|
||||
<div className='relative sm:pt-4'>
|
||||
<div className='relative sm:pt-2'>
|
||||
<div className='mx-auto max-w-3xl sm:px-6 md:grid md:max-w-7xl md:grid-cols-12 md:gap-8 md:px-8'>
|
||||
{children}
|
||||
</div>
|
||||
|
@ -31,7 +31,7 @@ const Layout: LayoutComponent = ({ children }) => (
|
|||
/** Left sidebar container in the UI. */
|
||||
const Sidebar: React.FC<ISidebar> = ({ children }) => (
|
||||
<div className='hidden lg:col-span-3 lg:block'>
|
||||
<StickyBox offsetTop={80} className='pb-4'>
|
||||
<StickyBox className='pb-4'>
|
||||
{children}
|
||||
</StickyBox>
|
||||
</div>
|
||||
|
@ -51,7 +51,7 @@ const Main: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ children, classN
|
|||
/** Right sidebar container in the UI. */
|
||||
const Aside: React.FC<IAside> = ({ children }) => (
|
||||
<aside className='hidden xl:col-span-3 xl:block'>
|
||||
<StickyBox offsetTop={80} className='space-y-6 pb-12'>
|
||||
<StickyBox className='space-y-6 pb-12'>
|
||||
{children}
|
||||
</StickyBox>
|
||||
</aside>
|
||||
|
|
|
@ -57,7 +57,7 @@ const AccountCard: React.FC<IAccountCard> = ({ id }) => {
|
|||
<Text
|
||||
truncate
|
||||
align='left'
|
||||
className={clsx('[&_br]:hidden [&_p:first-child]:inline [&_p:first-child]:truncate [&_p]:hidden')}
|
||||
className={clsx('line-clamp-2 [&_br]:hidden [&_p:first-child]:block [&_p]:hidden')}
|
||||
dangerouslySetInnerHTML={{ __html: account.note_emojified || ' ' }}
|
||||
/>
|
||||
</Stack>
|
||||
|
|
|
@ -20,15 +20,17 @@ const messages = defineMessages({
|
|||
changePassword: { id: 'settings.change_password', defaultMessage: 'Change Password' },
|
||||
configureMfa: { id: 'settings.configure_mfa', defaultMessage: 'Configure MFA' },
|
||||
deleteAccount: { id: 'settings.delete_account', defaultMessage: 'Delete Account' },
|
||||
domainBlocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
||||
editProfile: { id: 'settings.edit_profile', defaultMessage: 'Edit Profile' },
|
||||
exportData: { id: 'column.export_data', defaultMessage: 'Export data' },
|
||||
filters: { id: 'navigation_bar.filters', defaultMessage: 'Filters' },
|
||||
importData: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' },
|
||||
mfaDisabled: { id: 'mfa.disabled', defaultMessage: 'Disabled' },
|
||||
mfaEnabled: { id: 'mfa.enabled', defaultMessage: 'Enabled' },
|
||||
mutes: { id: 'settings.mutes', defaultMessage: 'Mutes' },
|
||||
mutesAndBlocks: { id: 'settings.mutes_blocks', defaultMessage: 'Mutes and blocks' },
|
||||
other: { id: 'settings.other', defaultMessage: 'Other options' },
|
||||
preferences: { id: 'settings.preferences', defaultMessage: 'Preferences' },
|
||||
privacy: { id: 'settings.privacy', defaultMessage: 'Privacy' },
|
||||
profile: { id: 'settings.profile', defaultMessage: 'Profile' },
|
||||
security: { id: 'settings.security', defaultMessage: 'Security' },
|
||||
sessions: { id: 'settings.sessions', defaultMessage: 'Active sessions' },
|
||||
|
@ -58,6 +60,8 @@ const Settings = () => {
|
|||
const navigateToExportData = () => history.push('/settings/export');
|
||||
const navigateToMutes = () => history.push('/mutes');
|
||||
const navigateToBlocks = () => history.push('/blocks');
|
||||
const navigateToFilters = () => history.push('/filters');
|
||||
const navigateToDomainBlocks = () => history.push('/domain_blocks');
|
||||
|
||||
const isMfaEnabled = mfa.getIn(['settings', 'totp']);
|
||||
|
||||
|
@ -85,13 +89,15 @@ const Settings = () => {
|
|||
</CardBody>
|
||||
|
||||
<CardHeader>
|
||||
<CardTitle title={intl.formatMessage(messages.privacy)} />
|
||||
<CardTitle title={intl.formatMessage(messages.mutesAndBlocks)} />
|
||||
</CardHeader>
|
||||
|
||||
<CardBody>
|
||||
<List>
|
||||
<ListItem label={intl.formatMessage(messages.mutes)} onClick={navigateToMutes} />
|
||||
<ListItem label={intl.formatMessage(messages.blocks)} onClick={navigateToBlocks} />
|
||||
{(features.filters || features.filtersV2) && <ListItem label={intl.formatMessage(messages.filters)} onClick={navigateToFilters} />}
|
||||
{features.federating && <ListItem label={intl.formatMessage(messages.domainBlocks)} onClick={navigateToDomainBlocks} />}
|
||||
</List>
|
||||
</CardBody>
|
||||
|
||||
|
|
|
@ -40,20 +40,9 @@ const LinkFooter: React.FC = (): JSX.Element => {
|
|||
<div className='space-y-2'>
|
||||
<div className='divide-x-dot flex flex-wrap items-center text-gray-600'>
|
||||
{account && <>
|
||||
{features.profileDirectory && (
|
||||
<FooterLink to='/directory'><FormattedMessage id='navigation_bar.profile_directory' defaultMessage='Profile directory' /></FooterLink>
|
||||
)}
|
||||
<FooterLink to='/blocks'><FormattedMessage id='navigation_bar.blocks' defaultMessage='Blocks' /></FooterLink>
|
||||
<FooterLink to='/mutes'><FormattedMessage id='navigation_bar.mutes' defaultMessage='Mutes' /></FooterLink>
|
||||
{(features.filters || features.filtersV2) && (
|
||||
<FooterLink to='/filters'><FormattedMessage id='navigation_bar.filters' defaultMessage='Filters' /></FooterLink>
|
||||
)}
|
||||
{features.followedHashtagsList && (
|
||||
<FooterLink to='/followed_tags'><FormattedMessage id='navigation_bar.followed_tags' defaultMessage='Followed hashtags' /></FooterLink>
|
||||
)}
|
||||
{features.federating && (
|
||||
<FooterLink to='/domain_blocks'><FormattedMessage id='navigation_bar.domain_blocks' defaultMessage='Domain blocks' /></FooterLink>
|
||||
)}
|
||||
{account.admin && (
|
||||
<FooterLink to='/soapbox/config'><FormattedMessage id='navigation_bar.soapbox_config' defaultMessage='Soapbox config' /></FooterLink>
|
||||
)}
|
||||
|
|
|
@ -112,10 +112,6 @@ const HotkeysModal: React.FC<IHotkeysModal> = ({ onClose }) => {
|
|||
<TableCell><Hotkey>backspace</Hotkey></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.back' defaultMessage='to navigate back' /></TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableCell><Hotkey>s</Hotkey>, <Hotkey>/</Hotkey></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to focus search' /></TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableCell><Hotkey>esc</Hotkey></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.unfocus' defaultMessage='to un-focus compose textarea/search' /></TableCell>
|
||||
|
@ -133,9 +129,13 @@ const HotkeysModal: React.FC<IHotkeysModal> = ({ onClose }) => {
|
|||
<TableCell><Hotkey>g</Hotkey> + <Hotkey>h</Hotkey></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.home' defaultMessage='to open home timeline' /></TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableCell><Hotkey>g</Hotkey> + <Hotkey>s</Hotkey></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to open search page' /></TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableCell><Hotkey>g</Hotkey> + <Hotkey>n</Hotkey></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.notifications' defaultMessage='to open notifications column' /></TableCell>
|
||||
<TableCell><FormattedMessage id='keyboard_shortcuts.notifications' defaultMessage='to open notifications list' /></TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableCell><Hotkey>g</Hotkey> + <Hotkey>f</Hotkey></TableCell>
|
||||
|
|
|
@ -8,11 +8,8 @@ import { fetchInstance } from 'soapbox/actions/instance';
|
|||
import { openSidebar } from 'soapbox/actions/sidebar';
|
||||
import SiteLogo from 'soapbox/components/site-logo';
|
||||
import { Avatar, Button, Form, HStack, IconButton, Input, Tooltip } from 'soapbox/components/ui';
|
||||
import Search from 'soapbox/features/compose/components/search';
|
||||
import { useAppDispatch, useFeatures, useOwnAccount, useRegistrationStatus } from 'soapbox/hooks';
|
||||
|
||||
import ProfileDropdown from './profile-dropdown';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -65,11 +62,11 @@ const Navbar = () => {
|
|||
if (mfaToken) return <Redirect to={`/login?token=${encodeURIComponent(mfaToken)}`} />;
|
||||
|
||||
return (
|
||||
<nav className='sticky top-0 z-50 bg-white shadow dark:bg-primary-900' ref={node} data-testid='navbar'>
|
||||
<nav className={clsx('sticky top-0 z-50 bg-white shadow dark:bg-primary-900', { 'lg:hidden': !!account })} ref={node} data-testid='navbar'>
|
||||
<div className='mx-auto max-w-7xl px-2 sm:px-6 lg:px-8'>
|
||||
<div className='relative flex h-12 justify-between lg:h-16'>
|
||||
{account && (
|
||||
<div className='absolute inset-y-0 left-0 flex items-center rtl:left-auto rtl:right-0 lg:hidden'>
|
||||
<div className='absolute inset-y-0 left-0 flex items-center rtl:left-auto rtl:right-0'>
|
||||
<button onClick={onOpenSidebar}>
|
||||
<Avatar src={account.avatar} size={34} />
|
||||
</button>
|
||||
|
@ -88,24 +85,10 @@ const Navbar = () => {
|
|||
<SiteLogo alt='Logo' className='h-5 w-auto cursor-pointer' />
|
||||
<span className='hidden'><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></span>
|
||||
</Link>
|
||||
|
||||
{account && (
|
||||
<div className='hidden flex-1 items-center justify-center px-2 lg:ml-6 lg:flex lg:justify-start'>
|
||||
<div className='hidden w-full max-w-xl lg:block lg:max-w-xs'>
|
||||
<Search openInRoute autosuggest />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<HStack space={3} alignItems='center' className='absolute inset-y-0 right-0 pr-2 lg:static lg:inset-auto lg:ml-6 lg:pr-0'>
|
||||
{account ? (
|
||||
<div className='relative hidden items-center lg:flex'>
|
||||
<ProfileDropdown account={account}>
|
||||
<Avatar src={account.avatar} size={34} />
|
||||
</ProfileDropdown>
|
||||
</div>
|
||||
) : (
|
||||
{!account && (
|
||||
<>
|
||||
<Form className='hidden items-center space-x-2 rtl:space-x-reverse lg:flex' onSubmit={handleSubmit}>
|
||||
<Input
|
||||
|
|
|
@ -42,7 +42,7 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
|
|||
const intl = useIntl();
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { x, y, strategy, refs } = useFloating<HTMLButtonElement>({ placement: 'bottom-end' });
|
||||
const { x, y, strategy, refs } = useFloating<HTMLButtonElement>({ placement: 'top-start' });
|
||||
const authUsers = useAppSelector((state) => state.auth.users);
|
||||
const otherAccounts = useAppSelector((state) => authUsers.map((authUser: any) => getAccount(state, authUser.id)!));
|
||||
|
||||
|
|
|
@ -10,10 +10,11 @@ import type { Account } from 'soapbox/schemas';
|
|||
const messages = defineMessages({
|
||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||
statuses: { id: 'account.statuses', defaultMessage: 'Statuses' },
|
||||
});
|
||||
|
||||
interface IProfileStats {
|
||||
account: Pick<Account, 'acct' | 'followers_count' | 'following_count'> | undefined
|
||||
account: Pick<Account, 'acct' | 'followers_count' | 'following_count' | 'statuses_count'> | undefined
|
||||
onClickHandler?: React.MouseEventHandler
|
||||
}
|
||||
|
||||
|
@ -27,6 +28,15 @@ const ProfileStats: React.FC<IProfileStats> = ({ account, onClickHandler }) => {
|
|||
|
||||
return (
|
||||
<HStack alignItems='center' space={3}>
|
||||
<HStack alignItems='center' space={1}>
|
||||
<Text theme='primary' weight='bold' size='sm'>
|
||||
{shortNumberFormat(account.statuses_count)}
|
||||
</Text>
|
||||
<Text weight='bold' size='sm'>
|
||||
{intl.formatMessage(messages.statuses)}
|
||||
</Text>
|
||||
</HStack>
|
||||
|
||||
<NavLink to={`/@${account.acct}/followers`} onClick={onClickHandler} title={intl.formatNumber(account.followers_count)} className='hover:underline'>
|
||||
<HStack alignItems='center' space={1}>
|
||||
<Text theme='primary' weight='bold' size='sm'>
|
||||
|
|
|
@ -9,7 +9,6 @@ import { useAppSelector, useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
|||
const keyMap = {
|
||||
help: '?',
|
||||
new: 'n',
|
||||
search: ['s', '/'],
|
||||
forceNew: 'option+n',
|
||||
reply: 'r',
|
||||
favourite: 'f',
|
||||
|
@ -29,6 +28,7 @@ const keyMap = {
|
|||
goToBlocked: 'g b',
|
||||
goToMuted: 'g m',
|
||||
goToRequests: 'g r',
|
||||
goToSearch: 'g s',
|
||||
toggleHidden: 'x',
|
||||
toggleSensitive: 'h',
|
||||
openMedia: 'a',
|
||||
|
@ -58,17 +58,6 @@ const GlobalHotkeys: React.FC<IGlobalHotkeys> = ({ children, node }) => {
|
|||
}
|
||||
};
|
||||
|
||||
const handleHotkeySearch = (e?: KeyboardEvent) => {
|
||||
e?.preventDefault();
|
||||
if (!node.current) return;
|
||||
|
||||
const element = node.current.querySelector('input#search') as HTMLInputElement;
|
||||
|
||||
if (element) {
|
||||
element.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const handleHotkeyForceNew = (e?: KeyboardEvent) => {
|
||||
handleHotkeyNew(e);
|
||||
dispatch(resetCompose());
|
||||
|
@ -132,12 +121,16 @@ const GlobalHotkeys: React.FC<IGlobalHotkeys> = ({ children, node }) => {
|
|||
history.push('/follow_requests');
|
||||
};
|
||||
|
||||
const handleHotkeyGoToSearch = () => {
|
||||
if (!account) return;
|
||||
history.push('/search');
|
||||
};
|
||||
|
||||
type HotkeyHandlers = { [key: string]: (keyEvent?: KeyboardEvent) => void };
|
||||
|
||||
const handlers: HotkeyHandlers = {
|
||||
help: handleHotkeyToggleHelp,
|
||||
new: handleHotkeyNew,
|
||||
search: handleHotkeySearch,
|
||||
forceNew: handleHotkeyForceNew,
|
||||
back: handleHotkeyBack,
|
||||
goToHome: handleHotkeyGoToHome,
|
||||
|
@ -148,6 +141,7 @@ const GlobalHotkeys: React.FC<IGlobalHotkeys> = ({ children, node }) => {
|
|||
goToBlocked: handleHotkeyGoToBlocked,
|
||||
goToMuted: handleHotkeyGoToMuted,
|
||||
goToRequests: handleHotkeyGoToRequests,
|
||||
goToSearch: handleHotkeyGoToSearch,
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import clsx from 'clsx';
|
||||
import React, { useRef } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
|
||||
import { uploadCompose } from 'soapbox/actions/compose';
|
||||
import FeedCarousel from 'soapbox/features/feed-filtering/feed-carousel';
|
||||
import LinkFooter from 'soapbox/features/ui/components/link-footer';
|
||||
import {
|
||||
|
@ -17,10 +13,9 @@ import {
|
|||
CtaBanner,
|
||||
AnnouncementsPanel,
|
||||
} from 'soapbox/features/ui/util/async-components';
|
||||
import { useAppSelector, useOwnAccount, useFeatures, useSoapboxConfig, useDraggedFiles, useAppDispatch } from 'soapbox/hooks';
|
||||
import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
|
||||
|
||||
import { Avatar, Card, CardBody, HStack, Layout } from '../components/ui';
|
||||
import ComposeForm from '../features/compose/components/compose-form';
|
||||
import { Layout } from '../components/ui';
|
||||
import BundleContainer from '../features/ui/containers/bundle-container';
|
||||
|
||||
interface IHomePage {
|
||||
|
@ -28,59 +23,17 @@ interface IHomePage {
|
|||
}
|
||||
|
||||
const HomePage: React.FC<IHomePage> = ({ children }) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const me = useAppSelector(state => state.me);
|
||||
const { account } = useOwnAccount();
|
||||
const features = useFeatures();
|
||||
const soapboxConfig = useSoapboxConfig();
|
||||
|
||||
const composeId = 'home';
|
||||
const composeBlock = useRef<HTMLDivElement>(null);
|
||||
|
||||
const hasPatron = soapboxConfig.extensions.getIn(['patron', 'enabled']) === true;
|
||||
const hasCrypto = typeof soapboxConfig.cryptoAddresses.getIn([0, 'ticker']) === 'string';
|
||||
const cryptoLimit = soapboxConfig.cryptoDonatePanel.get('limit', 0);
|
||||
|
||||
const { isDragging, isDraggedOver } = useDraggedFiles(composeBlock, (files) => {
|
||||
dispatch(uploadCompose(composeId, files, intl));
|
||||
});
|
||||
|
||||
const acct = account ? account.acct : '';
|
||||
const avatar = account ? account.avatar : '';
|
||||
|
||||
return (
|
||||
<>
|
||||
<Layout.Main className='space-y-3 pt-3 dark:divide-gray-800 sm:pt-0'>
|
||||
{me && (
|
||||
<Card
|
||||
className={clsx('relative z-[1] transition', {
|
||||
'border-2 border-primary-600 border-dashed z-[99]': isDragging,
|
||||
'ring-2 ring-offset-2 ring-primary-600': isDraggedOver,
|
||||
})}
|
||||
variant='rounded'
|
||||
ref={composeBlock}
|
||||
>
|
||||
<CardBody>
|
||||
<HStack alignItems='start' space={4}>
|
||||
<Link to={`/@${acct}`}>
|
||||
<Avatar src={avatar} size={46} />
|
||||
</Link>
|
||||
|
||||
<div className='w-full translate-y-0.5'>
|
||||
<ComposeForm
|
||||
id={composeId}
|
||||
shouldCondense
|
||||
autoFocus={false}
|
||||
clickableAreaRef={composeBlock}
|
||||
/>
|
||||
</div>
|
||||
</HStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{features.carousel && <FeedCarousel />}
|
||||
|
||||
{children}
|
||||
|
|
|
@ -154,4 +154,4 @@ const accountSchema = baseAccountSchema.extend({
|
|||
|
||||
type Account = Resolve<z.infer<typeof accountSchema>>;
|
||||
|
||||
export { accountSchema, type Account };
|
||||
export { accountSchema, type Account };
|
||||
|
|
Loading…
Reference in a new issue