Merge branch 'tag-improvements' into 'develop'

Tag improvements

See merge request soapbox-pub/soapbox!2458
environments/review-develop-3zknud/deployments/3241
Chewbacca 2023-04-24 12:59:13 +00:00
commit b6a5c56859
10 zmienionych plików z 78 dodań i 46 usunięć

Wyświetl plik

@ -248,6 +248,9 @@ const expandListTimeline = (id: string, { maxId }: Record<string, any> = {}, don
const expandGroupTimeline = (id: string, { maxId }: Record<string, any> = {}, done = noOp) =>
expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done);
const expandGroupTimelineFromTag = (id: string, tagName: string, { maxId }: Record<string, any> = {}, done = noOp) =>
expandTimeline(`group:tags:${id}:${tagName}`, `/api/v1/timelines/group/${id}/tags/${tagName}`, { max_id: maxId }, done);
const expandGroupMediaTimeline = (id: string | number, { maxId }: Record<string, any> = {}) =>
expandTimeline(`group:${id}:media`, `/api/v1/timelines/group/${id}`, { max_id: maxId, only_media: true, limit: 40, with_muted: true });
@ -350,6 +353,7 @@ export {
expandAccountMediaTimeline,
expandListTimeline,
expandGroupTimeline,
expandGroupTimelineFromTag,
expandGroupMediaTimeline,
expandHashtagTimeline,
expandTimelineRequest,

Wyświetl plik

@ -39,8 +39,6 @@ const GroupTagListItem = (props: IGroupMemberListItem) => {
const { updateGroupTag } = useUpdateGroupTag(group.id, tag.id);
const isOwner = group.relationship?.role === GroupRoles.OWNER;
const isAdmin = group.relationship?.role === GroupRoles.ADMIN;
const canEdit = isOwner || isAdmin;
const toggleVisibility = () => {
updateGroupTag({
@ -123,16 +121,16 @@ const GroupTagListItem = (props: IGroupMemberListItem) => {
return (
<HStack alignItems='center' justifyContent='between'>
<Link to={`/groups/${group.id}/tag/${tag.id}`} className='group grow'>
<Link to={`/group/${group.slug}/tag/${tag.id}`} className='group grow'>
<Stack>
<Text
weight='bold'
theme={(tag.visible || !canEdit) ? 'default' : 'subtle'}
theme={(tag.visible || !isOwner) ? 'default' : 'subtle'}
className='group-hover:underline'
>
#{tag.name}
</Text>
<Text size='sm' theme={(tag.visible || !canEdit) ? 'muted' : 'subtle'}>
<Text size='sm' theme={(tag.visible || !isOwner) ? 'muted' : 'subtle'}>
{intl.formatMessage(messages.total)}:
{' '}
<Text size='sm' theme='inherit' weight='semibold' tag='span'>
@ -142,7 +140,7 @@ const GroupTagListItem = (props: IGroupMemberListItem) => {
</Stack>
</Link>
{canEdit ? (
{isOwner ? (
<HStack alignItems='center' space={2}>
{tag.visible ? (
renderPinIcon()

Wyświetl plik

@ -1,28 +1,66 @@
import React from 'react';
import React, { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { Column } from 'soapbox/components/ui';
import { expandGroupTimelineFromTag } from 'soapbox/actions/timelines';
import { Column, Icon, Stack, Text } from 'soapbox/components/ui';
import { useAppDispatch } from 'soapbox/hooks';
import { useGroup, useGroupTag } from 'soapbox/hooks/api';
type RouteParams = { id: string, groupId: string };
import Timeline from '../ui/components/timeline';
type RouteParams = { tagId: string, groupId: string };
interface IGroupTimeline {
params: RouteParams
}
const GroupTagTimeline: React.FC<IGroupTimeline> = (props) => {
const dispatch = useAppDispatch();
const groupId = props.params.groupId;
const tagId = props.params.id;
const tagId = props.params.tagId;
const { group } = useGroup(groupId);
const { tag } = useGroupTag(tagId);
const { tag, isLoading } = useGroupTag(tagId);
if (!group) {
const handleLoadMore = (maxId: string) => {
dispatch(expandGroupTimelineFromTag(groupId, tag?.name as string, { maxId }));
};
useEffect(() => {
if (tag?.name) {
dispatch(expandGroupTimelineFromTag(groupId, tag?.name));
}
}, [groupId, tag]);
if (isLoading || !tag || !group) {
return null;
}
return (
<Column label={`#${tag}`}>
{/* TODO */}
<Column label={`#${tag.name}`}>
<Timeline
scrollKey='group_timeline'
timelineId={`group:tags:${groupId}:${tag.name}`}
onLoadMore={handleLoadMore}
divideType='border'
showGroup={false}
emptyMessageCard={false}
emptyMessage={
<Stack space={4} className='py-6' justifyContent='center' alignItems='center'>
<div className='rounded-full bg-gray-200 p-4 dark:bg-gray-800'>
<Icon
src={require('@tabler/icons/message-2.svg')}
className='h-6 w-6 text-gray-600'
/>
</div>
<Text theme='muted'>
<FormattedMessage id='empty_column.group' defaultMessage='There are no posts in this group yet.' />
</Text>
</Stack>
}
/>
</Column>
);
};

Wyświetl plik

@ -20,7 +20,7 @@ const GroupGridItem = forwardRef((props: IGroup, ref: React.ForwardedRef<HTMLDiv
return (
<div
key={group.id}
className='relative flex shrink-0 flex-col space-y-2 px-0.5'
className='relative flex shrink-0 flex-col space-y-2 px-1'
style={{
width,
}}
@ -39,7 +39,11 @@ const GroupGridItem = forwardRef((props: IGroup, ref: React.ForwardedRef<HTMLDiv
/>
)}
<Stack justifyContent='end' className='z-10 p-4 text-white' space={3}>
<div
className='absolute inset-x-0 bottom-0 flex justify-center rounded-b-lg bg-gradient-to-t from-gray-900 to-transparent pb-8 pt-12 transition-opacity duration-500'
/>
<Stack justifyContent='end' className='p-4 text-white' space={3}>
<GroupAvatar
group={group}
size={44}
@ -60,10 +64,6 @@ const GroupGridItem = forwardRef((props: IGroup, ref: React.ForwardedRef<HTMLDiv
</HStack>
</Stack>
</Stack>
<div
className='absolute inset-x-0 bottom-0 z-0 flex justify-center rounded-b-lg bg-gradient-to-t from-gray-900 to-transparent pb-8 pt-12 transition-opacity duration-500'
/>
</Stack>
</Link>

Wyświetl plik

@ -53,7 +53,7 @@ const PopularGroups = () => {
{isFetching ? (
new Array(4).fill(0).map((_, idx) => (
<div
className='relative flex shrink-0 flex-col space-y-2 px-0.5'
className='relative flex shrink-0 flex-col space-y-2 px-1'
style={{ width: width || 'auto' }}
key={idx}
>

Wyświetl plik

@ -46,10 +46,8 @@ export default (props: Props) => {
</div>
), []);
const renderGroupGrid = useCallback((group: Group, index: number) => (
<div className='pb-4'>
<GroupGridItem group={group} />
</div>
const renderGroupGrid = useCallback((group: Group) => (
<GroupGridItem group={group} />
), []);
return (
@ -79,10 +77,10 @@ export default (props: Props) => {
<VirtuosoGrid
useWindowScroll
data={groups}
itemContent={(index, group) => renderGroupGrid(group, index)}
itemContent={(_index, group) => renderGroupGrid(group)}
components={{
Item: (props) => (
<div {...props} className='w-1/2 flex-none' />
<div {...props} className='w-1/2 flex-none pb-4 [&:nth-last-of-type(-n+2)]:pb-0' />
),
List: GridList,
}}

Wyświetl plik

@ -46,10 +46,8 @@ const Popular: React.FC = () => {
</div>
), []);
const renderGroupGrid = useCallback((group: Group, index: number) => (
<div className='pb-4'>
<GroupGridItem group={group} />
</div>
const renderGroupGrid = useCallback((group: Group) => (
<GroupGridItem group={group} />
), []);
return (
@ -73,10 +71,10 @@ const Popular: React.FC = () => {
<VirtuosoGrid
useWindowScroll
data={groups}
itemContent={(index, group) => renderGroupGrid(group, index)}
itemContent={(_index, group) => renderGroupGrid(group)}
components={{
Item: (props) => (
<div {...props} className='w-1/2 flex-none' />
<div {...props} className='w-1/2 flex-none pb-4 [&:nth-last-of-type(-n+2)]:pb-0' />
),
List: GridList,
}}

Wyświetl plik

@ -46,10 +46,8 @@ const Suggested: React.FC = () => {
</div>
), []);
const renderGroupGrid = useCallback((group: Group, index: number) => (
<div className='pb-4'>
<GroupGridItem group={group} />
</div>
const renderGroupGrid = useCallback((group: Group) => (
<GroupGridItem group={group} />
), []);
return (
@ -73,10 +71,10 @@ const Suggested: React.FC = () => {
<VirtuosoGrid
useWindowScroll
data={groups}
itemContent={(index, group) => renderGroupGrid(group, index)}
itemContent={(_index, group) => renderGroupGrid(group)}
components={{
Item: (props) => (
<div {...props} className='w-1/2 flex-none' />
<div {...props} className='w-1/2 flex-none pb-4 [&:nth-last-of-type(-n+2)]:pb-0' />
),
List: GridList,
}}

Wyświetl plik

@ -50,10 +50,8 @@ const Tag: React.FC<ITag> = (props) => {
</div>
), []);
const renderGroupGrid = useCallback((group: Group, index: number) => (
<div className='pb-4'>
<GroupGridItem group={group} />
</div>
const renderGroupGrid = useCallback((group: Group) => (
<GroupGridItem group={group} />
), []);
if (isLoading || !tag) {
@ -100,10 +98,10 @@ const Tag: React.FC<ITag> = (props) => {
<VirtuosoGrid
useWindowScroll
data={groups}
itemContent={(index, group) => renderGroupGrid(group, index)}
itemContent={(_index, group) => renderGroupGrid(group)}
components={{
Item: (props) => (
<div {...props} className='w-1/2 flex-none' />
<div {...props} className='w-1/2 flex-none pb-4 [&:nth-last-of-type(-n+2)]:pb-0' />
),
List: GridList,
}}

Wyświetl plik

@ -327,7 +327,7 @@ const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = ({ children }) =>
{features.groups && <WrappedRoute path='/groups/:groupId/posts/:statusId' exact page={StatusPage} component={Status} content={children} />}
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tags' exact page={GroupPage} component={GroupTagsSlug} content={children} />}
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tag/:id' exact page={GroupsPendingPage} component={GroupTagTimelineSlug} content={children} />}
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tag/:tagId' exact page={GroupsPendingPage} component={GroupTagTimelineSlug} content={children} />}
{features.groups && <WrappedRoute path='/group/:groupSlug' exact page={GroupPage} component={GroupTimelineSlug} content={children} />}
{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} />}