Update Lists list UI, fix reply mentions modal overflow
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
@ -297,7 +297,7 @@ const Account = ({
|
||||
</HStack>
|
||||
|
||||
<div ref={actionRef}>
|
||||
{withRelationship ? renderAction() : null}
|
||||
{(withRelationship || action) ? renderAction() : null}
|
||||
</div>
|
||||
</HStack>
|
||||
</div>
|
||||
|
||||
@ -103,9 +103,7 @@ const Bookmarks: React.FC<IBookmarks> = ({ params }) => {
|
||||
return (
|
||||
<Column
|
||||
label={folder ? folder.name : intl.formatMessage(messages.heading)}
|
||||
action={
|
||||
<DropdownMenu items={items} src={require('@tabler/icons/outline/dots-vertical.svg')} />
|
||||
}
|
||||
action={<DropdownMenu items={items} src={require('@tabler/icons/outline/dots-vertical.svg')} />}
|
||||
transparent
|
||||
>
|
||||
<PullToRefresh onRefresh={handleRefresh}>
|
||||
|
||||
@ -1,18 +1,28 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { fetchList } from 'soapbox/actions/lists';
|
||||
import { deleteList, fetchList } from 'soapbox/actions/lists';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { expandListTimeline } from 'soapbox/actions/timelines';
|
||||
import { useListStream } from 'soapbox/api/hooks';
|
||||
import DropdownMenu from 'soapbox/components/dropdown-menu';
|
||||
import MissingIndicator from 'soapbox/components/missing-indicator';
|
||||
import { Column, Button, Spinner } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useAppSelector, useTheme } from 'soapbox/hooks';
|
||||
|
||||
import Timeline from '../ui/components/timeline';
|
||||
|
||||
const messages = defineMessages({
|
||||
deleteHeading: { id: 'confirmations.delete_list.heading', defaultMessage: 'Delete list' },
|
||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||
deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' },
|
||||
editList: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
||||
deleteList: { id: 'lists.delete', defaultMessage: 'Delete list' },
|
||||
});
|
||||
|
||||
const ListTimeline: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const theme = useTheme();
|
||||
@ -35,6 +45,19 @@ const ListTimeline: React.FC = () => {
|
||||
dispatch(openModal('LIST_EDITOR', { listId: id }));
|
||||
};
|
||||
|
||||
const handleDeleteClick = (e: React.MouseEvent | React.KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
heading: intl.formatMessage(messages.deleteHeading),
|
||||
message: intl.formatMessage(messages.deleteMessage),
|
||||
confirm: intl.formatMessage(messages.deleteConfirm),
|
||||
onConfirm: () => {
|
||||
dispatch(deleteList(id));
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const title = list ? list.title : id;
|
||||
|
||||
if (typeof list === 'undefined') {
|
||||
@ -59,8 +82,25 @@ const ListTimeline: React.FC = () => {
|
||||
</div>
|
||||
);
|
||||
|
||||
const items = [
|
||||
{
|
||||
text: intl.formatMessage(messages.editList),
|
||||
action: handleEditClick,
|
||||
icon: require('@tabler/icons/outline/edit.svg'),
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage(messages.deleteList),
|
||||
action: handleDeleteClick,
|
||||
icon: require('@tabler/icons/outline/trash.svg'),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Column label={title} transparent>
|
||||
<Column
|
||||
label={title}
|
||||
action={<DropdownMenu items={items} src={require('@tabler/icons/outline/dots-vertical.svg')} />}
|
||||
transparent
|
||||
>
|
||||
<Timeline
|
||||
className='black:p-4 black:sm:p-5'
|
||||
scrollKey='list_timeline'
|
||||
|
||||
@ -32,7 +32,7 @@ const NewListForm: React.FC = () => {
|
||||
|
||||
return (
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<HStack space={2}>
|
||||
<HStack space={2} alignItems='center'>
|
||||
<label className='grow'>
|
||||
<span style={{ display: 'none' }}>{label}</span>
|
||||
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { deleteList, fetchLists } from 'soapbox/actions/lists';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Column, IconButton, Spinner } from 'soapbox/components/ui';
|
||||
import { fetchLists } from 'soapbox/actions/lists';
|
||||
import List, { ListItem } from 'soapbox/components/list';
|
||||
import { Card, Column, HStack, Icon, Spinner, Stack } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
import NewListForm from './components/new-list-form';
|
||||
@ -17,12 +14,6 @@ import type { RootState } from 'soapbox/store';
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||
subheading: { id: 'lists.subheading', defaultMessage: 'Your lists' },
|
||||
add: { id: 'lists.new.create', defaultMessage: 'Add list' },
|
||||
deleteHeading: { id: 'confirmations.delete_list.heading', defaultMessage: 'Delete list' },
|
||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||
deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' },
|
||||
editList: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
||||
deleteList: { id: 'lists.delete', defaultMessage: 'Delete list' },
|
||||
});
|
||||
|
||||
const getOrderedLists = createSelector([(state: RootState) => state.lists], lists => {
|
||||
@ -51,49 +42,34 @@ const Lists: React.FC = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const handleEditClick = (id: number) => (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
dispatch(openModal('LIST_EDITOR', { listId: id }));
|
||||
};
|
||||
|
||||
const handleDeleteClick = (id: number) => (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
heading: intl.formatMessage(messages.deleteHeading),
|
||||
message: intl.formatMessage(messages.deleteMessage),
|
||||
confirm: intl.formatMessage(messages.deleteConfirm),
|
||||
onConfirm: () => {
|
||||
dispatch(deleteList(id));
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.lists' defaultMessage="You don't have any lists yet. When you create one, it will show up here." />;
|
||||
|
||||
return (
|
||||
<Column label={intl.formatMessage(messages.heading)}>
|
||||
<div className='space-y-4'>
|
||||
<Stack space={4}>
|
||||
<NewListForm />
|
||||
|
||||
<ScrollableList
|
||||
scrollKey='lists'
|
||||
emptyMessage={emptyMessage}
|
||||
itemClassName='py-2'
|
||||
>
|
||||
{lists.map((list: any) => (
|
||||
<Link key={list.id} to={`/list/${list.id}`} className='flex items-center gap-1.5 rounded-lg p-2 text-gray-900 hover:bg-gray-100 dark:text-gray-100 dark:hover:bg-gray-800'>
|
||||
<Icon src={require('@tabler/icons/outline/list.svg')} />
|
||||
<span className='grow'>
|
||||
{list.title}
|
||||
</span>
|
||||
<IconButton iconClassName='h-5 w-5 text-gray-700 hover:text-gray-800 dark:text-gray-600 dark:hover:text-gray-500' src={require('@tabler/icons/outline/pencil.svg')} onClick={handleEditClick(list.id)} title={intl.formatMessage(messages.editList)} />
|
||||
<IconButton iconClassName='h-5 w-5 text-gray-700 hover:text-gray-800 dark:text-gray-600 dark:hover:text-gray-500' src={require('@tabler/icons/outline/trash.svg')} onClick={handleDeleteClick(list.id)} title={intl.formatMessage(messages.deleteList)} />
|
||||
</Link>
|
||||
))}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
{lists.isEmpty() ? (
|
||||
<Card variant='rounded' size='lg'>
|
||||
{emptyMessage}
|
||||
</Card>
|
||||
) : (
|
||||
<List>
|
||||
{lists.map((list: any) => (
|
||||
<ListItem
|
||||
key={list.id}
|
||||
to={`/list/${list.id}`}
|
||||
label={
|
||||
<HStack alignItems='center' space={2}>
|
||||
<Icon src={require('@tabler/icons/outline/list.svg')} size={20} />
|
||||
<span>{list.title}</span>
|
||||
</HStack>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
)}
|
||||
</Stack>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
||||
@ -6,7 +6,6 @@ import { addToMentions, removeFromMentions } from 'soapbox/actions/compose';
|
||||
import { useAccount } from 'soapbox/api/hooks';
|
||||
import AccountComponent from 'soapbox/components/account';
|
||||
import IconButton from 'soapbox/components/icon-button';
|
||||
import { HStack } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useCompose } from 'soapbox/hooks';
|
||||
|
||||
const messages = defineMessages({
|
||||
@ -48,12 +47,9 @@ const Account: React.FC<IAccount> = ({ composeId, accountId, author }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<HStack space={1} alignItems='center' justifyContent='between' className='p-2.5'>
|
||||
<div className='w-full'>
|
||||
<AccountComponent account={account} withRelationship={false} withLinkToProfile={false} />
|
||||
</div>
|
||||
{!author && button}
|
||||
</HStack>
|
||||
<div className='p-2'>
|
||||
<AccountComponent account={account} withRelationship={false} withLinkToProfile={false} action={author ? undefined : button} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user